Compare commits

...

174 Commits
v4.5.2 ... v4.6

Author SHA1 Message Date
David Cook
917079931e Merge pull request #12778 from chahmedejaz/bugfix/12596-fix-annoying-oc-warning-display
[BUU] Fix Messy flash notifications on new products page
2024-08-16 10:29:43 +10:00
Ahmed Ejaz
46e54f48c9 12596: keep flash[:notice] check 2024-08-15 14:50:32 +05:00
Konrad
059dceb304 Merge pull request #12735 from chahmedejaz/bugfix/12698-fix-products-stateful-navigataion
Fix 'Back to products list' stateful navigation
2024-08-15 10:43:13 +02:00
David Cook
f0abe650f6 Update all locales with the latest Transifex translations 2024-08-15 16:56:59 +10:00
Ahmed Ejaz
282df9859e 12596 - fix specs
- As we are only showing the oc warning once now we need these steps where we are dismissing the oc warning after each navigation. Just keeping the first notice dismiss after login
2024-08-15 05:59:17 +05:00
Ahmed Ejaz
3474c60f4c 12596 - fix annoying oc warning display
- such that it only displays once per user session
2024-08-15 05:59:17 +05:00
Konrad
503148b13b Merge pull request #12653 from wandji20/wb-OFN-11613
Add warning modal to order cycle with attached schedule general setting form [OFN-11613]
2024-08-14 18:14:33 +02:00
Konrad
8442c7d334 Merge pull request #12749 from wandji20/wb-OFN-11636
Remove awesome nested set gem and dependencies [OFN-11636]
2024-08-14 17:43:11 +02:00
Ahmed Ejaz
b14cd08990 12698 - keep old UI URL as it is 2024-08-13 14:23:39 +05:00
David Cook
50ebfe412c Merge pull request #12764 from openfoodfoundation/dependabot/npm_and_yarn/js-big-decimal-2.1.0
Bump js-big-decimal from 2.0.7 to 2.1.0
2024-08-13 11:31:05 +10:00
David Cook
e59ab6b2d9 Merge pull request #12763 from openfoodfoundation/dependabot/npm_and_yarn/mrujs-1.0.1
Bump mrujs from 1.0.0 to 1.0.1
2024-08-13 11:28:24 +10:00
Gaetan Craig-Riou
417d39f684 Merge pull request #12757 from EdwardLi-coder/upload_artifact_v3_to_v4
update artifact v3 to v4
2024-08-13 09:35:04 +10:00
wandji20
35169f66dc Include order cycle spec for non-simple cycles [OFN-11613] 2024-08-12 23:16:04 +01:00
Ahmed Ejaz
64568f4aa4 Revert "test artifact upload from different nodes at the same time"
This reverts commit 8a2be468fc.
2024-08-13 00:57:58 +05:00
Ahmed Ejaz
734aebbaaa update uploaded artifact names to be different 2024-08-13 00:42:59 +05:00
Ahmed Ejaz
8a2be468fc test artifact upload from different nodes at the same time 2024-08-13 00:22:10 +05:00
Gaetan Craig-Riou
feb429fee7 Fix typo 2024-08-12 18:47:16 +01:00
wandji20
b75101f24f Fix rebase issue [OFN-11636] 2024-08-12 18:47:16 +01:00
wandji20
1e71db9315 Remove permalinmk from taxons [OFN-11636] 2024-08-12 18:47:16 +01:00
wandji20
82b742608d Remove jquery/js.tree plugin [OFN-11636] 2024-08-12 18:47:16 +01:00
Maikel Linke
49aa9e0768 Make taxonomy migration reversible 2024-08-12 18:47:16 +01:00
wandji20
a85cfab506 Remove awesome nested set gem and dependencies [OFN-11636] 2024-08-12 18:47:16 +01:00
Ahmed Ejaz
e2e3aa9281 12698: add specs 2024-08-12 15:16:47 +05:00
dependabot[bot]
6bd0f2c088 Bump js-big-decimal from 2.0.7 to 2.1.0
Bumps [js-big-decimal](https://github.com/royNiladri/js-big-decimal) from 2.0.7 to 2.1.0.
- [Release notes](https://github.com/royNiladri/js-big-decimal/releases)
- [Commits](https://github.com/royNiladri/js-big-decimal/compare/v2.0.7...v2.1.0)

---
updated-dependencies:
- dependency-name: js-big-decimal
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 09:26:19 +00:00
dependabot[bot]
ab2968ffd2 Bump mrujs from 1.0.0 to 1.0.1
Bumps [mrujs](https://github.com/KonnorRogers/mrujs) from 1.0.0 to 1.0.1.
- [Changelog](https://github.com/KonnorRogers/mrujs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KonnorRogers/mrujs/compare/v1.0.0...v1.0.1)

---
updated-dependencies:
- dependency-name: mrujs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 09:25:57 +00:00
EdwardLi-coder
83bf19084b remove fail test 2024-08-12 16:29:52 +08:00
Edward Li
40a59c988b Merge branch 'openfoodfoundation:master' into upload_artifact_v3_to_v4 2024-08-12 16:17:53 +08:00
Gaetan Craig-Riou
43d983cac2 Remoce left over console.log 2024-08-12 09:05:48 +01:00
wandji20
ad3e772944 Refactor and update order cycle form controller [OFN-11613] 2024-08-12 09:05:48 +01:00
wandji20
6a438a07fe Add stimulus controler to monitor order cycle status message data attribute change and trigger warning modal [OFN-11613] 2024-08-12 09:05:48 +01:00
wandji20
ea238829a8 Revert front end validation and implement backend validation for changes in datetime order cycle values [OFN-11613] 2024-08-12 09:05:48 +01:00
wandji20
91fddeaa8b Fix failing spec [OFN-11613] 2024-08-12 09:05:48 +01:00
wandji20
0de8a90b14 Add warning modal to order cycle with attached schedule general setting form [OFN-11613] 2024-08-12 09:05:48 +01:00
EdwardLi-coder
9fe128d494 add fail test 2024-08-12 16:04:22 +08:00
David Cook
193e17b625 Merge pull request #12759 from EdwardLi-coder/admin_style_v3-for-75%
[BUU] Activate admin_style_v3 for 75% of users
2024-08-12 17:59:25 +10:00
David Cook
6ad03e6d5c Remove comment 2024-08-12 17:49:09 +10:00
Gaetan Craig-Riou
1f55ff4b72 Merge pull request #12729 from mkllnk/fdc-update
Remove now unneeded FDC compatibility code from product import
2024-08-12 11:14:44 +10:00
EdwardLi-coder
be13d43e0c delete Archive failed tests screenshots 2024-08-11 00:20:18 +08:00
EdwardLi-coder
af7b663334 update admin_style_v3-for-75% 2024-08-10 23:55:58 +08:00
EdwardLi-coder
da24638079 update artifact v3 to v4 2024-08-10 22:04:17 +08:00
Maikel Linke
8ab1cbe600 Update all locales with the latest Transifex translations 2024-08-09 15:13:33 +10:00
Maikel
cad0245510 Merge pull request #12754 from mkllnk/hu-mini-magick-fix
Load MiniMagick before use
2024-08-09 15:10:51 +10:00
Maikel Linke
93edf4e3ad Load MiniMagick before use
We only reference MiniMagick when rescuing errors but when it's not
loaded, that code fails to find the error class itself to apply the
rescue block.

The rescue block is covered by a spec but the code passes there as
MiniMagick is loaded.

We can see this error only in development, staging and production.
2024-08-09 14:25:29 +10:00
Maikel
caa2764317 Merge pull request #12752 from openfoodfoundation/dependabot/npm_and_yarn/floating-ui/dom-1.6.10
Bump @floating-ui/dom from 1.6.9 to 1.6.10
2024-08-09 09:48:14 +10:00
Maikel
4f1e6382c9 Merge pull request #12753 from openfoodfoundation/dependabot/npm_and_yarn/trix-2.1.5
Bump trix from 2.1.4 to 2.1.5
2024-08-09 09:47:37 +10:00
Maikel
54d33ca103 Merge pull request #12748 from chahmedejaz/bugfix/12739-fix-number-rounding-with-hu-locale
Fix NoMethodError in Admin::ProductsV3#index - Only when using the hu.yml locale
2024-08-09 09:44:48 +10:00
Ahmed Ejaz
787205dcca Merge branch 'master' into bugfix/12739-fix-number-rounding-with-hu-locale 2024-08-09 01:59:50 +05:00
Filipe
fcb0996a76 Merge pull request #12713 from dacook/buu/style-fixes2
[BUU] Style fixes
2024-08-08 17:31:20 +01:00
Filipe
76d874d5f9 Merge pull request #12710 from chahmedejaz/bugfix/12705-fix-products-index-page
[BUU] Fixes Products Page ActionView::Template::Error
2024-08-08 16:20:26 +01:00
Rachel Arnould
81711e4c43 Merge pull request #12721 from dacook/connected-apps-settings-12549
New settings screen to activate each connected app type
2024-08-08 16:56:33 +02:00
dependabot[bot]
e64f60a166 Bump trix from 2.1.4 to 2.1.5
Bumps [trix](https://github.com/basecamp/trix) from 2.1.4 to 2.1.5.
- [Release notes](https://github.com/basecamp/trix/releases)
- [Commits](https://github.com/basecamp/trix/compare/v2.1.4...v2.1.5)

---
updated-dependencies:
- dependency-name: trix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-08 09:58:22 +00:00
dependabot[bot]
24bc56781b Bump @floating-ui/dom from 1.6.9 to 1.6.10
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.6.9 to 1.6.10.
- [Release notes](https://github.com/floating-ui/floating-ui/releases)
- [Changelog](https://github.com/floating-ui/floating-ui/blob/master/packages/dom/CHANGELOG.md)
- [Commits](https://github.com/floating-ui/floating-ui/commits/@floating-ui/dom@1.6.10/packages/dom)

---
updated-dependencies:
- dependency-name: "@floating-ui/dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-08 09:58:08 +00:00
Ahmed Ejaz
6757c8df74 12739 - fix number_with_precision method 2024-08-07 18:54:35 +05:00
Ahmed Ejaz
647a384561 12705 - add specs for updating invalid unit_value 2024-08-07 16:59:10 +05:00
Maikel Linke
ec828c335d Remove superfluous FDC-specific request class 2024-08-07 15:09:05 +10:00
Maikel Linke
6d03a8ddf3 Test that the FDC is now complying with the DFC 2024-08-07 15:09:05 +10:00
David Cook
05878fcbb8 Merge pull request #12747 from mkllnk/flaky-dfc-spec
Stabilise flaky spec with unique taxons
2024-08-07 15:02:57 +10:00
Maikel Linke
fd8973862e Stabilise flaky spec with unique taxons
The test was creating two "Soft Drinks" taxons and it was random which
one was applied to a new product. Changing one taxon to a different one
removes the ambiguity.
2024-08-07 13:50:51 +10:00
David Cook
40c77948b9 Show success message
I'm not sure, but I assume that Config.set will raise an exception if it failed.
2024-08-07 10:31:06 +10:00
David Cook
a95aa1b3e9 Submit blank value if nothing selected
If a checkbox is not selected, the browser does not submit it at all.
2024-08-07 10:30:45 +10:00
Gaetan Craig-Riou
706eb737b1 Merge pull request #12742 from openfoodfoundation/dependabot/npm_and_yarn/floating-ui/dom-1.6.9
Bump @floating-ui/dom from 1.6.8 to 1.6.9
2024-08-07 10:09:09 +10:00
Gaetan Craig-Riou
c31758d347 Merge pull request #12741 from openfoodfoundation/dependabot/npm_and_yarn/jquery-ui-1.14.0
Bump jquery-ui from 1.13.3 to 1.14.0
2024-08-07 10:08:17 +10:00
Gaetan Craig-Riou
6139ba3015 Merge pull request #12738 from mkllnk/flaky-exchange-id
Stabilise spec by not relying on record ids
2024-08-07 09:41:00 +10:00
Konrad
256d5ba61c Merge pull request #12725 from wandji20/wb-OFN-12280
(Fix) chore(deps): bump invisible_captcha from 2.2.0 to 2.3.0
2024-08-06 15:04:38 +02:00
Konrad
cb42e7e119 Merge pull request #12671 from wandji20/wb-OFN-12591
Ensure product category error message is shown when creating new product [OFN-12591]
2024-08-06 14:09:59 +02:00
dependabot[bot]
566d310880 Bump @floating-ui/dom from 1.6.8 to 1.6.9
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.6.8 to 1.6.9.
- [Release notes](https://github.com/floating-ui/floating-ui/releases)
- [Changelog](https://github.com/floating-ui/floating-ui/blob/master/packages/dom/CHANGELOG.md)
- [Commits](https://github.com/floating-ui/floating-ui/commits/@floating-ui/dom@1.6.9/packages/dom)

---
updated-dependencies:
- dependency-name: "@floating-ui/dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-06 09:39:16 +00:00
dependabot[bot]
5cdce35ee8 Bump jquery-ui from 1.13.3 to 1.14.0
Bumps [jquery-ui](https://github.com/jquery/jquery-ui) from 1.13.3 to 1.14.0.
- [Release notes](https://github.com/jquery/jquery-ui/releases)
- [Commits](https://github.com/jquery/jquery-ui/compare/1.13.3...1.14.0)

---
updated-dependencies:
- dependency-name: jquery-ui
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-06 09:38:57 +00:00
David Cook
ffe3f12a23 Move class definition inside migration 2024-08-06 11:26:03 +02:00
David Cook
bd48a982fb Set connected apps as enabled if any
Could have easily done this manually, but this makes the transition smoother.

BTW I tested each case manually, didn't seem worth writing a spec.
2024-08-06 11:26:03 +02:00
David Cook
5d732d80a6 Add connected apps settings screen
I considered adding a request spec, but figured it still doesnt' test the form, so better to use a full system spec.
2024-08-06 11:26:03 +02:00
David Cook
254e11aa36 Use whitelist
It wasn't really necessary, but I'm going to need this list in a moment, so we might as well use it.
Also it allows us to ensure the options are listed in a certain order.

Also maybe it will help protect against corrupt preferences.
2024-08-06 11:26:03 +02:00
David Cook
4223b36bc3 Only show enabled connected app types
The preference will be set from the admin interface in a new commit

It would be nice if we had an array/list type for preferences. Probably not too hard to implement, but this will do.
2024-08-06 11:26:03 +02:00
David Cook
fcea437d7e Only show connected apps in enterprise settings, if system setting is enabled 2024-08-06 11:26:03 +02:00
David Cook
8716b75d3d Merge pull request #12722 from openfoodfoundation/dependabot/npm_and_yarn/karma-6.4.4
Bump karma from 6.4.3 to 6.4.4
2024-08-06 15:28:06 +10:00
Maikel Linke
e055b8b16c Stabilise spec by not relying on record ids
A spec was referring to and input id:

```
"order_cycle_incoming_exchange_0_variants_#{new_product.variants.first.id}"
```

But sometimes the exchange would have the id 1 instead of 0 and the test
would fail. Instead I opted to select the field by text visible to the
user.
2024-08-06 12:31:54 +10:00
Maikel
f5875e4c0b Merge pull request #12667 from cyrillefr/FixRailsRootPathnameMethods
Fixes Rails/RootPathnameMethods offense
2024-08-06 11:02:28 +10:00
dependabot[bot]
56d23c172c Bump karma from 6.4.3 to 6.4.4
Bumps [karma](https://github.com/karma-runner/karma) from 6.4.3 to 6.4.4.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v6.4.3...v6.4.4)

---
updated-dependencies:
- dependency-name: karma
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-06 01:02:06 +00:00
Maikel
19bb40d1d3 Merge pull request #12736 from openfoodfoundation/dependabot/npm_and_yarn/jasmine-core-5.2.0
Bump jasmine-core from 5.1.2 to 5.2.0
2024-08-06 10:59:33 +10:00
Maikel
4169a956c9 Merge pull request #12737 from openfoodfoundation/dependabot/npm_and_yarn/trix-2.1.4
Bump trix from 2.1.3 to 2.1.4
2024-08-06 10:58:28 +10:00
filipefurtad0
d54dbdfe2d Update all locales with the latest Transifex translations 2024-08-05 11:33:39 +01:00
dependabot[bot]
fed2ae9a93 Bump trix from 2.1.3 to 2.1.4
Bumps [trix](https://github.com/basecamp/trix) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/basecamp/trix/releases)
- [Commits](https://github.com/basecamp/trix/compare/2.1.3...v2.1.4)

---
updated-dependencies:
- dependency-name: trix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 09:57:36 +00:00
dependabot[bot]
f00b2f0397 Bump jasmine-core from 5.1.2 to 5.2.0
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 5.1.2 to 5.2.0.
- [Release notes](https://github.com/jasmine/jasmine/releases)
- [Changelog](https://github.com/jasmine/jasmine/blob/main/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine/compare/v5.1.2...v5.2.0)

---
updated-dependencies:
- dependency-name: jasmine-core
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 09:57:26 +00:00
Ahmed Ejaz
c101c4e42f 12698 - fix 'go back to products' stateful navigation 2024-08-05 13:51:59 +05:00
Gaetan Craig-Riou
11ba33d7f4 Merge pull request #12696 from openfoodfoundation/dependabot/npm_and_yarn/floating-ui/dom-1.6.8
Bump @floating-ui/dom from 1.6.7 to 1.6.8
2024-08-05 16:38:03 +10:00
dependabot[bot]
8e663dac3f Bump @floating-ui/dom from 1.6.7 to 1.6.8
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.6.7 to 1.6.8.
- [Release notes](https://github.com/floating-ui/floating-ui/releases)
- [Changelog](https://github.com/floating-ui/floating-ui/blob/master/packages/dom/CHANGELOG.md)
- [Commits](https://github.com/floating-ui/floating-ui/commits/@floating-ui/dom@1.6.8/packages/dom)

---
updated-dependencies:
- dependency-name: "@floating-ui/dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 04:38:50 +00:00
Gaetan Craig-Riou
df0795acf1 Merge pull request #12689 from openfoodfoundation/dependabot/npm_and_yarn/hotwired/turbo-8.0.5
Bump @hotwired/turbo from 8.0.4 to 8.0.5
2024-08-05 14:36:05 +10:00
Gaetan Craig-Riou
7e1af9e04b Merge pull request #12723 from johansenja/optimise-shops-page
Preload enterprise logos and promo images for /shops page
2024-08-05 13:54:20 +10:00
Gaetan Craig-Riou
4805adec42 Merge pull request #12730 from openfoodfoundation/revert-12665-wb-OFN-12532
Revert "Pluralize admin products search result [OFN-12532]"
2024-08-05 10:29:52 +10:00
Filipe
7939bf8038 Revert "Pluralize admin products search result [OFN-12532]" 2024-08-05 10:03:58 +10:00
Ahmed Ejaz
d4e0b2ab51 12705 - fix specs 2024-08-04 18:20:15 +05:00
Ahmed Ejaz
1014a50aff 12705 - incorporate old UI behavior
- if unit_value is not present and unit_description then display unit_description only.
- if both are not present then display empty fields
2024-08-04 17:47:02 +05:00
filipefurtad0
0afbdf157e Update all locales with the latest Transifex translations 2024-08-02 11:42:59 +01:00
Filipe
5012c52438 Merge pull request #12711 from cillian/wider-item-column-on-invoice-pdf
Make Item column wider and tax and quantity columns narrower in invoice PDF
2024-08-02 10:20:24 +01:00
Maikel
615a81c55d Merge pull request #12728 from mkllnk/flaky-order-cycle-spec
Fix flaky spec with fixed order of products
2024-08-02 14:39:42 +10:00
Maikel Linke
99b31d05cb Fix flaky spec with fixed order of products 2024-08-02 14:26:54 +10:00
Konrad
1a72b5b227 Merge pull request #12563 from abdulazizali77/bugfix/11326-incoming-exchange-per-item-calculator
Display only per_item fees for oc incoming exchange #11326
2024-08-02 03:11:27 +02:00
wandji20
a1aea54405 Disable recaptcha spiner check in test environment [OFN-12280] 2024-08-01 21:43:51 +01:00
dependabot[bot]
e01354e863 chore(deps): bump invisible_captcha from 2.2.0 to 2.3.0
Bumps [invisible_captcha](https://github.com/markets/invisible_captcha) from 2.2.0 to 2.3.0.
- [Changelog](https://github.com/markets/invisible_captcha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/markets/invisible_captcha/compare/v2.2.0...v2.3.0)

---
updated-dependencies:
- dependency-name: invisible_captcha
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-01 17:33:03 +01:00
Joseph Johansen
ffe4603f2f Preload enterprise logos and promo images for shops page 2024-08-01 14:10:53 +01:00
wandji20
ebc794194f Add product spec when supplier is empty and remove error status code from product create action [OFN-12591] 2024-08-01 09:03:26 +01:00
wandji20
287f65ec8e Ensure product category error message is shown when creating new product [OFN-12591] 2024-08-01 08:58:54 +01:00
David Cook
1288592d58 Merge pull request #12715 from rioug/add-request-id-log
Add request_id to logs for production and staging
2024-08-01 10:01:25 +10:00
David Cook
0836d844a6 Merge pull request #12677 from openfoodfoundation/dependabot/npm_and_yarn/trix-2.1.3
Bump trix from 2.1.2 to 2.1.3
2024-08-01 09:49:07 +10:00
David Cook
96355a1ed4 Merge pull request #12719 from dacook/ActivateAdminStyleV3For50PcUsers
[BUU] Activate admin_style_v3 for ~50% of users
2024-08-01 09:24:33 +10:00
Filipe
ce44f19b4a Merge pull request #12704 from cyrillefr/FilteringProductBySupplierPropertyBreaksWhenEnterpriseHasCustomSortingByCategorySet
Fixes 422 error due to bad sql building
2024-07-31 19:45:09 +01:00
Filipe
6c214543ad Merge pull request #12690 from wandji20/wb-OFN-12666
Require variant category and supplier when creating new product variants [OFN-12666]
2024-07-31 19:28:31 +01:00
Filipe
8b1713d169 Merge pull request #12665 from wandji20/wb-OFN-12532
Pluralize admin products search result [OFN-12532]
2024-07-31 18:55:53 +01:00
David Cook
587ce5ad9d Activate admin_style_v3 for 50% of users 2024-07-31 16:55:12 +10:00
Rachel Arnould
f51705cb57 Merge pull request #12676 from dacook/add-affiliate_sales_data-connected_app-12550
Add "Affiliate Sales Data" connected app option
2024-07-30 16:14:27 +02:00
wandji20
55df9416cc Add test to check when new variant category and producer is empty [OFN-12666] 2024-07-30 12:09:59 +01:00
wandji20
0376c04ad5 Fix failing specs [OFN-12666] 2024-07-30 12:07:50 +01:00
wandji20
2709479bf2 Require varian t category when creating new product variant [OFN-12666] 2024-07-30 12:07:50 +01:00
David Cook
c5fc621aa4 Use scope to determine which enterprises are ready to be affiliated 2024-07-30 15:21:29 +10:00
Gaetan Craig-Riou
bfd0e7f784 Add request_id to logs for production and staging
It will prepend a request unique id to each log lines, it makes it
easier to debug individual request.
2024-07-30 11:38:46 +10:00
David Cook
ec3c157f1e Add gap between elements
It could be done better, but requires more code cleanup than it's worth.
2024-07-29 15:20:36 +10:00
David Cook
32aacbd2b0 Don't use fixed heights 🔥
Just don't. It makes life hard and doesn't solve the problem properly.

Now, when the content doesn't fit within the screen width, it will flow naturally and not jump up and down all over other elements.
2024-07-29 15:13:30 +10:00
David Cook
655dc92246 Clean up wacky input styles 🔥
Trying to style a pretend input just doesn't work in practice, it resulted in a couple of style issues.
Let's keep it simple,
2024-07-29 15:02:06 +10:00
David Cook
fece8beef5 Style/Send 2024-07-29 14:13:22 +10:00
David Cook
53e3621e04 Merge pull request #12703 from johansenja/fix-rubocop-style-send
Fix rubocop Style/Send group
2024-07-29 14:02:01 +10:00
David Cook
1949839056 Update interpolation variable name
This avoids error 'missing interpolation argument'.
2024-07-29 10:41:11 +10:00
Konrad
00a0006ff2 Merge pull request #12691 from ccozkan/use-vertical-transitions-for-cloning-and-deleting
Use vertical transitions for cloning and deleting products
2024-07-28 18:25:07 +02:00
Konrad
325f9aa6f3 Merge pull request #12664 from wandji20/wb-OFN-12551
Remove SR from clear search button [OFN-12551]
2024-07-28 14:31:08 +02:00
Konrad
95ec5c3c58 Merge pull request #12655 from wandji20/wb-OFN-11513
(Fix) [User->New] Language is displayed twice [OFN-11513]
2024-07-28 13:46:51 +02:00
wandji20
ef87cdb167 Revert changes and use selectable locales for helper local_options [OFN-11513] 2024-07-28 12:52:01 +02:00
wandji20
65d4596f3b Fix failling spec [OFN-11513] 2024-07-28 12:52:01 +02:00
wandji20
a9e295bc11 (Fix) [User->New] Language is displayed twice [OFN-11513] 2024-07-28 12:52:01 +02:00
Abdul Aziz Ali
ac8caf7710 Revert to use .order_cycle_id #11326 2024-07-28 17:57:56 +08:00
Abdul Aziz Ali
8a1e61fd60 Fix incoming_controller_spec. Remove .order_cycle_id usage #11326 2024-07-27 17:54:39 +08:00
Abdul Aziz Ali
baf38b6b30 Only set per_item flag in order_cycle incoming controller #11326 2024-07-27 16:12:26 +08:00
Cillian O'Ruanaidh
3507405dae Make Item column wider and tax and quantity columns narrower in invoice PDF 2024-07-26 15:36:42 +01:00
Filipe
c25fe6ae57 Merge pull request #12654 from wandji20/wb-OFN-112509
Use public contact email at the bottom of order confirmation email [OFN-12509]
2024-07-25 20:14:47 +01:00
Filipe
7bcf3206d8 Merge pull request #12678 from chahmedejaz/bugfix/11640-products-page-broken-URL
Fix URL State management on the Products page
2024-07-25 20:00:49 +01:00
Ahmed Ejaz
e808c7fb2b 12705 - set 1 as default for variant's unit_value 2024-07-25 23:42:03 +05:00
David Cook
df81e8ed35 Add task to connect all enterprises
Example usage:
 rake ofn:enterprises:activate_connected_app_type[affiliate_sales_data]
2024-07-25 21:14:04 +10:00
David Cook
e9d7a0b099 Add User#affiliate_enterprises 2024-07-25 21:14:01 +10:00
David Cook
da7bbcf82f Enable/disable affiliate sales data 2024-07-25 17:06:13 +10:00
David Cook
1742d2807f Add affiliate sales data to form 2024-07-25 17:06:13 +10:00
David Cook
d3c5e2365a Add AffiliateSalesData model
Using namespace subfolder to help organise it and show the inheritance.

Hmm, instead of scopes, we could have different has_many relationships on the Enterprise. Maybe it should be in a concern. We can refactor later I guess.
2024-07-25 17:06:13 +10:00
David Cook
27e53f9dcc Scope spec to section
Because there's going to be a new section with the same button label
2024-07-25 17:06:13 +10:00
David Cook
5d0f55b8c3 Re-organise spec
Best viewed with whitespac ignored.
2024-07-25 17:06:13 +10:00
David Cook
9d89b4726b Move connect logic to model
Then subtypes can override as needed.
2024-07-25 17:06:13 +10:00
David Cook
9b37eacb8d add scope for discover_regen 2024-07-25 17:06:13 +10:00
David Cook
bbe22bbfeb AddTypeToConnectedApps 2024-07-25 17:06:13 +10:00
David Cook
85d5e2ee70 Expect single connected_app record for discover regen 2024-07-25 17:05:42 +10:00
David Cook
9a4051f37b Move discover regen to named partial
To make way for a new type of connected app.

If only we could use [relative partial paths](https://github.com/rails/rails/issues/1143)
2024-07-25 17:05:42 +10:00
cyrillefr
05ed4639b2 Fixes 422 error due to bad sql building
- first part of query use supplier_properties parameter, but not
  second part, that can leads to mismatch between the 2 parts.
  Remove supplier_properties parameter + modify SQL to get it right.
- spec tests category filtering & sorting + producer properties
2024-07-24 21:49:11 +02:00
Abdul Aziz Ali
2bcf84d9a9 Add outgoing exchange scenario spec #11326 2024-07-24 17:38:10 +08:00
Gaetan Craig-Riou
99acf752f4 Update all locales with the latest Transifex translations 2024-07-24 15:34:16 +10:00
Joseph Johansen
5086f2d8b5 Fix rubocop Style/Send group 2024-07-23 14:18:26 +01:00
wandji20
0b46c41ffd Update reply email for order confirmation mail [OFN-12509] 2024-07-23 08:54:06 +01:00
wandji20
4fe3f60009 Use public contact email at the bottom of order confirmation email [OFN-12509] 2024-07-23 08:35:30 +01:00
Gaetan Craig-Riou
dfea0cd805 Merge pull request #12700 from rioug/fix-number-rounding-with-hu-locale
[BUU] fix error 500 on hungary instance
2024-07-23 16:35:48 +10:00
Gaetan Craig-Riou
0f04b2fb10 Fix call to ActiveSupport::NumberHelper.number_to_rounded
When running with :hu locale, call to `number_to_rounded` wiht parameter
precision: nil breaks, adding significant: false fixes the issue
2024-07-23 13:51:32 +10:00
Ahmed Ejaz
a6efad73a8 12551 - add no-cache policy for Turbo cache control 2024-07-22 13:45:01 +05:00
Çağrı Özkan
29d63b0f0f Change slide in animation to appear from top 2024-07-22 06:01:01 +03:00
Çağrı Özkan
25e9fd22d8 Change slide out animation to disappear towards top 2024-07-22 06:01:01 +03:00
wandji20
bb427db66a Add spec for clearing search input when no results is found [OFN-12551] 2024-07-19 14:25:46 +01:00
wandji20
1165b00600 Remove SR from clear search button [OFN-12551] 2024-07-19 14:21:35 +01:00
dependabot[bot]
2d45952611 Bump @hotwired/turbo from 8.0.4 to 8.0.5
Bumps [@hotwired/turbo](https://github.com/hotwired/turbo) from 8.0.4 to 8.0.5.
- [Release notes](https://github.com/hotwired/turbo/releases)
- [Commits](https://github.com/hotwired/turbo/compare/v8.0.4...v8.0.5)

---
updated-dependencies:
- dependency-name: "@hotwired/turbo"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-19 09:58:25 +00:00
Ahmed Ejaz
1af811cf51 11640 - fix per_page issue when the page is changed
- Fix the scenario when per_page is selected as 100 and next page is clicked, then per_page is empty in the request.
- Expected behavior should be that it retains the per_page selected previously
2024-07-17 10:17:06 +05:00
Ahmed Ejaz
1850f298a6 11640 - use turbo navigation 2024-07-17 10:16:52 +05:00
wandji20
80ade22bd6 Pluralize admin products search result [OFN-12532] 2024-07-16 13:10:22 +01:00
dependabot[bot]
4fb458afe0 Bump trix from 2.1.2 to 2.1.3
Bumps [trix](https://github.com/basecamp/trix) from 2.1.2 to 2.1.3.
- [Release notes](https://github.com/basecamp/trix/releases)
- [Commits](https://github.com/basecamp/trix/compare/v2.1.2...2.1.3)

---
updated-dependencies:
- dependency-name: trix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-16 09:30:08 +00:00
cyrillefr
2baf7c0250 Fixex Rails/RootPathnameMethods offense
- Cf. Cop doc at https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsrootpathnamemethods
2024-07-12 14:20:17 +02:00
Gaetan Craig-Riou
29aa3a8059 Remove useless code 2024-07-12 10:34:42 +10:00
Abdul Aziz Ali
718e6765e1 Enterprise fee controller: Add all fees scenario #11326 2024-07-10 19:42:47 +08:00
Abdul Aziz Ali
31d49ee99e Rubocop. Fix simple spec long line #11326 2024-07-10 08:18:00 +08:00
Abdul Aziz Ali
1e08f2713e Remove sleep. Use Capybara select helper #11326 2024-07-10 08:12:19 +08:00
Abdul Aziz Ali
8955972b05 Rubocop. fix formatting #11326 2024-07-09 08:56:54 +08:00
Abdul Aziz Ali
5fe5804b56 Add enterprise fee check in system admin ordercycles simple spec #11326 2024-07-09 08:49:45 +08:00
Abdul Aziz Ali
9d12e55bd7 Add enterprise fees controller spec #11326 2024-06-26 06:36:57 +08:00
Abdul Aziz Ali
b3570991f4 Rubocop. Fix cyclomatic complexity in fees controller #11326 2024-06-26 06:36:42 +08:00
Abdul Aziz Ali
e2aca63fff Rubocop. Change yield_self to then #11326 2024-06-12 08:52:43 +08:00
Abdul Aziz Ali
e537bda9b7 Display only per_item fees for oc incoming exchange #11326
Add per_item param to EnterpriseFee angular service and rails controller
2024-06-12 08:29:34 +08:00
235 changed files with 3099 additions and 7439 deletions

View File

@@ -216,9 +216,9 @@ jobs:
- name: Archive failed tests screenshots
if: failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: failed-tests-screenshots
name: failed-admin-tests-screenshots
path: tmp/capybara/screenshots/*.png
retention-days: 7
if-no-files-found: ignore
@@ -294,9 +294,9 @@ jobs:
- name: Archive failed tests screenshots
if: failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: failed-tests-screenshots
name: failed-consumer-tests-screenshots
path: tmp/capybara/screenshots/*.png
retention-days: 7
if-no-files-found: ignore
@@ -371,15 +371,6 @@ jobs:
run: |
bin/rake knapsack_pro:rspec
- name: Archive failed tests screenshots
if: failure()
uses: actions/upload-artifact@v3
with:
name: failed-tests-screenshots
path: tmp/capybara/screenshots/*.png
retention-days: 7
if-no-files-found: ignore
test_the_rest:
runs-on: ubuntu-22.04
services:

View File

@@ -12,22 +12,6 @@ Layout/EmptyLines:
Exclude:
- 'app/services/products_renderer.rb'
# Offense count: 6
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented, indented_relative_to_receiver
Layout/MultilineMethodCallIndentation:
Exclude:
- 'app/services/products_renderer.rb'
# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented
Layout/MultilineOperationIndentation:
Exclude:
- 'app/services/products_renderer.rb'
# Offense count: 16
# Configuration parameters: AllowComments, AllowEmptyLambdas.
Lint/EmptyBlock:
@@ -101,7 +85,7 @@ Lint/UselessMethodDefinition:
Exclude:
- 'app/models/spree/gateway.rb'
# Offense count: 23
# Offense count: 24
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
Metrics/AbcSize:
Exclude:
@@ -114,6 +98,7 @@ Metrics/AbcSize:
- 'app/helpers/spree/admin/navigation_helper.rb'
- 'app/models/enterprise_group.rb'
- 'app/models/enterprise_relationship.rb'
- 'app/models/product_import/entry_processor.rb'
- 'app/models/spree/ability.rb'
- 'app/models/spree/address.rb'
- 'app/models/spree/order/checkout.rb'
@@ -142,7 +127,7 @@ Metrics/BlockNesting:
Exclude:
- 'app/models/spree/payment/processing.rb'
# Offense count: 47
# Offense count: 46
# Configuration parameters: CountComments, Max, CountAsOne.
Metrics/ClassLength:
Exclude:
@@ -178,7 +163,6 @@ 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'
@@ -408,7 +392,6 @@ 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/stripe_sca_spec.rb'
- 'spec/requests/home_controller_spec.rb'
@@ -638,12 +621,6 @@ 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: 7
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
@@ -725,7 +702,7 @@ Style/ClassAndModuleChildren:
- 'lib/open_food_network/locking.rb'
- 'spec/models/spree/payment_method_spec.rb'
# Offense count: 2
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: always, always_true, never
@@ -872,39 +849,6 @@ Style/ReturnNilInPredicateMethodDefinition:
- 'app/serializers/api/admin/customer_serializer.rb'
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
# Offense count: 207
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: 3
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/SlicingWithRange:

View File

@@ -16,7 +16,6 @@ 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 'webpacker', '~> 5'

View File

@@ -161,8 +161,6 @@ 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)
@@ -358,7 +356,7 @@ GEM
ruby-vips (>= 2.0.17, < 3)
immigrant (0.3.6)
activerecord (>= 3.0)
invisible_captcha (2.2.0)
invisible_captcha (2.3.0)
rails (>= 5.2)
io-console (0.7.2)
ipaddress (0.8.3)
@@ -417,7 +415,7 @@ GEM
net-imap
net-pop
net-smtp
marcel (1.0.2)
marcel (1.0.4)
matrix (0.4.2)
method_source (1.1.0)
mime-types (3.5.2)
@@ -449,7 +447,7 @@ GEM
net-smtp (0.5.0)
net-protocol
newrelic_rpm (9.9.0)
nio4r (2.7.0)
nio4r (2.7.1)
nokogiri (1.16.5)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
@@ -863,7 +861,6 @@ 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

View File

@@ -10,7 +10,6 @@
//= require jquery.ui.all
//= require jquery.powertip
//= require jquery.cookie
//= require jquery.jstree/jquery.jstree
//= require jquery.vAlign
//= require angular
//= require angular-resource

View File

@@ -126,8 +126,11 @@ 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: $scope.nextVariantId()
id: newVariantId
unit_value: null
unit_description: null
on_demand: false
@@ -136,8 +139,9 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
on_hand: null
price: null
tax_category_id: null
category_id: null
category_id: newVariantCategoryId
DisplayProperties.setShowVariants product.id, true
DirtyProducts.addVariantProperty(product.id, newVariantId, 'category_id', newVariantCategoryId)
$scope.nextVariantId = ->

View File

@@ -3,6 +3,7 @@ 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)
@@ -18,6 +19,8 @@ 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)
@@ -25,4 +28,4 @@ angular.module('admin.orderCycles')
if $scope.order_cycle_form?.$dirty
t('admin.unsaved_confirm_leave')
NavigationCheck.register(warnAboutUnsavedChanges)
NavigationCheck.register(warnAboutUnsavedChanges)

View File

@@ -1,8 +1,9 @@
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $rootScope, $controller, $location, Enterprise, OrderCycle, ExchangeProduct, ocInstance) ->
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $rootScope, $controller, $location, Enterprise, EnterpriseFee, 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]?

View File

@@ -22,6 +22,8 @@ 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()

View File

@@ -6,6 +6,8 @@ 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'
})
{

View File

@@ -161,7 +161,11 @@ 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()})
oc = new OrderCycleResource({
order_cycle: this.dataForSubmit(),
confirm: this.order_cycle.confirm,
trigger_action: this.order_cycle.trigger_action
})
oc.$update {order_cycle_id: this.order_cycle.id, reloading: (if destination? then 1 else 0)}, (data) =>
form.$setPristine() if form
if destination?
@@ -171,6 +175,8 @@ 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'))

View File

@@ -1,21 +0,0 @@
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()

View File

@@ -1,139 +0,0 @@
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()

View File

@@ -10,7 +10,9 @@ angular.module("admin.utils").factory "StatusMessage", ->
statusMessage:
text: ""
style: {}
style: {},
type: null,
actionName: null
invalidMessage: ""
@@ -23,11 +25,15 @@ angular.module("admin.utils").factory "StatusMessage", ->
active: ->
@statusMessage.text != ''
display: (type, text) ->
display: (type, text, actionName = null) ->
@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

View File

@@ -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' }
%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}}" }
{{ StatusMessage.statusMessage.text || "&nbsp;" }}
%h5#status-message{ style: 'color: #C85136', "ng-show": "StatusMessage.invalidMessage !== ''" }
{{ StatusMessage.invalidMessage || "&nbsp;" }}

View File

@@ -24,6 +24,19 @@
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 */

View File

@@ -0,0 +1,22 @@
# 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

View File

@@ -5,12 +5,12 @@ module Admin
def create
authorize! :admin, enterprise
app = ConnectedApp.create!(enterprise_id: enterprise.id)
attributes = {}
attributes[:type] = connected_app_params[:type] if connected_app_params[:type]
ConnectAppJob.perform_later(
app, spree_current_user.spree_api_key,
channel: SessionChannel.for_request(request),
)
app = ConnectedApp.create!(enterprise_id: enterprise.id, **attributes)
app.connect(api_key: spree_current_user.spree_api_key,
channel: SessionChannel.for_request(request))
render_panel
end
@@ -18,15 +18,9 @@ module Admin
def destroy
authorize! :admin, enterprise
app = enterprise.connected_apps.first
app = enterprise.connected_apps.find(params.require(:id))
app.destroy
WebhookDeliveryJob.perform_later(
app.data["destroy"],
"disconnect-app",
nil
)
render_panel
end
@@ -39,5 +33,9 @@ module Admin
def render_panel
redirect_to "#{edit_admin_enterprise_path(enterprise)}#/connected_apps_panel"
end
def connected_app_params
params.permit(:type)
end
end
end

View File

@@ -35,13 +35,7 @@ module Admin
private
def fetch_catalog(url)
if url =~ /food-data-collaboration/
fdc_json = FdcRequest.new(spree_current_user).call(url)
fdc_message = JSON.parse(fdc_json)
fdc_message["products"]
else
DfcRequest.new(spree_current_user).call(url)
end
DfcRequest.new(spree_current_user).call(url)
end
# Most of this code is the same as in the DfcProvider::SuppliedProductsController.

View File

@@ -65,7 +65,9 @@ module Admin
order_cycle ||= OrderCycle.new(coordinator:) if coordinator.present?
enterprises = OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user,
order_cycle).visible_enterprises
EnterpriseFee.for_enterprises(enterprises).order('enterprise_id', 'fee_type', 'name')
fees = EnterpriseFee.for_enterprises(enterprises).order('enterprise_id', 'fee_type', 'name')
filter_fees(fees)
else
collection = EnterpriseFee.managed_by(spree_current_user).order('enterprise_id',
'fee_type', 'name')
@@ -74,6 +76,12 @@ 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

View File

@@ -11,6 +11,7 @@ module Admin
before_action :remove_protected_attrs, only: [:update]
before_action :require_order_cycle_set_params, only: [:bulk_update]
around_action :protect_invalid_destroy, only: :destroy
before_action :verify_datetime_change, only: :update
def index
respond_to do |format|
@@ -235,7 +236,7 @@ module Admin
else
begin
yield
rescue ActiveRecord::InvalidForeignKey
rescue ActiveRecord::InvalidForeignKey, ActiveRecord::DeleteRestrictionError
redirect_to main_app.admin_order_cycles_url
flash[:error] = I18n.t('admin.order_cycles.destroy_errors.orders_present')
end
@@ -294,5 +295,22 @@ module Admin
collection_attributes: [:id] + PermittedAttributes::OrderCycle.basic_attributes
).to_h.with_indifferent_access
end
# Check that order cycle datetime values changed if it has existing orders
def verify_datetime_change
return unless params[:order_cycle][:confirm]
return unless @order_cycle.orders.exists?
return if same_dates(@order_cycle.orders_open_at, order_cycle_params[:orders_open_at]) &&
same_dates(@order_cycle.orders_close_at, order_cycle_params[:orders_close_at])
render json: { trigger_action: params[:order_cycle][:trigger_action] },
status: :unprocessable_entity
end
def same_dates(date, string)
false unless date && string
DateTime.parse(string).to_fs(:short) == date.to_fs(:short)
end
end
end

View File

@@ -11,6 +11,8 @@ module Admin
def index
fetch_products
render "index", locals: { producers:, categories:, tax_category_options:, flash: }
session[:products_return_to_url] = request.url
end
def bulk_update

View File

@@ -1,16 +0,0 @@
# 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

View File

@@ -5,12 +5,10 @@ module Api
class TaxonsController < Api::V0::BaseController
respond_to :json
skip_authorization_check only: [:index, :show, :jstree]
skip_authorization_check only: [:index, :show]
def index
@taxons = if taxonomy
taxonomy.root.children
elsif params[:ids]
@taxons = if params[:ids]
Spree::Taxon.where(id: raw_params[:ids].split(","))
else
Spree::Taxon.ransack(raw_params[:q]).result
@@ -18,23 +16,9 @@ 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
@@ -60,20 +44,14 @@ module Api
private
def taxonomy
return if params[:taxonomy_id].blank?
@taxonomy ||= Spree::Taxonomy.find(params[:taxonomy_id])
end
def taxon
@taxon ||= taxonomy.taxons.find(params[:id])
@taxon = Spree::Taxon.find(params[:id])
end
def taxon_params
return if params[:taxon].blank?
params.require(:taxon).permit([:name, :parent_id, :position])
params.require(:taxon).permit([:name, :position])
end
end
end

View File

@@ -19,15 +19,18 @@ module Spree
before_action :authorize_admin
before_action :set_locale
before_action :warn_invalid_order_cycles, if: :html_request?
before_action :warn_invalid_order_cycles, if: :page_load_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?
return if flash[:notice].present? || session[:displayed_order_cycle_warning]
warning = OrderCycles::WarningService.new(spree_current_user).call
flash[:notice] = warning if warning.present?
return if warning.blank?
flash.now[:notice] = warning
session[:displayed_order_cycle_warning] = true
end
protected
@@ -81,6 +84,12 @@ module Spree
private
def page_load_request?
return false if request.format.include?('turbo')
html_request?
end
def html_request?
request.format.html?
end

View File

@@ -10,6 +10,7 @@ module Spree
include OpenFoodNetwork::SpreeApiKeyLoader
include OrderCyclesHelper
include EnterprisesHelper
helper ::Admin::ProductsHelper
before_action :load_data
before_action :load_producers, only: [:index, :new]

View File

@@ -1,27 +0,0 @@
# frozen_string_literal: true
module Spree
module Admin
class TaxonomiesController < ::Admin::ResourceController
respond_to :json, only: [:get_children]
def get_children
@taxons = Taxon.find(params[:parent_id]).children
end
private
def location_after_save
if @taxonomy.created_at == @taxonomy.updated_at
spree.edit_admin_taxonomy_url(@taxonomy)
else
spree.admin_taxonomies_url
end
end
def permitted_resource_params
params.require(:taxonomy).permit(:name)
end
end
end
end

View File

@@ -2,122 +2,70 @@
module Spree
module Admin
class TaxonsController < Spree::Admin::BaseController
respond_to :html, :json, :js
class TaxonsController < ::Admin::ResourceController
before_action :set_taxon, except: %i[create index new]
def edit
@taxonomy = Taxonomy.find(params[:taxonomy_id])
@taxon = @taxonomy.taxons.find(params[:id])
@permalink_part = @taxon.permalink.split("/").last
def index
@taxons = Taxon.order(:name)
end
def new
@taxon = Taxon.new
end
def edit; end
def create
@taxonomy = Taxonomy.find(params[:taxonomy_id])
@taxon = @taxonomy.taxons.build(params[:taxon])
@taxon = Spree::Taxon.new(taxon_params)
if @taxon.save
respond_with(@taxon) do |format|
format.json { render json: @taxon.to_json }
end
flash[:success] = flash_message_for(@taxon, :successfully_created)
redirect_to edit_admin_taxon_path(@taxon.id)
else
flash[:error] = Spree.t('errors.messages.could_not_create_taxon')
respond_with(@taxon) do |format|
format.html do
if redirect_to @taxonomy
spree.edit_admin_taxonomy_url(@taxonomy)
else
spree.admin_taxonomies_url
end
end
end
render :new, status: :unprocessable_entity
end
end
def update
@taxonomy = Taxonomy.find(params[:taxonomy_id])
@taxon = @taxonomy.taxons.find(params[:id])
parent_id = params[:taxon][:parent_id]
new_position = params[:taxon][:position]
if parent_id || new_position # taxon is being moved
new_parent = parent_id.nil? ? @taxon.parent : Taxon.find(parent_id.to_i)
new_position = new_position.nil? ? -1 : new_position.to_i
# Bellow is a very complicated way of finding where in nested set we
# should actually move the taxon to achieve sane results,
# JS is giving us the desired position, which was awesome for previous setup,
# but now it's quite complicated to find where we should put it as we have
# to differenciate between moving to the same branch, up down and into
# first position.
new_siblings = new_parent.children
if new_position <= 0 && new_siblings.empty?
@taxon.move_to_child_of(new_parent)
elsif new_parent.id != @taxon.parent_id
if new_position.zero?
@taxon.move_to_left_of(new_siblings.first)
else
@taxon.move_to_right_of(new_siblings[new_position - 1])
end
elsif new_position < new_siblings.index(@taxon)
@taxon.move_to_left_of(new_siblings[new_position]) # we move up
else
@taxon.move_to_right_of(new_siblings[new_position - 1]) # we move down
end
# Reset legacy position, if any extensions still rely on it
new_parent.children.reload.each do |t|
t.update_columns(
position: t.position,
updated_at: Time.zone.now
)
end
if parent_id
@taxon.reload
@taxon.set_permalink
@taxon.save!
@update_children = true
end
end
if params.key? "permalink_part"
parent_permalink = @taxon.permalink.split("/")[0...-1].join("/")
parent_permalink += "/" if parent_permalink.present?
params[:taxon][:permalink] = parent_permalink + params[:permalink_part]
end
# check if we need to rename child taxons if parent name or permalink changes
if params[:taxon][:name] != @taxon.name || params[:taxon][:permalink] != @taxon.permalink
@update_children = true
end
if @taxon.update(taxon_params)
flash[:success] = flash_message_for(@taxon, :successfully_updated)
end
# rename child taxons
if @update_children
@taxon.descendants.each do |taxon|
taxon.reload
taxon.set_permalink
taxon.save!
end
end
respond_with(@taxon) do |format|
format.html { redirect_to spree.edit_admin_taxonomy_url(@taxonomy) }
format.json { render json: @taxon.to_json }
redirect_to edit_admin_taxon_path(@taxon.id)
else
render :edit, status: :unprocessable_entity
end
end
def destroy
@taxon = Taxon.find(params[:id])
@taxon.destroy
respond_with(@taxon) { |format| format.json { render json: '' } }
status = if @taxon.destroy
flash_message = t('.delete_taxon.success')
status = :ok
else
flash_message = t('.delete_taxon.error')
status = :unprocessable_entity
end
respond_to do |format|
format.html {
flash[:success] = flash_message if status == :ok
flash[:error] = flash_message if status == :unprocessable_entity
redirect_to admin_taxons_path
}
format.turbo_stream {
flash[:success] = flash_message if status == :ok
flash[:error] = flash_message if status == :unprocessable_entity
render :destroy_taxon, status:
}
end
end
private
def set_taxon
@taxon = Taxon.find(params[:id])
end
def taxon_params
params.require(:taxon).permit(
:name, :parent_id, :position, :icon, :description, :permalink, :taxonomy_id,
:name, :position, :icon, :description, :permalink,
:meta_description, :meta_keywords, :meta_title, :dfc_id
)
end

View File

@@ -26,7 +26,8 @@ module Admin
show_enterprise_fees = can?(:manage_enterprise_fees,
enterprise) && (is_shop || enterprise.is_primary_producer)
show_connected_apps = can?(:manage_connected_apps, enterprise) &&
feature?(:connected_apps, spree_current_user, enterprise)
feature?(:connected_apps, spree_current_user, enterprise) &&
Spree::Config.connected_apps_enabled.present?
build_enterprise_side_menu_items(
is_shop:,
@@ -38,6 +39,11 @@ module Admin
)
end
def connected_apps_enabled
connected_apps_enabled = Spree::Config.connected_apps_enabled&.split(',') || []
ConnectedApp::TYPES & connected_apps_enabled
end
private
def build_enterprise_side_menu_items(

View File

@@ -11,21 +11,31 @@ module Admin
end
def prepare_new_variant(product)
product.variants.build do |variant|
variant.unit_value = 1.0 * (product.variant_unit_scale || 1)
variant.unit_presentation = VariantUnits::OptionValueNamer.new(variant).name
end
product.variants.build
end
def unit_value_with_description(variant)
scaled_unit_value = variant.unit_value / (variant.product.variant_unit_scale || 1)
precised_unit_value = number_with_precision(
scaled_unit_value,
precision: nil,
strip_insignificant_zeros: true
)
precised_unit_value = nil
if variant.unit_value
scaled_unit_value = variant.unit_value / (variant.product.variant_unit_scale || 1)
precised_unit_value = number_with_precision(
scaled_unit_value,
precision: nil,
strip_insignificant_zeros: true,
significant: false,
)
end
[precised_unit_value, variant.unit_description].compact_blank.join(" ")
end
def products_return_to_url(url_filters)
if feature?(:admin_style_v3, spree_current_user)
return session[:products_return_to_url] || admin_products_url
end
"#{admin_products_path}#{url_filters.empty? ? '' : "#?#{url_filters.to_query}"}"
end
end
end

View File

@@ -2,7 +2,7 @@
module I18nHelper
def locale_options
OpenFoodNetwork::I18nConfig.available_locales.map do |locale|
OpenFoodNetwork::I18nConfig.selectable_locales.map do |locale|
[t('language_name', locale:), locale]
end
end

View File

@@ -10,4 +10,8 @@ module MailerHelper
link_to ofn, "https://www.openfoodnetwork.org"
end
end
def order_reply_email(order)
order.distributor.email_address.presence || order.distributor.contact.email
end
end

View File

@@ -1,11 +0,0 @@
# frozen_string_literal: true
module Spree
module Admin
module TaxonsHelper
def taxon_path(taxon)
taxon.ancestors.reverse.collect(&:name).join( " >> ")
end
end
end
end

View File

@@ -19,8 +19,8 @@ class ConnectAppJob < ApplicationJob
selector = "#connected-app-discover-regen.enterprise_#{enterprise.id}"
html = ApplicationController.render(
partial: "admin/enterprises/form/connected_apps",
locals: { enterprise: },
partial: "admin/enterprises/form/connected_apps/discover_regen",
locals: { enterprise:, connected_app: enterprise.connected_apps.discover_regen.first },
)
cable_ready[channel].morph(selector:, html:).broadcast

View File

@@ -4,8 +4,34 @@
#
# Here we store keys and links to access the app.
class ConnectedApp < ApplicationRecord
TYPES = ['discover_regen', 'affiliate_sales_data'].freeze
belongs_to :enterprise
after_destroy :disconnect
scope :discover_regen, -> { where(type: "ConnectedApp") }
scope :affiliate_sales_data, -> { where(type: "ConnectedApps::AffiliateSalesData") }
scope :connecting, -> { where(data: nil) }
scope :ready, -> { where.not(data: nil) }
def connecting?
data.nil?
end
def ready?
!connecting?
end
def connect(api_key:, channel:)
ConnectAppJob.perform_later(self, api_key, channel:)
end
def disconnect
WebhookDeliveryJob.perform_later(
data["destroy"],
"disconnect-app",
nil
)
end
end

View File

@@ -0,0 +1,13 @@
# frozen_string_literal: true
# An enterprise can opt-in for their data to be included in the affiliate_sales_data endpoint
#
module ConnectedApps
class AffiliateSalesData < ConnectedApp
def connect(_opts)
update! data: true # not-nil value indicates it is ready
end
def disconnect; end
end
end

View File

@@ -1,5 +1,7 @@
# frozen_string_literal: false
require "mini_magick"
class Enterprise < ApplicationRecord
SELLS = %w(unspecified none own any).freeze
ENTERPRISE_SEARCH_RADIUS = 100

View File

@@ -24,6 +24,7 @@ class OrderCycle < ApplicationRecord
where incoming: false
}, class_name: "Exchange", dependent: :destroy
has_many :orders, class_name: 'Spree::Order', dependent: :restrict_with_exception
has_many :suppliers, -> { distinct }, source: :sender, through: :cached_incoming_exchanges
has_many :distributors, -> { distinct }, source: :receiver, through: :cached_outgoing_exchanges
has_many :order_cycle_schedules, dependent: :destroy

View File

@@ -162,7 +162,7 @@ module ProductImport
return
end
product = Spree::Product.new
product = Spree::Product.new(supplier_id: entry.enterprise_id)
product.assign_attributes(
entry.assignable_attributes.except('id', 'on_hand', 'on_demand', 'display_name')
)

View File

@@ -377,7 +377,7 @@ module ProductImport
end
def mark_as_new_product(entry)
new_product = Spree::Product.new
new_product = Spree::Product.new(supplier_id: entry.enterprise_id)
new_product.assign_attributes(
entry.assignable_attributes.except('id', 'on_hand', 'on_demand', 'display_name')
)

View File

@@ -39,7 +39,6 @@ module Spree
can [:index, :read], StockLocation
can [:index, :read], StockMovement
can [:index, :read], Taxon
can [:index, :read], Taxonomy
can [:index, :read], Variant
can [:index, :read], Zone
end

View File

@@ -139,5 +139,8 @@ module Spree
# Available units
preference :available_units, :string, default: "g,kg,T,mL,L,kL"
# Connected Apps
preference :connected_apps_enabled, :string, default: nil
end
end

View File

@@ -1,5 +1,7 @@
# frozen_string_literal: true
require "mini_magick"
module Spree
class Image < Asset
has_one_attached :attachment, service: image_service do |attachment|

View File

@@ -69,6 +69,7 @@ module Spree
attr_accessor :price, :display_as, :unit_value, :unit_description, :tax_category_id,
:shipping_category_id, :primary_taxon_id, :supplier_id
after_validation :validate_variant_attrs, on: :create
after_create :ensure_standard_variant
after_update :touch_supplier, if: :saved_change_to_primary_taxon_id?
around_destroy :destruction
@@ -264,6 +265,7 @@ module Spree
def variant_unit_with_scale
scale_clean = ActiveSupport::NumberHelper.number_to_rounded(variant_unit_scale,
precision: nil,
significant: false,
strip_insignificant_zeros: true)
[variant_unit, scale_clean].compact_blank.join("_")
end
@@ -288,6 +290,21 @@ module Spree
private
def validate_variant_attrs
# Avoid running validation when we can't set variant attrs
# eg clone product. Will raise error if clonning a product with no variant
return if variants.first&.valid?
unless Spree::Taxon.find_by(id: primary_taxon_id)
errors.add(:primary_taxon_id,
I18n.t('activerecord.errors.models.spree/product.must_exist'))
end
return if Enterprise.find_by(id: supplier_id)
errors.add(:supplier_id,
I18n.t('activerecord.errors.models.spree/product.must_exist'))
end
def update_units
return unless saved_change_to_variant_unit? || saved_change_to_variant_unit_name?

View File

@@ -2,19 +2,11 @@
module Spree
class Taxon < ApplicationRecord
self.belongs_to_required_by_default = false
acts_as_nested_set dependent: :destroy
belongs_to :taxonomy, class_name: 'Spree::Taxonomy', touch: true
has_many :variants, class_name: "Spree::Variant", foreign_key: "primary_taxon_id",
inverse_of: :primary_taxon, dependent: :restrict_with_error
has_many :products, through: :variants, dependent: nil
before_create :set_permalink
validates :name, presence: true
# Indicate which filters should be used for this taxon
@@ -31,26 +23,6 @@ module Spree
end
end
def set_permalink
if parent.present?
self.permalink = [parent.permalink, permalink_end].join('/')
elsif permalink.blank?
self.permalink = UrlGenerator.to_url(name)
end
end
# For #2759
def to_param
permalink
end
def pretty_name
ancestor_chain = ancestors.inject("") do |name, ancestor|
name + "#{ancestor.name} -> "
end
ancestor_chain + name.to_s
end
# Find all the taxons of supplied products for each enterprise, indexed by enterprise.
# Format: {enterprise_id => [taxon_id, ...]}
def self.supplied_taxons
@@ -90,13 +62,5 @@ module Spree
ts[t.enterprise_id.to_i] << t.id
end
end
private
def permalink_end
return UrlGenerator.to_url(name) if permalink.blank?
permalink.split('/').last
end
end
end

View File

@@ -1,27 +0,0 @@
# frozen_string_literal: true
module Spree
class Taxonomy < ApplicationRecord
validates :name, presence: true
has_many :taxons, dependent: :nullify
has_one :root, -> { where parent_id: nil }, class_name: "Spree::Taxon", dependent: :destroy
after_save :set_name
default_scope -> { order("#{table_name}.position") }
private
def set_name
if root
root.update_columns(
name:,
updated_at: Time.zone.now
)
else
self.root = Taxon.create!(taxonomy_id: id, name:)
end
end
end
end

View File

@@ -156,6 +156,12 @@ module Spree
self.disabled_at = value == '1' ? Time.zone.now : nil
end
def affiliate_enterprises
return [] unless Flipper.enabled?(:affiliate_sales_data, self)
Enterprise.joins(:connected_apps).merge(ConnectedApps::AffiliateSalesData.ready)
end
protected
def password_required?

View File

@@ -87,7 +87,6 @@ module Spree
before_validation :ensure_unit_value
before_validation :update_weight_from_unit_value, if: ->(v) { v.product.present? }
before_validation :convert_variant_weight_to_decimal
before_validation :assign_related_taxon, if: ->(v) { v.primary_taxon.blank? }
before_save :assign_units, if: ->(variant) {
variant.new_record? || variant.changed_attributes.keys.intersection(NAME_FIELDS).any?
@@ -217,10 +216,6 @@ module Spree
private
def assign_related_taxon
self.primary_taxon ||= product.variants.last&.primary_taxon
end
def check_currency
return unless currency.nil?

View File

@@ -1,177 +0,0 @@
# frozen_string_literal: true
class ProductsReflex < ApplicationReflex
include Pagy::Backend
before_reflex :init_filters_params, :init_pagination_params
def change_per_page
@per_page = element.value.to_i
@page = 1
fetch_and_render_products_with_flash
end
def clear_search
@search_term = nil
@producer_id = nil
@category_id = nil
@page = 1
fetch_and_render_products_with_flash
end
private
def init_filters_params
# params comes from the form
# _params comes from the url
# priority is given to params from the form (if present) over url params
@search_term = params[:search_term] || params[:_search_term]
@producer_id = params[:producer_id] || params[:_producer_id]
@category_id = params[:category_id] || params[:_category_id]
end
def init_pagination_params
# prority is given to element dataset (if present) over url params
@page = element.dataset.page || params[:_page] || 1
@per_page = element.dataset.perpage || params[:_per_page] || 15
end
def fetch_and_render_products_with_flash
fetch_products
render_products
end
def render_products
cable_ready.replace(
selector: "#products-content",
html: render(partial: "admin/products_v3/content",
locals: { products: @products, pagy: @pagy, search_term: @search_term,
producer_options: producers, producer_id: @producer_id,
category_options: categories, tax_category_options:,
category_id: @category_id, flashes: flash })
)
cable_ready.replace_state(
url: current_url,
)
morph :nothing
end
def render_products_form_with_flash
locals = { products: @products }
locals[:error_counts] = @error_counts if @error_counts.present?
locals[:flashes] = flash if flash.any?
cable_ready.replace(
selector: "#products-form",
html: render(partial: "admin/products_v3/table", locals:)
)
morph :nothing
# dunno why this doesn't work. The HTML stops after the first `<col>` element, wtf?!
# morph "#products-form", render(partial: "admin/products_v3/table", locals:)
end
def producers
producers = OpenFoodNetwork::Permissions.new(current_user)
.managed_product_enterprises.is_primary_producer.by_name
producers.map { |p| [p.name, p.id] }
end
def categories
Spree::Taxon.order(:name).map { |c| [c.name, c.id] }
end
def tax_category_options
Spree::TaxCategory.order(:name).pluck(:name, :id)
end
def fetch_products
product_query = OpenFoodNetwork::Permissions.new(current_user)
.editable_products.merge(product_scope).ransack(ransack_query).result(distinct: true)
@pagy, @products = pagy(product_query.order(:name), items: @per_page, page: @page,
size: [1, 2, 2, 1])
end
def product_scope
scope = if current_user.has_spree_role?("admin") || current_user.enterprises.present?
Spree::Product
else
Spree::Product.active
end
scope.includes(product_query_includes)
end
def ransack_query
query = {}
query.merge!(variants_supplier_id_in: @producer_id) if @producer_id.present?
if @search_term.present?
query.merge!(Spree::Variant::SEARCH_KEY => @search_term)
end
query.merge!(variants_primary_taxon_id_in: @category_id) if @category_id.present?
query
end
# Optimise by pre-loading required columns
def product_query_includes
# TODO: add other fields used in columns? (eg supplier: [:name])
[
# variants: [
# :default_price,
# :stock_locations,
# :stock_items,
# :variant_overrides
# ]
]
end
def current_url
url = URI(request.original_url)
url.query = url.query.present? ? "#{url.query}&" : ""
# add params with _ to avoid conflicts with params from the form
url.query += "_page=#{@page}"
url.query += "&_per_page=#{@per_page}"
url.query += "&_search_term=#{@search_term}" if @search_term.present?
url.query += "&_producer_id=#{@producer_id}" if @producer_id.present?
url.query += "&_category_id=#{@category_id}" if @category_id.present?
url.to_s
end
# Similar to spree/admin/products_controller
def product_set_from_params
# Form field names:
# '[products][0][id]' (hidden field)
# '[products][0][name]'
# '[products][0][variants_attributes][0][id]' (hidden field)
# '[products][0][variants_attributes][0][display_name]'
#
# Resulting in params:
# "products" => {
# "0" => {
# "id" => "123"
# "name" => "Pommes",
# "variants_attributes" => {
# "0" => {
# "id" => "1234",
# "display_name" => "Large box",
# }
# }
# }
collection_hash = products_bulk_params[:products]
.transform_values { |product|
# Convert variants_attributes form hash to an array if present
product[:variants_attributes] &&= product[:variants_attributes].values
product
}.with_indifferent_access
Sets::ProductSet.new(collection_attributes: collection_hash)
end
def products_bulk_params
params.permit(products: ::PermittedAttributes::Product.attributes)
.to_h.with_indifferent_access
end
end

View File

@@ -3,7 +3,7 @@
module Api
module Admin
class TaxonSerializer < ActiveModel::Serializer
attributes :id, :name, :pretty_name
attributes :id, :name
end
end
end

View File

@@ -4,5 +4,5 @@ class Api::TaxonSerializer < ActiveModel::Serializer
cached
delegate :cache_key, to: :object
attributes :id, :name, :permalink, :pretty_name, :position, :parent_id, :taxonomy_id
attributes :id, :name, :permalink, :position
end

View File

@@ -16,7 +16,7 @@ module OrderCycles
end
def products_relation_incl_supplier_properties
query = relation_by_sorting(supplier_properties: true)
query = relation_by_sorting
query = supplier_property_join(query)
@@ -34,10 +34,10 @@ module OrderCycles
attr_reader :distributor, :order_cycle, :customer
def relation_by_sorting(supplier_properties: false)
def relation_by_sorting
query = Spree::Product.where(id: stocked_products)
if sorting == "by_producer" || supplier_properties
if sorting == "by_producer"
# Joins on the first product variant to allow us to filter product by supplier. This is so
# enterprise can display product sorted by supplier in a custom order on their shopfront.
#
@@ -57,7 +57,8 @@ module OrderCycles
# different category for a given product.
query.
joins("LEFT JOIN (
SELECT DISTINCT ON(product_id) id, product_id, primary_taxon_id
SELECT DISTINCT ON(product_id) id, product_id, primary_taxon_id,
supplier_id
FROM spree_variants WHERE deleted_at IS NULL
) first_variant ON spree_products.id = first_variant.product_id").
select("spree_products.*, first_variant.primary_taxon_id").
@@ -71,6 +72,16 @@ module OrderCycles
distributor.preferred_shopfront_product_sorting_method
end
def sorting_by_producer?
sorting == "by_producer" &&
distributor.preferred_shopfront_producer_order.present?
end
def sorting_by_category?
sorting == "by_category" &&
distributor.preferred_shopfront_taxon_order.present?
end
def supplier_property_join(query)
query.joins("
JOIN enterprises ON enterprises.id = first_variant.supplier_id
@@ -79,16 +90,14 @@ module OrderCycles
end
def order
if distributor.preferred_shopfront_product_sorting_method == "by_producer" &&
distributor.preferred_shopfront_producer_order.present?
if sorting_by_producer?
order_by_producer = distributor
.preferred_shopfront_producer_order
.split(",").map { |id| "first_variant.supplier_id=#{id} DESC" }
.join(", ")
"#{order_by_producer}, spree_products.name ASC, spree_products.id ASC"
elsif distributor.preferred_shopfront_product_sorting_method == "by_category" &&
distributor.preferred_shopfront_taxon_order.present?
elsif sorting_by_category?
order_by_category = distributor
.preferred_shopfront_taxon_order
.split(",").map { |id| "first_variant.primary_taxon_id=#{id} DESC" }

View File

@@ -19,5 +19,7 @@ class ShopsListService
.includes(address: [:state, :country])
.includes(:properties)
.includes(supplied_products: :properties)
.with_attached_promo_image
.with_attached_logo
end
end

View File

@@ -0,0 +1,25 @@
= render :partial => 'spree/admin/shared/configuration_menu'
- content_for :page_title do
= t('.title')
= form_tag main_app.admin_connected_app_settings_path, :method => :put do
%fieldset
%legend= t('.enabled_legend')
= t('.info_html')
.field
-# Blank value in case nothing is selected
= hidden_field_tag("preferences[connected_apps_enabled][]", "")
- ConnectedApp::TYPES.each do |type|
%label
= check_box_tag("preferences[connected_apps_enabled][]", type,
Spree::Config.connected_apps_enabled&.split(',')&.include?(type))
= t('.connected_apps_enabled.' + type)
%br
.form-buttons
= button t(:update), 'icon-refresh'

View File

@@ -1,30 +1,3 @@
%div{ id: "connected-app-discover-regen", class: "enterprise_#{enterprise.id}" }
.connected-app__head
%div
%h3= t ".title"
%p= t ".tagline"
%div
- if enterprise.connected_apps.empty?
= button_to t(".enable"), admin_enterprise_connected_apps_path(enterprise.id), method: :post, disabled: !managed_by_user?(enterprise)
-# This is only seen by super-admins:
%em= t(".need_to_be_manager") unless managed_by_user?(enterprise)
- elsif enterprise.connected_apps.connecting.present?
%button{ disabled: true }
%i.spinner.fa.fa-spin.fa-circle-o-notch
&nbsp;
= t ".loading"
- else
= button_to t(".disable"), admin_enterprise_connected_app_path(0, enterprise_id: enterprise.id), method: :delete
.connected-app__connection
- if enterprise.connected_apps.ready.present?
.connected-app__note
- link = enterprise.connected_apps[0].data["link"]
%p= t ".note"
%div
%a{ href: link, target: "_blank", class: "button secondary" }
= t ".link_label"
%hr
.connected-app__description
= t ".description_html"
- connected_apps_enabled.each do |type|
= render partial: "/admin/enterprises/form/connected_apps/#{type}",
locals: { enterprise:, connected_app: enterprise.connected_apps.public_send(type).first }

View File

@@ -0,0 +1,15 @@
%section.connected_app
.connected-app__head
%div
%h3= t ".title"
%p= t ".tagline"
%div
- if connected_app.nil?
= button_to t(".enable"), admin_enterprise_connected_apps_path(enterprise.id, type: "ConnectedApps::AffiliateSalesData"), method: :post, disabled: !managed_by_user?(enterprise)
-# This is only seen by super-admins:
%em= t(".need_to_be_manager") unless managed_by_user?(enterprise)
- else
= button_to t(".disable"), admin_enterprise_connected_app_path(connected_app.id, enterprise_id: enterprise.id), method: :delete
%hr
.connected-app__description
= t ".description_html"

View File

@@ -0,0 +1,30 @@
%section.connected_app{ id: "connected-app-discover-regen", class: "enterprise_#{enterprise.id}" }
.connected-app__head
%div
%h3= t ".title"
%p= t ".tagline"
%div
- if connected_app.nil?
= button_to t(".enable"), admin_enterprise_connected_apps_path(enterprise.id), method: :post, disabled: !managed_by_user?(enterprise)
-# This is only seen by super-admins:
%em= t(".need_to_be_manager") unless managed_by_user?(enterprise)
- elsif connected_app&.connecting?
%button{ disabled: true }
%i.spinner.fa.fa-spin.fa-circle-o-notch
&nbsp;
= t ".loading"
- else
= button_to t(".disable"), admin_enterprise_connected_app_path(connected_app.id, enterprise_id: enterprise.id), method: :delete
.connected-app__connection
- if connected_app&.ready?
.connected-app__note
- link = connected_app.data["link"]
%p= t ".note"
%div
%a{ href: link, target: "_blank", class: "button secondary" }
= t ".link_label"
%hr
.connected-app__description
= t ".description_html"

View File

@@ -0,0 +1,14 @@
.flex-column-gap-1
%h6
= t('.title')
%div{ style: 'font-size: 1rem;' }
= t('.content')
%p.modal-actions.justify-end.gap-1
%button.button.secondary{ "ng-click": "submit($event, null)", type: "button", style: "display: none;", data: { action: 'click->modal#close', 'trigger-action': 'save' } }
= t('.proceed')
%button.button.secondary{ "ng-click": "submit($event, '#{main_app.admin_order_cycle_incoming_path(@order_cycle)}')", type: "button", style: "display: none;", data: { action: 'click->modal#close', 'trigger-action': 'saveAndNext' } }
= t('.proceed')
%button.button.secondary{ "ng-click": "submit($event, '#{main_app.admin_order_cycles_path}')", type: "button", style: "display: none;", data: { action: 'click->modal#close', 'trigger-action': 'saveAndBack' } }
= t('.proceed')
%button.button.primary{ type: "button", 'data-action': 'click->modal#close' }
= t('.cancel')

View File

@@ -16,18 +16,25 @@
- ng_controller = @order_cycle.simple? ? 'AdminSimpleEditOrderCycleCtrl' : 'AdminEditOrderCycleCtrl'
= admin_inject_order_cycle_instance(@order_cycle)
= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => ng_controller, name: 'order_cycle_form'} do |f|
%div{ data: { controller: 'order-cycle-form' } }
= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => ng_controller, name: 'order_cycle_form'} do |f|
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
%input.red{ type: "button", value: t('.save'), "ng-click": "submit($event, null)", "ng-disabled": "!order_cycle_form.$dirty || order_cycle_form.$invalid", data: { confirm: "true", 'trigger-action': 'save' } }
- if @order_cycle.simple?
%input.red{ type: "button", value: t('.save_and_back_to_list'), "ng-click": "submit($event, '#{main_app.admin_order_cycles_path}')", "ng-disabled": "!order_cycle_form.$dirty || order_cycle_form.$invalid", data: { confirm: "true", 'trigger-action': 'saveAndBack' } }
- else
%input.red{ type: "button", value: t('.save_and_next'), "ng-click": "submit($event, '#{main_app.admin_order_cycle_incoming_path(@order_cycle)}')", "ng-disabled": "!order_cycle_form.$dirty || order_cycle_form.$invalid", data: { confirm: "true", 'trigger-action': 'saveAndNext' } }
%input{ type: "button", value: t('.next'), "ng-click": "cancel('#{main_app.admin_order_cycle_incoming_path(@order_cycle)}')", "ng-disabled": "order_cycle_form.$dirty" }
%input{ type: "button", "ng-value": "order_cycle_form.$dirty ? '#{t('.cancel')}' : '#{t('.back_to_list')}'", "ng-click": "cancel('#{main_app.admin_order_cycles_path}')" }
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
%input.red{ type: "button", value: t('.save'), "ng-click": "submit($event, null)", "ng-disabled": "!order_cycle_form.$dirty || order_cycle_form.$invalid" }
- if @order_cycle.simple?
%input.red{ type: "button", value: t('.save_and_back_to_list'), "ng-click": "submit($event, '#{main_app.admin_order_cycles_path}')", "ng-disabled": "!order_cycle_form.$dirty || order_cycle_form.$invalid" }
= render 'simple_form', f: f
- else
%input.red{ type: "button", value: t('.save_and_next'), "ng-click": "submit($event, '#{main_app.admin_order_cycle_incoming_path(@order_cycle)}')", "ng-disabled": "!order_cycle_form.$dirty || order_cycle_form.$invalid" }
%input{ type: "button", value: t('.next'), "ng-click": "cancel('#{main_app.admin_order_cycle_incoming_path(@order_cycle)}')", "ng-disabled": "order_cycle_form.$dirty" }
%input{ type: "button", "ng-value": "order_cycle_form.$dirty ? '#{t('.cancel')}' : '#{t('.back_to_list')}'", "ng-click": "cancel('#{main_app.admin_order_cycles_path}')" }
= render 'form', f: f
- if @order_cycle.simple?
= render 'simple_form', f: f
- else
= render 'form', f: f
%div.warning-modal{ data: { controller: 'modal modal-link', 'modal-link-target-value': "linked-order-warning-modal" } }
%button.modal-target-trigger{ type: 'button', data: { 'action': 'modal-link#open' }, style: 'display: none;' }
= render ModalComponent.new(id: "linked-order-warning-modal", close_button: false) do
.content.flex-column.gap-2
= render 'date_time_warning_modal_content'

View File

@@ -1,6 +1,6 @@
= form_with url: admin_products_path, id: "filters", method: :get, data: { "search-target": "form", 'turbo-frame': "_self" } do
= form_with url: admin_products_path, id: "filters", method: :get, data: { "search-target": "form", 'turbo-frame': "_self", 'turbo-action': "advance" } do
= hidden_field_tag :page, nil, class: "page"
= hidden_field_tag :per_page, nil, class: "per-page"
= hidden_field_tag :per_page, params[:per_page], class: "per-page"
= hidden_field_tag '[q][s]', params.dig(:q, :s) || 'name asc', class: 'sort', 'data-default': 'name asc'
.query

View File

@@ -1,6 +1,6 @@
- if search_term.present? || producer_id.present? || category_id.present?
= t('.no_products_found_for_search')
%a{ href: "#", class: "button disruptive relaxed", data: { reflex: "click->products#clear_search" } }
%a{ href: admin_products_path, class: "button disruptive relaxed", 'data-turbo-frame': "_self" }
= t("admin.products_v3.sort.pagination.clear_search")
- else
= t('.no_products_found')

View File

@@ -4,7 +4,7 @@
= t(".pagination.total_html", total: pagy.count, from: pagy.from, to: pagy.to)
- if search_term.present? || producer_id.present? || category_id.present?
%a{ href: url_for(page: 1), class: "button disruptive", 'data-turbo-frame': "_self" }
%a{ href: url_for(page: 1), class: "button disruptive", data: { 'turbo-frame': "_self", 'turbo-action': "advance" } }
= t(".pagination.clear_search")
%form.with-dropdown

View File

@@ -18,7 +18,7 @@
= f.hidden_field :unit_value
= f.hidden_field :unit_description
= f.text_field :unit_value_with_description,
value: unit_value_with_description(variant), 'aria-label': t('admin.products_page.columns.unit_value'), required: true
value: unit_value_with_description(variant), 'aria-label': t('admin.products_page.columns.unit_value')
.field
= f.label :display_as, t('admin.products_page.columns.display_as')
= f.text_field :display_as, placeholder: VariantUnits::OptionValueNamer.new(variant).name
@@ -37,20 +37,24 @@
= f.label :on_demand do
= f.check_box :on_demand, 'data-action': 'change->toggle-control#disableIfPresent change->popout#closeIfChecked'
= t(:on_demand)
%td.col-producer.naked_inputs
%td.col-producer.field.naked_inputs
= render(SearchableDropdownComponent.new(form: f,
name: :supplier_id,
aria_label: t('.producer_field_name'),
options: producer_options,
selected_option: variant.supplier_id,
placeholder_value: t('admin.products_v3.filters.search_for_producers')))
include_blank: t('admin.products_v3.filters.select_producer'),
placeholder_value: t('admin.products_v3.filters.select_producer')))
= error_message_on variant, :supplier
%td.col-category.field.naked_inputs
= render(SearchableDropdownComponent.new(form: f,
name: :primary_taxon_id,
options: category_options,
selected_option: variant.primary_taxon_id,
aria_label: t('.category_field_name'),
placeholder_value: t('admin.products_v3.filters.search_for_categories')))
include_blank: t('admin.products_v3.filters.select_category'),
placeholder_value: t('admin.products_v3.filters.select_category')))
= error_message_on variant, :primary_taxon
%td.col-tax_category.field.naked_inputs
= render(SearchableDropdownComponent.new(form: f,
name: :tax_category_id,

View File

@@ -3,17 +3,17 @@
%tr
%th{:align => "left"}
%h5= t(:invoice_column_item)
%th{:align => "right", :width => "15%"}
%th{:align => "right", :width => "6%" }
%h5= t(:invoice_column_qty)
%th{:align => "right", :width => "15%"}
%h5= t(:invoice_column_weight_volume)
%th{:align => "right", :width => "15%"}
%h5= t(:invoice_column_price_per_unit_without_taxes)
%th{:align => "right", :width => "15%"}
%th{:align => "right", :width => "12%"}
%h5= t(:invoice_column_price_without_taxes)
%th{:align => "right", :width => "15%"}
%th{:align => "right", :width => "9%" }
%h5= t(:invoice_column_tax_rate)
%th{:align => "right", :width => "15%"}
%th{:align => "right", :width => "12%" }
%h5= t(:invoice_column_price_with_taxes)
%tbody
- @order.sorted_line_items.each do |item|

View File

@@ -1,7 +1,7 @@
= admin_inject_available_units
- content_for :page_actions do
%li= button_link_to t('admin.products.back_to_products_list'), "#{admin_products_path}#{(@url_filters.empty? ? "" : "#?#{@url_filters.to_query}")}", :icon => 'icon-arrow-left'
%li= button_link_to t('admin.products.back_to_products_list'), products_return_to_url(@url_filters), :icon => 'icon-arrow-left'
%li#new_product_link
= button_link_to t(:new_product), new_object_url, { :icon => 'icon-plus', :id => 'admin_new_product' }
@@ -16,4 +16,4 @@
.form-buttons.filter-actions.actions
= button t(:update), 'icon-refresh'
= button_link_to t(:cancel), "#{collection_url}#{(@url_filters.empty? ? "" : "#?#{@url_filters.to_query}")}", icon: 'icon-remove'
= button_link_to t(:cancel), products_return_to_url(@url_filters), icon: 'icon-remove'

View File

@@ -12,7 +12,7 @@
= f.label :supplier, t(".supplier")
%span.required *
= f.select :supplier_id, options_from_collection_for_select(@producers, :id, :name, @product.supplier_id), { include_blank: t("spree.admin.products.new.supplier_select_placeholder") }, { "data-controller": "tom-select", class: "primary" }
= f.error_message_on :supplier
= f.error_message_on :supplier_id
.eight.columns.omega
= f.field_container :name do
= f.label :name, t(".product_name")

View File

@@ -15,7 +15,7 @@
- if DefaultCountry.id
= configurations_sidebar_menu_item Spree.t(:states), admin_country_states_path(DefaultCountry.id)
= configurations_sidebar_menu_item Spree.t(:payment_methods), admin_payment_methods_path
= configurations_sidebar_menu_item Spree.t(:taxonomies), admin_taxonomies_path
= configurations_sidebar_menu_item Spree.t(:taxons), admin_taxons_path
= configurations_sidebar_menu_item Spree.t(:shipping_methods), admin_shipping_methods_path
= configurations_sidebar_menu_item Spree.t(:shipping_categories), admin_shipping_categories_path
= configurations_sidebar_menu_item t(:enterprise_fees), main_app.admin_enterprise_fees_path
@@ -23,3 +23,4 @@
= configurations_sidebar_menu_item t('admin.invoice_settings.edit.title'), main_app.edit_admin_invoice_settings_path
= configurations_sidebar_menu_item t('admin.matomo_settings.edit.title'), main_app.edit_admin_matomo_settings_path
= configurations_sidebar_menu_item t('admin.stripe_connect_settings.edit.title'), main_app.edit_admin_stripe_connect_settings_path
= configurations_sidebar_menu_item t('admin.connected_app_settings.edit.title'), main_app.edit_admin_connected_app_settings_path

View File

@@ -1,4 +1,5 @@
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}
%meta{ name: "turbo-cache-control", content: "no-cache" }
= csrf_meta_tags
= action_cable_meta_tag

View File

@@ -3,7 +3,7 @@
= tab :order_cycles, url: main_app.admin_order_cycles_path, icon: 'icon-refresh'
= tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path, icon: 'icon-shopping-cart'
= tab :reports, url: main_app.admin_reports_path, icon: 'icon-file'
= tab :general_settings, :terms_of_service_files, :mail_methods, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxonomies, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path
= tab :general_settings, :terms_of_service_files, :mail_methods, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxons, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, :connected_app_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path
= tab :enterprises, :enterprise_relationships, :vouchers, :oidc_settings, url: main_app.admin_enterprises_path
= tab :customers, url: main_app.admin_customers_path
= tab :enterprise_groups, url: main_app.admin_enterprise_groups_path, label: 'groups'

View File

@@ -1,7 +0,0 @@
.field.align-center
= f.field_container :name do
= f.label :name, t("spree.name")
%span.required *
%br/
= error_message_on :taxonomy, :name
= text_field :taxonomy, :name

View File

@@ -1,13 +0,0 @@
<% content_for :head do %>
<%= javascript_tag "var taxonomy_id = #{@taxonomy.id};
var loading = '#{escape_javascript t("spree.loading")}';
var new_taxon = '#{escape_javascript t("spree.new_taxon")}';
var server_error = '#{escape_javascript t("spree.server_error")}';
var taxonomy_tree_error = '#{escape_javascript t("spree.taxonomy_tree_error")}';
$(document).ready(function(){
setup_taxonomy_tree(taxonomy_id);
});
"
%>
<% end %>

View File

@@ -1,19 +0,0 @@
%table#listing_taxonomies.index.sortable{"data-sortable-link" => update_positions_admin_taxonomies_url}
%colgroup
%col{style: "width: 85%"}/
%col{style: "width: 15%"}/
%thead
%tr
%th= t("spree.name")
%th.actions
%tbody
- @taxonomies.each do |taxonomy|
- tr_class = cycle('odd', 'even')
- tr_id = spree_dom_id(taxonomy)
%tr{class: tr_class, id: tr_id}
%td
%span.handle
= taxonomy.name
%td.actions
= link_to_edit taxonomy.id, no_text: true
= link_to_delete taxonomy, no_text: true

View File

@@ -1,7 +0,0 @@
- if taxon.children.length != 0
%ul
- taxon.children.each do |child|
%li{id: "#{child.id}", rel: "taxon"}
%a{href: "#"}= child.name
- if child.children.length > 0
= render partial: 'taxon', locals: { taxon: child }

View File

@@ -1,27 +0,0 @@
= render partial: 'spree/admin/shared/configuration_menu'
= render partial: 'js_head'
- content_for :page_title do
= t("spree.taxonomy_edit")
- content_for :page_actions do
%li
= button_link_to t("spree.back_to_taxonomies_list"), spree.admin_taxonomies_path, icon: 'icon-arrow-left'
#ajax_error.errorExplanation{style: "display:none;"}
= form_for [:admin, @taxonomy] do |f|
%fieldset.no-border-top
= render partial: 'form', locals: { f: f }
%div
= label_tag nil, t("spree.tree")
%br/
:javascript
Spree.routes.taxonomy_taxons = "#{main_app.api_v0_taxonomy_taxons_url(@taxonomy)}";
Spree.routes.admin_taxonomy_taxons = "#{spree.admin_taxonomy_taxons_url(@taxonomy)}";
#taxonomy_tree.tree
.info= t("spree.taxonomy_tree_instruction")
%br/
.filter-actions.actions
= button t('spree.actions.update'), 'icon-refresh'
= button_link_to t('spree.actions.cancel'), admin_taxonomies_path, icon: 'icon-remove'

View File

@@ -1,11 +0,0 @@
= render partial: 'spree/admin/shared/configuration_menu'
- content_for :page_title do
= t("spree.taxonomies")
- content_for :page_actions do
%li
= button_link_to t("spree.new_taxonomy"), spree.new_admin_taxonomy_url, icon: 'icon-plus', id: 'admin_new_taxonomy_link'
#list-taxonomies
= render partial: 'list'

View File

@@ -1,15 +0,0 @@
= render partial: 'spree/admin/shared/configuration_menu'
- content_for :page_title do
= t("spree.new_taxonomy")
- content_for :page_actions do
%li
= button_link_to t("spree.back_to_taxonomies_list"), spree.admin_taxonomies_path, icon: 'icon-arrow-left'
= form_for [:admin, @taxonomy] do |f|
= render partial: 'form', locals: { f: f }
%fieldset.no-border-top
%br/
.filter-actions.actions
= button t("spree.create"), 'icon-ok'

View File

@@ -6,12 +6,6 @@
%br/
= error_message_on :taxon, :name
= text_field :taxon, :name, class: 'fullwidth'
= f.field_container :permalink_part do
= f.label :permalink_part, t(".permalink")
%span.required *
%br/
= @taxon.permalink.split("/")[0...-1].join("/") + "/"
= text_field_tag :permalink_part, @permalink_part
= f.field_container :meta_title do
= f.label :meta_title, t(".meta_title")
%br/

View File

@@ -0,0 +1,4 @@
- unless flash[:error]
= turbo_stream.remove(spree_dom_id(@taxon))
= turbo_stream.append "flashes" do
= render(partial: 'admin/shared/flashes', locals: { flashes: flash })

View File

@@ -1,16 +1,16 @@
= render partial: 'spree/admin/shared/configuration_menu'
- content_for :page_title do
= t("spree.taxonomy_edit")
= t(".title")
- content_for :page_actions do
%li
= button_link_to t("spree.back_to_taxonomies_list"), spree.admin_taxonomies_path, icon: 'icon-arrow-left'
= button_link_to t("spree.admin.taxons.back_to_list"), admin_taxons_path, icon: 'icon-arrow-left'
- # Because otherwise the form would attempt to use to_param of @taxon
- form_url = admin_taxonomy_taxon_path(@taxonomy.id, @taxon.id)
= form_for [:admin, @taxonomy, @taxon], method: :put, url: form_url, html: { multipart: true } do |f|
= form_with model: @taxon, url: admin_taxon_path(@taxon.id),
data: { turbo: true }, id: "edit-taxon-#{@taxon.id}",
method: :put, html: { multipart: true } do |f|
= render partial: 'form', locals: { f: f }
.form-buttons
= button t('spree.actions.update'), 'icon-refresh'
= button_link_to t('spree.actions.cancel'), edit_admin_taxonomy_url(@taxonomy), icon: "icon-remove"
= button_link_to t('spree.actions.cancel'), admin_taxons_url, icon: "icon-remove"

View File

@@ -0,0 +1,27 @@
= render partial: 'spree/admin/shared/configuration_menu'
- content_for :page_title do
= t(".title")
- content_for :page_actions do
%li
= button_link_to t(".new_taxon"), spree.new_admin_taxon_url, icon: 'icon-plus', id: 'admin_new_taxon_link'
%table#listing_taxons.index
%colgroup
%col{style: "width: 85%"}/
%col{style: "width: 15%"}/
%thead
%tr
%th= t("spree.name")
%th.actions
%tbody
- @taxons.each do |taxon|
%tr{class: cycle('odd', 'even'), id: spree_dom_id(taxon)}
%td
= taxon.name
%td.actions
= link_to_edit taxon.id, no_text: true
= link_to '', admin_taxon_path(taxon.id), method: :delete,
class: "icon_link with-tip icon-trash no-text",
data: { turbo: true, turbo_method: :delete, turbo_confirm: t(:are_you_sure) }

View File

@@ -0,0 +1,14 @@
= render partial: 'spree/admin/shared/configuration_menu'
- content_for :page_title do
= t(".title")
- content_for :page_actions do
%li
= button_link_to t("spree.admin.taxons.back_to_list"), spree.admin_taxons_path, icon: 'icon-arrow-left'
= form_with model: @taxon, url: admin_taxons_path, data: { turbo: true }, html: { multipart: true } do |f|
= render partial: 'form', locals: { f: f }
.form-buttons
= button t('actions.create'), 'icon-ok'
= button_link_to t('actions.cancel'), admin_taxons_url, icon: "icon-remove"

View File

@@ -9,8 +9,8 @@
%br
= @order.distributor.phone || ""
%br
%a{:href => "mailto:#{@order.distributor.contact.email}", :target => "_blank"}
= @order.distributor.contact.email
%a{:href => "mailto:#{order_reply_email(@order)}", :target => "_blank"}
= order_reply_email(@order)
%br
= @order.distributor.website || ""
%br

View File

@@ -12,6 +12,9 @@ export const useOpenAndCloseAsAModal = (controller) => {
}.bind(controller),
close: function (_event, remove = false) {
// Only execute close if there is an open modal
if (!document.querySelector("body").classList.contains('modal-open')) return;
this.modalTarget.classList.remove("in");
this.backgroundTarget.classList.remove("in");
document.querySelector("body").classList.remove("modal-open");

View File

@@ -0,0 +1,44 @@
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ['statusMessage']
connect() {
this.observer = new MutationObserver(this.updateCallback);
this.observer.observe(
this.statusMessageTarget,
{ attributes: true, attributeOldValue: true, attributeFilter: ['data-type'] }
);
}
// Callback to trigger warning modal
updateCallback(mutationsList) {
const newDataType = document.getElementById('status-message').getAttribute('data-type');
const actionName = document.getElementById('status-message').getAttribute('data-action-name');
if(!actionName) return;
for(let mutation of mutationsList) {
if (mutation.type === 'attributes' && mutation.attributeName === 'data-type') {
// Only trigger warning modal when notice display (notice) is preceeded by progress display (progress)
if(mutation.oldValue === 'progress' && newDataType === 'notice') {
// Hide all confirmation buttons in warning modal
document.querySelectorAll(
'#linked-order-warning-modal .modal-actions button.secondary'
).forEach((node) => {
node.style.display = 'none';
});
// Show the appropriate confirmation button, open warning modal, and return
document.querySelectorAll(
`#linked-order-warning-modal button[data-trigger-action=${actionName}]`
).forEach((node) => {
node.style.display = 'block';
})
document.querySelector('.warning-modal button.modal-target-trigger').click();
}
}
}
}
disconnect() {
this.observer.disconnect();
}
}

View File

@@ -34,7 +34,6 @@
@import "plugins/flatpickr-customization";
@import "plugins/powertip";
@import "plugins/jstree";
@import "plugins/select2";
@import "sections/orders";

View File

@@ -2,10 +2,18 @@
max-width: 615px;
}
.connected_app {
margin-bottom: 2rem;
&:not(:first-of-type) {
border-top: 1px solid $color-border;
}
}
.connected-app__head {
display: flex;
justify-content: space-between;
margin-bottom: 1em;
margin: 1em 0;
h3 {
margin-bottom: 1em;

View File

@@ -62,3 +62,7 @@ form.order_cycle {
}
}
}
#linked-order-warning-modal .reveal-modal{
width: 28rem;
}

View File

@@ -1,131 +0,0 @@
#taxonomy_tree {
> ul,
.jstree-icon {
background-image: none;
}
.jstree-icon {
@extend [class^="icon-"], :before;
}
.jstree-open > .jstree-icon {
@extend .icon-caret-down;
}
.jstree-closed > .jstree-icon {
@extend .icon-caret-right;
}
li {
background-image: none;
a {
background-color: very-light($color-3);
border: 1px solid $color-border;
color: $color-body-text;
font-weight: $font-weight-bold;
text-shadow: none;
width: 90%;
height: auto;
line-height: inherit;
padding: 5px 0 5px 10px;
margin-bottom: 10px;
.jstree-icon {
padding-left: 0px;
@extend .icon-move;
}
}
}
}
#vakata-dragged.jstree-apple .jstree-invalid,
#vakata-dragged.jstree-apple .jstree-ok,
#jstree-marker {
background-image: none !important;
background-color: transparent !important;
@extend [class^="icon-"], :before;
}
#vakata-dragged.jstree-apple .jstree-invalid {
@extend .icon-remove;
color: $color-5;
}
#vakata-dragged.jstree-apple .jstree-ok {
@extend .icon-ok;
color: $color-2;
}
#jstree-marker {
@extend .icon-caret-right;
color: $color-body-text !important;
width: 4px !important;
}
#jstree-marker-line {
@include border-radius($border-radius !important);
height: 0px !important;
margin-left: 5px !important;
margin-top: -2px !important;
border: none !important;
border-bottom: 1px solid $color-body-text !important;
background-color: very-light($color-3) !important;
-webkit-box-shadow: none !important;
-moz-box-shadow: none !important;
box-shadow: none !important;
}
#vakata-contextmenu {
background-color: $color-3 !important;
-moz-box-shadow: none !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
border: none !important;
@include border-radius($border-radius !important);
&:before {
content: "";
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid $color-3;
top: 0px;
margin-top: -10px;
left: 25px;
z-index: 1;
}
a {
color: $color-1 !important;
line-height: inherit !important;
padding: 5px 10px !important;
margin: 0 !important;
font-size: 90% !important;
&:hover {
@include border-radius($border-radius !important);
background-color: $color-2 !important;
border: none !important;
-moz-box-shadow: none !important;
-webkit-box-shadow: none !important;
line-height: inherit !important;
padding: 5px 10px !important;
margin: 0 !important;
}
}
li:first-child a:hover:before {
content: "";
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid $color-2;
top: 0px;
margin-top: -10px;
left: 25px;
z-index: 1;
}
li.vakata-separator {
display: none;
}
}

View File

@@ -220,15 +220,13 @@
justify-content: space-between;
align-items: center;
line-height: $btn-relaxed-height;
height: $btn-relaxed-height;
&.disabled-section {
display: none;
}
.pagination-description {
flex-grow: 1; // Grow to fill space
margin-right: 1em; // TODO: cleanup and use flex gap
}
.with-dropdown {
@@ -257,31 +255,20 @@
min-width: 15em;
.search-input {
width: 100%;
position: relative;
background-color: $lighter-grey;
border: 1px solid $lighter-grey;
border-radius: 4px;
height: $btn-relaxed-height;
line-height: $btn-relaxed-height;
&:has(input:focus),
&:has(input:active) {
border: 1px solid $dark-blue;
}
> input {
// Totally hide the input from its container
background-color: transparent;
border: none;
width: calc(100% - 30px); // 30px is the width of the search icon + padding
padding-left: 33px;
width: 100%;
}
&:before {
position: absolute;
font-family: FontAwesome;
content: "\f002";
color: $near-black;
font-size: 16px;
margin-top: 0.7rem;
margin-left: 10px;
}
}
@@ -435,33 +422,31 @@
}
}
@keyframes slideOutLeft {
@keyframes slideOutTop {
from {
transform: translateX(0);
opacity: 1;
transform: scaleY(1);
}
to {
transform: translateX(-100%);
opacity: 0;
transform: scaleY(0);
}
}
.slide-out {
animation: slideOutLeft 0.5s forwards;
transform-origin: top;
animation: slideOutTop 0.5s forwards;
}
@keyframes slideInRight {
@keyframes slideInTop {
from {
transform: translateX(100%);
opacity: 0;
transform: scaleY(0);
}
to {
transform: translateX(0);
opacity: 1;
transform: scaleY(1);
}
}
.slide-in {
animation: slideInRight 0.5s forwards;
transform-origin: top;
animation: slideInTop 0.5s forwards;
}
}

View File

@@ -39,7 +39,6 @@
@import "plugins/flatpickr-customization"; // admin_v3
@import "plugins/powertip"; // admin_v3
@import "../admin/plugins/jstree";
@import "sections/orders"; // admin_v3
@import "../admin/sections/products";

View File

@@ -40,6 +40,7 @@ Openfoodnetwork::Application.configure do
# Configure logging:
config.log_formatter = Logger::Formatter.new.tap { |f| f.datetime_format = "%Y-%m-%d %H:%M:%S" }
config.log_tags = [:request_id]
# Use a different cache store in production
config.cache_store = :redis_cache_store, {

View File

@@ -40,6 +40,7 @@ Openfoodnetwork::Application.configure do
# Configure logging:
config.log_formatter = Logger::Formatter.new.tap { |f| f.datetime_format = "%Y-%m-%d %H:%M:%S" }
config.log_tags = [:request_id]
# Use a different cache store in production
config.cache_store = :redis_cache_store, {

View File

@@ -44,7 +44,7 @@ ar:
spree/product:
name: "اسم المنتج"
price: "السعر"
primary_taxon: "نوع المنتج "
primary_taxon_id: "نوع المنتج "
shipping_category_id: "نوع الشحن"
variant_unit: "وحدة النوع"
variant_unit_name: "اسم وحدة النوع"
@@ -1133,16 +1133,19 @@ ar:
add_new: اضف جديد
no_voucher_yet: لا قسائم حتى الآن
connected_apps:
tagline: "By clicking Allow data sharing, you are sharing data between Open Food Network and the Discover Regenerative Portal, and agreeing to make specific data public on the Portal, which will also be publicly available on the API.\nIMPORTANT: Before you stop sharing and remove your listing, please first contact hello@regenerative.org.au to request a copy of your Discover Regenerative data."
loading: "جار التحميل"
description_html: |
<p>
Discover Regenerative is a showcase of Australias Regenerative Farmers, their produce/products, outcomes and achievements. It simplifies how business-to-business (B2B) / wholesale buyers can find regenerative produce and directly connect with Producers.
</p>
<p>
<a href="https://regenerative.org.au/" target="_blank"><b>Visit Discover Regenerative</b>
<i class="icon-external-link"></i></a>
</p>
affiliate_sales_data:
loading: "جار التحميل"
discover_regen:
tagline: "By clicking Allow data sharing, you are sharing data between Open Food Network and the Discover Regenerative Portal, and agreeing to make specific data public on the Portal, which will also be publicly available on the API.\nIMPORTANT: Before you stop sharing and remove your listing, please first contact hello@regenerative.org.au to request a copy of your Discover Regenerative data."
loading: "جار التحميل"
description_html: |
<p>
Discover Regenerative is a showcase of Australias Regenerative Farmers, their produce/products, outcomes and achievements. It simplifies how business-to-business (B2B) / wholesale buyers can find regenerative produce and directly connect with Producers.
</p>
<p>
<a href="https://regenerative.org.au/" target="_blank"><b>Visit Discover Regenerative</b>
<i class="icon-external-link"></i></a>
</p>
actions:
edit_profile: الإعدادات
properties: الخصائص
@@ -1235,6 +1238,8 @@ ar:
choose_products_from: "اختر المنتجات من:"
re_notify_producers: إعادة إخطار المنتجين
notify_producers_tip: سيؤدي هذا إلى إرسال بريد إلكتروني إلى كل منتج مع قائمة طلباتهم.
date_time_warning_modal_content:
cancel: 'إلغاء'
incoming:
incoming: "الوارد"
supplier: "المورد"
@@ -3297,6 +3302,7 @@ ar:
سيؤدي ذلك إلى ضبط مستوى المخزون لصفر على جميع المنتجات
المؤسسة غير موجودة في الملف الذي تم تحميله.
order_cycles:
unsaved_changes: "لم تحفظ التغييرات"
create_failure: "فشل في تكوين دورة الطلب"
update_success: 'تم تحديث دورة الطلب.'
update_failure: "فشل في تحديث دورة الطلب"
@@ -3633,8 +3639,6 @@ ar:
delivery: "موقعة ومختومة وتم التسليم"
start_date: "تاريخ البدء"
successfully_removed: "تمت الإزالة بنجاح"
taxonomy_edit: "التصنيف"
tree: "شجرة"
updating: "تحديث"
your_order_is_empty_add_product: "طلبك فارغ ، يرجى البحث عن المنتج أعلاه وإضافته"
add_product: "أضف منتج"
@@ -3748,9 +3752,7 @@ ar:
abbreviation: "الاختصار"
new_state: "محافظة جديدة"
payment_methods: "طرق الدفع"
taxonomies: "التصنيفات"
new_taxonomy: "تصنيف جديد"
back_to_taxonomies_list: "العودة إلى قائمة التصنيفات"
taxons: "فئات المنتجات"
shipping_methods: "طرق الشحن"
shipping_method: "طريقة الشحن"
shipment: "الشحنة"
@@ -4215,9 +4217,10 @@ ar:
total: "المجموع"
billing_address_name: "الاسم"
taxons:
index:
title: "فئات المنتجات"
form:
name: الاسم
permalink: الرابط الثابت
description: وصف
general_settings:
edit:

View File

@@ -44,7 +44,7 @@ ca:
spree/product:
name: "Nom del producte"
price: "Preu"
primary_taxon: "Categoria del producte"
primary_taxon_id: "Categoria del producte"
shipping_category_id: "Categoria d'enviament"
variant_unit: "Unitat de la variant"
variant_unit_name: "Nom de la unitat de la variant"
@@ -1197,7 +1197,10 @@ ca:
remove_logo_success: "Logo eliminat"
white_label_logo_link_label: "Enllaç del logotip utilitzat a botiga"
connected_apps:
loading: "S'està carregant"
affiliate_sales_data:
loading: "S'està carregant"
discover_regen:
loading: "S'està carregant"
actions:
edit_profile: Configuració
properties: Propietats
@@ -1289,6 +1292,8 @@ ca:
save_and_back_to_list: "Desa i torna a la llista"
choose_products_from: "Trieu Productes des de:"
notify_producers_tip: Això enviarà un correu electrònic a cada productor amb la llista dels seus productes demanats a les comandes.
date_time_warning_modal_content:
cancel: 'Cancel·lar'
incoming:
incoming: "Entrant"
supplier: "Proveïdora"
@@ -3278,6 +3283,7 @@ ca:
Això establirà el nivell d'estoc a zero en tots els productes per aquesta
organització que no estan presents al fitxer carregat.
order_cycles:
unsaved_changes: "Teniu canvis sense desar"
create_failure: "No s'ha pogut crear el cicle de comanda"
update_success: 'S''ha actualitzat el cicle de comanda.'
update_failure: "No s'ha pogut actualitzar el cicle de comanda"
@@ -3510,8 +3516,6 @@ ca:
delivery: "Signat, segellat, lliurat"
start_date: "Data d'inici"
successfully_removed: "S'ha suprimit correctament"
taxonomy_edit: "Edició de taxonomia"
tree: "Arbre"
updating: "Actualitzant"
your_order_is_empty_add_product: "La comanda està buida, si us plau cerca i afegeix un producte a dalt"
add_product: "Afegeix un producte"
@@ -3626,9 +3630,7 @@ ca:
abbreviation: "Abreviatura"
new_state: "Nou estat"
payment_methods: "Mètodes de Pagament"
taxonomies: "Taxonomies"
new_taxonomy: "Nova taxonomia"
back_to_taxonomies_list: "Torna a la llista de taxonomies"
taxons: "Tipus de productes"
shipping_methods: "Mètodes d'enviament"
shipping_method: "Mètode d'enviament"
shipment: "Enviament"
@@ -4093,9 +4095,10 @@ ca:
total: "Total"
billing_address_name: "Nom"
taxons:
index:
title: "Tipus de productes"
form:
name: Nom
permalink: Enllaç permanent
description: Descripció
general_settings:
edit:

View File

@@ -47,7 +47,7 @@ cy:
spree/product:
name: "Enw Cynnyrch"
price: "Pris"
primary_taxon: "Categori Cynnyrch"
primary_taxon_id: "Categori Cynnyrch"
shipping_category_id: "Categori dosbarthu."
variant_unit: "Uned Amrywiol"
variant_unit_name: "Enw Uned Amrywiol"
@@ -1254,10 +1254,15 @@ cy:
custom_tab_content: "Cynnwys y tab pwrpasol"
connected_apps:
legend: "Apiau cysylltiedig"
enable: "Caniatáu rhannu data"
disable: "Rhoir gorau i rannu"
loading: "Yn llwytho"
link_label: "Rheolir rhestru"
affiliate_sales_data:
enable: "Caniatáu rhannu data"
disable: "Rhoir gorau i rannu"
loading: "Yn llwytho"
discover_regen:
enable: "Caniatáu rhannu data"
disable: "Rhoir gorau i rannu"
loading: "Yn llwytho"
link_label: "Rheolir rhestru"
actions:
edit_profile: Gosodiadau
properties: Manylion
@@ -1350,6 +1355,8 @@ cy:
choose_products_from: "Dewis Cynnyrch gan:"
re_notify_producers: Ail-hysbysu cynhyrchwyr.
notify_producers_tip: Trwy hyn anfonir ebost at bob cynhyrchydd gyda rhestr o'r archebion.
date_time_warning_modal_content:
cancel: 'Canslo'
incoming:
incoming: "Yn dod i mewn"
supplier: "Cyflenwr"
@@ -3457,6 +3464,7 @@ cy:
This will set stock level to zero on all products for this
enterprise that are not present in the uploaded file.
order_cycles:
unsaved_changes: "Mae gennych chi newidiadau heb eu cadw"
create_failure: "Wedi methu creu cylch archebu"
update_success: 'Diweddarwyd eich cylch archebu'
update_failure: "Wedi methu diweddaru'r cylch archebu"
@@ -3746,8 +3754,6 @@ cy:
delivery: "Llofnodwyd, cadarnhawyd a chyflenwyd"
start_date: "Dyddiad cychwyn"
successfully_removed: "Llwyddwyd i ddileu"
taxonomy_edit: "Golygu tacsonomi"
tree: "Coeden"
updating: "Yn diweddaru"
your_order_is_empty_add_product: "Mae eich archeb yn wag, chwiliwch am ac ychwanegwch gynnyrch uchod"
add_product: "Ychwanegu Cynnyrch"
@@ -3862,9 +3868,7 @@ cy:
abbreviation: "Talfyriad"
new_state: "Sir Newydd"
payment_methods: "Dulliau Talu"
taxonomies: "Tacsonomeg"
new_taxonomy: "Tacsonomeg Newydd"
back_to_taxonomies_list: "Yn ôl i'r Rhestr Tacsonomeg"
taxons: "Categorïau Cynnyrch"
shipping_methods: "Dulliau Anfon"
shipping_method: "Dull Anfon"
shipment: "Llwyth"
@@ -4345,9 +4349,10 @@ cy:
total: "Cyfanswm"
billing_address_name: "Enw"
taxons:
index:
title: "Categorïau Cynnyrch"
form:
name: Enw
permalink: Permalink
meta_title: Meta Title
meta_description: Meta Description
meta_keywords: Meta Keywords

View File

@@ -33,7 +33,7 @@ de_CH:
spree/product:
name: "Produktname"
price: "Preis"
primary_taxon: "Produktkategorie"
primary_taxon_id: "Produktkategorie"
shipping_category_id: "Lieferkategorie"
variant_unit: "Varianteneinheit"
variant_unit_name: "Name der Varianteneinheit"
@@ -1108,7 +1108,10 @@ de_CH:
customers: Kunde
active: Aktiv?
connected_apps:
loading: "Wird geladen ..."
affiliate_sales_data:
loading: "Wird geladen ..."
discover_regen:
loading: "Wird geladen ..."
actions:
edit_profile: Einstellungen
properties: Eigenschaften
@@ -1201,6 +1204,8 @@ de_CH:
choose_products_from: "Wählen Sie Produkte von:"
re_notify_producers: Produzenten erneut benachrichtigen
notify_producers_tip: Benachrichtigen Sie die Produzenten per E-Mail über in diesem Bestellzyklus erhaltene Bestellungen.
date_time_warning_modal_content:
cancel: 'Stornieren'
incoming:
incoming: "Eingehend"
supplier: "Lieferant"
@@ -3207,6 +3212,7 @@ de_CH:
Dadurch wird der Lagerbestand für alle Produkte dieses Unternehmens,
die in der hochgeladenen Datei nicht vorhanden sind, auf Null gesetzt.
order_cycles:
unsaved_changes: "Sie haben nicht gespeicherte Änderungen."
create_failure: "Fehler beim Erstellen des Bestellzyklus."
update_success: 'Ihr Bestellzyklus wurde aktualisiert.'
update_failure: "Fehler beim Aktualisieren des Bestellzyklus."
@@ -3437,8 +3443,6 @@ de_CH:
UPS Ground: "UPS Ground"
start_date: "Anfangsdatum"
successfully_removed: "Erfolgreich gelöscht"
taxonomy_edit: "Kategorien bearbeiten"
tree: "Struktur"
updating: "Aktualisierung"
your_order_is_empty_add_product: "Ihre Bestellung ist leer. Suchen Sie oben ein Produkt und fügen Sie es hinzu."
add_product: "Produkt hinzufügen"
@@ -3551,9 +3555,7 @@ de_CH:
abbreviation: "Abkürzung"
new_state: "Neuer Kanton"
payment_methods: "Zahlungsarten"
taxonomies: "Kategorien"
new_taxonomy: "Neue Kategorie"
back_to_taxonomies_list: "Zurück zur Kategorieliste"
taxons: "Produktkategorien"
shipping_methods: "Lieferoptionen"
shipping_method: "Lieferoption"
shipment: "Lieferung"
@@ -3999,9 +4001,10 @@ de_CH:
total: "Gesamt"
billing_address_name: "Name"
taxons:
index:
title: "Produktkategorien"
form:
name: Name
permalink: Permalink
description: Beschreibung
general_settings:
edit:

View File

@@ -47,7 +47,7 @@ de_DE:
spree/product:
name: "Produktname"
price: "Preis"
primary_taxon: "Produktkategorie"
primary_taxon_id: "Produktkategorie"
shipping_category_id: "Lieferkategorie"
variant_unit: "Varianteneinheit"
variant_unit_name: "Name der Varianteneinheit"
@@ -1239,7 +1239,10 @@ de_DE:
custom_tab_content: "Inhalt des Reiters"
connected_apps:
legend: "Verknüpfte Apps"
loading: "Wird geladen ..."
affiliate_sales_data:
loading: "Wird geladen ..."
discover_regen:
loading: "Wird geladen ..."
actions:
edit_profile: Einstellungen
properties: Eigenschaften
@@ -1332,6 +1335,8 @@ de_DE:
choose_products_from: "Wählen Sie Produkte von:"
re_notify_producers: Produzenten erneut benachrichtigen
notify_producers_tip: Benachrichtigen Sie die Produzenten per E-Mail über in diesem Bestellzyklus erhaltene Bestellungen.
date_time_warning_modal_content:
cancel: 'Abbrechen'
incoming:
incoming: "Eingehend"
supplier: "Lieferant"
@@ -3447,6 +3452,7 @@ de_DE:
Dadurch wird der Lagerbestand für alle Produkte dieses Unternehmens,
die in der hochgeladenen Datei nicht vorhanden sind, auf Null gesetzt.
order_cycles:
unsaved_changes: "Sie haben nicht gespeicherte Änderungen."
create_failure: "Fehler beim Erstellen des Bestellzyklus."
update_success: 'Ihr Bestellzyklus wurde aktualisiert.'
update_failure: "Fehler beim Aktualisieren des Bestellzyklus."
@@ -3687,8 +3693,6 @@ de_DE:
delivery: "Lieferung"
start_date: "Anfangsdatum"
successfully_removed: "Erfolgreich gelöscht"
taxonomy_edit: "Kategorien bearbeiten"
tree: "Struktur"
updating: "Aktualisierung"
your_order_is_empty_add_product: "Ihre Bestellung ist leer. Suchen Sie oben ein Produkt und fügen Sie es hinzu."
add_product: "Produkt hinzufügen"
@@ -3803,9 +3807,7 @@ de_DE:
abbreviation: "Abkürzung"
new_state: "Neues Bundesland"
payment_methods: "Zahlungsarten"
taxonomies: "Kategorien"
new_taxonomy: "Neue Kategorie"
back_to_taxonomies_list: "Zurück zur Kategorieliste"
taxons: "Produktkategorien"
shipping_methods: "Lieferoptionen"
shipping_method: "Lieferoption"
shipment: "Lieferung"
@@ -4278,9 +4280,10 @@ de_DE:
total: "Gesamt"
billing_address_name: "Name"
taxons:
index:
title: "Produktkategorien"
form:
name: Name
permalink: Permalink
description: Beschreibung
general_settings:
edit:

View File

@@ -44,7 +44,7 @@ el:
spree/product:
name: "Όνομα Προϊόντος"
price: "Τιμή"
primary_taxon: "Κατηγορία προϊόντος"
primary_taxon_id: "Κατηγορία προϊόντος"
shipping_category_id: "Κατηγορία μεταφορικών"
variant_unit: "Μονάδα μέτρησης μεταβλητής"
variant_unit_name: "Όνομα μεταβλητής"
@@ -454,7 +454,7 @@ el:
admin_and_handling: Διαχείριση
profile: Προφίλ
supplier_only: Μόνο Προμηθευτής
has_shopfront: Διαθέτει σελίδα καταστήματος
has_shopfront: Ενεργό κατάστημα
weight: Βάρος
volume: Όγκος
items: Αντικείμενα
@@ -570,7 +570,7 @@ el:
email: Email
ends_at: Ολοκληρώνεται σε
ends_on: Ολοκληρώνεται στις
name: Όνονα
name: Όνομα
first_name: Όνομα
last_name: Επίθετο
on_hand: Στο χέρι
@@ -725,7 +725,7 @@ el:
title: "Χρεώσεις επιχείρησης"
enterprise: "Επιχείρηση"
fee_type: "Κατηγορίες αμοιβών"
name: "Όνονα"
name: "Όνομα"
tax_category: "Φορολογική Κατηγορία"
calculator: "Υπολογισμός"
calculator_values: "Υπολογισμός Αξίας"
@@ -875,7 +875,7 @@ el:
index:
notice: "Ειδοποίηση"
beta_notice: "Αυτή η λειτουργία είναι ακόμα σε δοκιμαστική έκδοση beta: ενδέχεται να αντιμετωπίσετε ορισμένα σφάλματα κατά τη χρήση της. Μη διστάσετε να επικοινωνήσετε με την υποστήριξη."
select_file: Επιλέξτε φύλλο εργασίας προς ανέβασμα
select_file: Επιλέξτε αρχείο CSV
spreadsheet: Φύλλο Εργασίας
choose_import_type: Επιλογή τύπου εισαγωγής
import_into: Τύπος εισαγωγής
@@ -886,7 +886,7 @@ el:
csv_templates: Πρότυπο CSV
product_list_template: Λήψη προτύπου λίστας προϊόντων
inventory_template: Λήψη προτύπου κατάλογου προϊόντων
category_values: Διαθέσιμες παραλλαγές Κατηγορίας
category_values: Διαθέσιμες κατηγορίες
product_categories: Κατηγορίες προϊόντος
tax_categories: Κατηγορίες Φορολόγησης
shipping_categories: Κατηγορίες Μεταφορικών
@@ -913,8 +913,8 @@ el:
not_found: δεν ήταν δυνατή η εύρεση της επιχείρησης στη βάση δεδομένων
no_name: Δεν υπάρχει όνομα
blank_enterprise: ορισμένα προϊόντα δεν έχουν συσχετιστεί με κάποια επιχείρηση
reset_absent?: Επαναφέρετε τα προϊόντα που λείπουν
reset_absent_tip: Ορίστε μηδενικό απόθεμα για όλα τα εξερχόμενα προϊόντα που δεν υπάρχουν στο αρχείο
reset_absent?: Σχετικά με τα υπόλοιπα προϊόντα
reset_absent_tip: Ορίστε μηδενικό απόθεμα για όλα τα προϊόντα που δεν υπάρχουν στο αρχείο
overwrite_all: Αντικατάσταση Όλων
overwrite_empty: Αντικατάσταση αν είναι κενό
default_stock: Ορισμός επιπέδου αποθέματος
@@ -1075,7 +1075,7 @@ el:
select_state: "Επέλεξε πόλη"
contact:
legend: "επικοινωνία"
name: Όνονα
name: Όνομα
name_placeholder: π.χ Gustav Plum
email_address: Δημόσια Διεύθυνση Ηλεκτρονικού Ταχυδρομείου
email_address_placeholder: π.χ. inquiries@fresh-food.com
@@ -1089,9 +1089,9 @@ el:
website_placeholder: π.χ. www.truffles.com
enterprise_fees:
legend: "Χρεώσεις επιχείρησης"
name: Όνονα
name: Όνομα
fee_type: Κατηγορίες αμοιβών
manage_fees: Διαχείρηση Αμοιβών Επιχειρήσεων
manage_fees: Διαχείριση αμοιβών επιχειρήσεων
no_fees_yet: Δεν έχετε τέλη επιχείρησης ακόμα.
create_button: Δημιούργησε έναν τώρα
enterprise_permissions:
@@ -1121,7 +1121,7 @@ el:
preferred_product_selection_from_inventory_only_no: Νέα προϊόντα πρέπει να προστεθούν στο απόθεμά μου πριν μπορέσουν να τοποθετηθούν στη βιτρίνα μου
payment_methods:
legend: "Τρόποι πληρωμής"
name: Όνονα
name: Όνομα
applies: Ισχύει?
manage: Διαχείριση Τρόπων Πληρωμής
no_method_yet: Δεν έχετε επιλέξει κανέναν τρόπο πληρωμής.
@@ -1129,7 +1129,7 @@ el:
create_one_button: Δημιούργησε έναν τώρα
primary_details:
legend: "Βασικές λεπτομέρειες"
name: Όνονα
name: Όνομα
name_placeholder: π.χ. Βιοδυναμικές τρούφες του καθηγητή Plum
groups: Ομάδες
groups_tip: Επέλεξε κάποια ομάδα ή περιοχή. Αυτό θα βοηθήσει τους καταναλωτές να βρίσκουν την επιχείρησή σου.
@@ -1158,7 +1158,7 @@ el:
ofn_uid_tip: Το μοναδικό αναγνωριστικό που χρησιμοποιείται για την ταυτοποίηση της επιχείρησης στο Open Food Network.
shipping_methods:
legend: "Τρόποι αποστολής"
name: "Όνονα"
name: "Όνομα"
applies: "Ενεργό;"
manage: "Διαχείριση Τρόπων Αποστολής"
create_button: "Δημιουργία Νέου Τρόπου Αποστολής"
@@ -1216,6 +1216,7 @@ el:
enabled: "Ενεργό"
disabled: "Απενεργοποιημένο"
social:
legend: "Κοινωνικός"
twitter_placeholder: "π.χ. @the_prof"
instagram_placeholder: "π.χ. the_prof"
facebook_placeholder: "π.χ. www.facebook.com/PageNameHere"
@@ -1288,28 +1289,34 @@ el:
custom_tab_content: "Περιεχόμενο για την προσαρμοσμένη καρτέλα"
connected_apps:
legend: "Μόνο οι διαχειριστές μπορούν να συνδέσουν εφαρμογές"
title: "Discover Regenerative"
tagline: "Να επιτρέψετε στο Discover Regenerative να δημοσιεύσει τις πληροφορίες της επιχείρησής σας."
enable: "Να επιτρέπεται η κοινοποίηση δεδομένων."
disable: "Διακοπή κοινοποίησης"
loading: "Φόρτωση"
need_to_be_manager: "Μόνο οι διαχειριστές μπορούν να συνδέουν εφαρμογές."
note: |
Ο λογαριασμός σας στο Open Food Network είναι συνδεδεμένος με το Discover Regenerative.
Προσθέστε ή ενημερώστε πληροφορίες για τη λίστα σας στο Discover Regenerative εδώ.
link_label: "Διαχείριση λίστας"
description_html: |
<p>
Οι επιλέξιμοι παραγωγοί μπορούν να παρουσιάσουν τις αναγεννητικές πιστοποιήσεις τους,
τις πρακτικές γεωργίας και άλλες πληροφορίες μέσω μιας καταχώρισης προφίλ.
Αυτό απλοποιεί τον τρόπο με τον οποίο οι αγοραστές μπορούν να βρουν αναγεννητικά προϊόντα και να συνδεθούν
με παραγωγούς που τους ενδιαφέρουν.
</p>
<p>
<a href="https://about.openfoodnetwork.org.au/regen-produce-portal/"
target="_blank"><b>Μάθετε περισσότερα για το Discover Regenerative</b>
<i class="icon-external-link"></i></a>
</p>
affiliate_sales_data:
enable: "Να επιτρέπεται η κοινοποίηση δεδομένων."
disable: "Διακοπή κοινοποίησης"
loading: "Φόρτωση"
need_to_be_manager: "Μόνο οι διαχειριστές μπορούν να συνδέουν εφαρμογές."
discover_regen:
title: "Discover Regenerative"
tagline: "Να επιτρέψετε στο Discover Regenerative να δημοσιεύσει τις πληροφορίες της επιχείρησής σας."
enable: "Να επιτρέπεται η κοινοποίηση δεδομένων."
disable: "Διακοπή κοινοποίησης"
loading: "Φόρτωση"
need_to_be_manager: "Μόνο οι διαχειριστές μπορούν να συνδέουν εφαρμογές."
note: |
Ο λογαριασμός σας στο Open Food Network είναι συνδεδεμένος με το Discover Regenerative.
Προσθέστε ή ενημερώστε πληροφορίες για τη λίστα σας στο Discover Regenerative εδώ.
link_label: "Διαχείριση λίστας"
description_html: |
<p>
Οι επιλέξιμοι παραγωγοί μπορούν να παρουσιάσουν τις αναγεννητικές πιστοποιήσεις τους,
τις πρακτικές γεωργίας και άλλες πληροφορίες μέσω μιας καταχώρισης προφίλ.
Αυτό απλοποιεί τον τρόπο με τον οποίο οι αγοραστές μπορούν να βρουν αναγεννητικά προϊόντα και να συνδεθούν
με παραγωγούς που τους ενδιαφέρουν.
</p>
<p>
<a href="https://about.openfoodnetwork.org.au/regen-produce-portal/"
target="_blank"><b>Μάθετε περισσότερα για το Discover Regenerative</b>
<i class="icon-external-link"></i></a>
</p>
actions:
edit_profile: Ρυθμήσεις
properties: Ιδιότητες
@@ -1350,7 +1357,7 @@ el:
loading_enterprises: ΦΌΡΤΩΣΕ ΤΙΣ ΕΠΙΧΕΙΡΉΣΕΙΣ
no_enterprises_found: Δεν βρέθηκε επιχείρηση.
search_placeholder: Αναζήτηση Με Όνομα
manage: Διαχείρηση
manage: Διαχείριση
manage_link: Ρυθμήσεις
producer?: "Παραγωγός?"
package: "Πακέτο"
@@ -1402,6 +1409,8 @@ el:
choose_products_from: "Επιλογή προϊόντων Από:"
re_notify_producers: Επαναλάβετε την ειδοποίηση προς τους παραγωγούς
notify_producers_tip: Αυτό θα στείλει ένα email σε κάθε παραγωγό με τη λίστα των παραγγελιών τους.
date_time_warning_modal_content:
cancel: 'Ακύρωση'
incoming:
incoming: "Εισερχόμενο"
supplier: "Προμηθευτής"
@@ -1469,7 +1478,7 @@ el:
add: Προσθήκη κομίστρου συντονιστή
filters:
search_by_order_cycle_name: "Αναζήτηση με όνομα Κύκλου Παραγγελίας ..."
involving: "Συμμετοχή"
involving: "Αφορά"
any_enterprise: "Οποιαδήποτε Επιχείρηση"
any_schedule: "Οποιοδήποτε Πρόγραμμα"
form:
@@ -1490,7 +1499,7 @@ el:
new_schedule: Νέο Πρόγραμμα
new_schedule_tooltip: Η συχνότητα με την οποία πραγματοποιείται μια συνδρομή
name_and_timing_form:
name: Όνονα
name: Όνομα
orders_open: Οι παραγγελίες ανοιγούν στις
coordinator: Συντονιστής
orders_close: Οι παραγγελίες είναι κλείστες
@@ -1546,6 +1555,7 @@ el:
primary_details: "Βασικές λεπτομέρειες"
address: "Διεύθυνση"
contact: "επικοινωνία"
social: "Κοινωνικός"
about: "Σχετικά"
business_details: "Λεπτομέρειες επιχείρησης "
images: "Εικόνες"
@@ -1654,6 +1664,7 @@ el:
table:
select_and_search: "Επιλέξτε φίλτρα και κάντε κλικ στο %{option} για να αποκτήσετε πρόσβαση στα δεδομένα σας."
headings:
hub: "Κεντρικό σημείο"
customer_code: "Κωδικός"
first_name: "Όνομα"
last_name: "Επίθετο"
@@ -2009,15 +2020,15 @@ el:
invoice_issued_on: "Το τιμολόγιο εκδόθηκε στις:"
order_number: "Αριθμός παραγγελίας:"
date_of_transaction: "Ημερομηνία συναλλαγής"
menu_1_title: "Καταστήματα"
menu_1_title: "Καταστηματα"
menu_1_url: "/shops"
menu_2_title: "Χάρτης"
menu_2_title: "Χαρτης"
menu_2_url: "/map"
menu_3_title: "Παραγωγοί"
menu_3_title: "Παραγωγοι"
menu_3_url: "/producers"
menu_4_title: "Ομάδες"
menu_4_title: "Ομαδες"
menu_4_url: "/groups"
menu_5_title: "Σχετικά"
menu_5_title: "Σχετικα"
menu_5_url: "https://about.openfoodnetwork.org.au/"
menu_6_title: "Σύνδεση"
menu_6_url: "https://openfoodnetwork.org/au/connect/"
@@ -2039,7 +2050,7 @@ el:
footer_links_md: "Σύνδεσμοι"
footer_about_url: "Σχετικά με τη διεύθυνση URL"
user_guide_link: "Σύνδεσμος οδηγού χρήστη"
name: Όνονα
name: Όνομα
first_name: Όνομα
last_name: Επίθετο
email: Email
@@ -2150,7 +2161,7 @@ el:
cookies_policy_link_desc: "Αν θέλετε να μάθετε περισσότερα, ελέγξτε το"
cookies_policy_link: "πολιτική cookies"
cookies_accept_button: "Αποδοχή Cookies"
home_shop: Αγόρασε Τώρα
home_shop: Αγορασε Τωρα
brandstory_headline: "Τροφή απευθείας από τον αγρό στο πιάτο μας"
brandstory_intro: "Κάποιες φορές ο καλύτερος τρόπος για να διορθώσεις το σύστημα είναι να ξεκινήσεις ένα νέο..."
brandstory_part1: "Ξεκινάμε από τη βάση. Με αγρότες και καλλιεργητές έτοιμους να πουν τις ιστορίες τους περήφανα και αληθινά. Με διανομείς έτοιμους να συνδέσουν τους ανθρώπους με προϊόντα δίκαια και ειλικρινά. Με αγοραστές που πιστεύουν ότι οι καλύτερες εβδομαδιαίες αποφάσεις αγορών μπορούν να αλλάξουν σοβαρά τον κόσμο."
@@ -2167,12 +2178,12 @@ el:
system_step3: "3. Παραλαβή / Αποστολή"
system_step3_text: "Περίμενε την παράδοση του φαγητού σου, ή επισκέψου τον παραγωγό ή το κατάστημα της περιοχής σου για μια πιο προσωπική επαφή. Η αγορά των τροφίμων είναι τόσο ποικιλόμορφη όσο η φύση ορίζει."
cta_headline: "Αγορές που κάνουν τον κόσμο καλύτερο."
cta_label: ίμαι έτοιμος"
cta_label: ιμαι ετοιμος"
stats_headline: "Δημιουργούμε ένα νέο σύστημα διατροφής."
stats_producers: "Παραγωγοί τροφίμων"
stats_shops: "Καταστήματα τροφίμων"
stats_shoppers: "Αγοραστές τροφίμων"
stats_orders: "Παραγγελίες τροφίμων"
stats_producers: "Παραγωγοι τροφιμων"
stats_shops: "Καταστηματα τροφιμων"
stats_shoppers: "Καταναλωτες τροφιμων"
stats_orders: "Παραγγελιες τροφιμων"
checkout_title: Ολοκλήρωση
checkout_now: Ολοκλήρωση τώρα
checkout_order_ready: Παραγγελία έτοιμη για
@@ -2324,7 +2335,7 @@ el:
enterprises_currently_open: "Οι παραγγελίες είναι προς το παρόν ανοιχτές"
enterprises_ready_for: "Έτοιμος για"
enterprises_choose: "Επιλέξτε πότε θέλετε την παραγγελία σας:"
maps_open: "Ανοιξε"
maps_open: "Άνοιγμα"
maps_closed: "Κλειστό"
map_title: "Χάρτης"
hubs_buy: "Ψώνια για:"
@@ -2764,9 +2775,9 @@ el:
admin_enterprise_groups_contact_country_id: "Χώρα"
admin_enterprise_groups_web_twitter: "π.χ. @the_prof"
admin_enterprise_groups_web_website_placeholder: "π.χ. www.fresh-food-supplier.gr"
admin_order_cycles: "Κύκλοι παραγγελίας διαχειριστή"
open: "Ανοιξε"
close: "Κλείσιμο"
admin_order_cycles: "Κύκλοι παραγγελιών διαχειριστή"
open: "Έναρξη"
close: "Λήξη"
create: "Δημιουργία"
search: "Αναζήτηση"
supplier: "Προμηθευτής"
@@ -2796,7 +2807,7 @@ el:
flexible_rate: "Ευέλικτο ποσοστό"
price_sack: "Price Sack"
new_order_cycles: "Κύκλοι νέας παραγγελίας"
new_order_cycle: "Κύκλος νέας παραγγελίας"
new_order_cycle: "Νέος κύκλος παραγγελίας"
new_order_cycle_tooltip: "Ανοίξτε το κατάστημα για μια ορισμένη χρονική περίοδο"
select_a_coordinator_for_your_order_cycle: "Επιλέξτε έναν συντονιστή για τον κύκλο παραγγελιών σας"
notify_producers: 'Ειδοποιήστε τους παραγωγούς'
@@ -2823,14 +2834,14 @@ el:
no_products: Χωρίς Προϊόντα
spree_admin_overview_enterprises_header: "Οι Επιχειρήσεις μου"
spree_admin_overview_enterprises_footer: "ΔΙΑΧΕΙΡΙΣΤΕ ΤΙΣ ΕΠΙΧΕΙΡΗΣΕΙΣ ΜΟΥ"
spree_admin_enterprises_hubs_name: "Όνονα"
spree_admin_enterprises_hubs_name: "Όνομα"
spree_admin_enterprises_create_new: "ΔΗΜΙΟΥΡΓΗΣΤΕ ΝΕΟ"
spree_admin_enterprises_shipping_methods: "Τρόποι αποστολής"
spree_admin_enterprises_fees: "Αμοιβή επιχείρησης"
spree_admin_enterprises_none_create_a_new_enterprise: "ΔΗΜΙΟΥΡΓΗΣΤΕ ΝΕΑ ΕΠΙΧΕΙΡΗΣΗ"
spree_admin_enterprises_none_text: "Δεν έχετε ακόμη επιχειρήσεις"
spree_admin_enterprises_tabs_hubs: "HUBS"
spree_admin_enterprises_producers_manage_products: ΙΑΧΕΙΡΙΣΗ ΠΡΟDΟΝΤΩΝ"
spree_admin_enterprises_producers_manage_products: ιαχείριση προϊόντων"
spree_admin_enterprises_create_new_product: "ΔΗΜΙΟΥΡΓΗΣΤΕ ΝΕΟ ΠΡΟDΟΝ"
spree_admin_single_enterprise_alert_mail_confirmation: "Παρακαλώ επιβεβαιώστε τη διεύθυνση email για"
spree_admin_single_enterprise_alert_mail_sent: "Έχουμε στείλει ένα email στο"
@@ -2856,17 +2867,17 @@ el:
spree_distributors_error: "Πρέπει να επιλεγεί τουλάχιστον ένας κόμβος"
spree_user_enterprise_limit_error: "^%{email} δεν επιτρέπεται να κατέχει άλλες επιχειρήσεις (το όριο είναι %{enterprise_limit})."
spree_variant_product_error: πρέπει να έχει τουλάχιστον μία παραλλαγή
your_profil_live: "Το προφίλ σας ζωντανά"
see: "Βλέπω"
live: "ζω"
manage: "Διαχείρηση"
your_profil_live: "Προφίλ καταστήματος"
see: "ΕΜΦΑΝΙΣΗ"
live: " "
manage: "Διαχείριση"
resend: "Ξαναστείλτε"
add_and_manage_products: "Προσθήκη και διαχείριση προϊόντων"
add_and_manage_order_cycles: "Προσθήκη &amp; διαχείριση κύκλων παραγγελίας"
add_and_manage_order_cycles: "Προσθήκη & διαχείριση κύκλων παραγγελίας"
manage_order_cycles: "Διαχείριση κύκλων παραγγελίας"
manage_products: "Διαχειριστείτε προϊόντα"
manage_products: "Διαχείριση προϊόντων"
edit_profile_details: "Επεξεργασία στοιχείων προφίλ"
edit_profile_details_etc: "Αλλάξτε την περιγραφή του προφίλ σας, εικόνες κ.λπ."
edit_profile_details_etc: "Αλλάξτε την περιγραφή του καταστήματός σας, εικόνες κ.λ.π."
order_cycle: "Κύκλος Παραγγελειών"
enterprise_relationships: "Δικαιώματα επιχείρησης"
first_name_begins_with: "Το όνομα αρχίζει με"
@@ -2886,12 +2897,13 @@ el:
admin_share_state: "Πόλη"
hub_sidebar_hubs: "Σημείο Συλλογής "
hub_sidebar_none_available: "Κανένα διαθέσιμο"
hub_sidebar_manage: "Διαχείρηση"
hub_sidebar_manage: "Διαχείριση"
hub_sidebar_at_least: "Πρέπει να επιλεγεί τουλάχιστον ένας κόμβος"
hub_sidebar_blue: "μπλε"
hub_sidebar_red: "το κόκκινο"
order_cycles_closed_for_hub: "Ο κόμβος που επιλέξατε είναι προσωρινά κλειστός για παραγγελίες. Παρακαλώ προσπαθήστε ξανά αργότερα."
report_customers_distributor: "Διανομέας"
report_customers_hub: "Κεντρικό σημείο"
report_customers_supplier: "Προμηθευτής"
report_customers_cycle: "Κύκλος Παραγγελειών"
report_customers_type: "Τύπος αναφοράς"
@@ -3502,6 +3514,7 @@ el:
Αυτό θα θέσει το επίπεδο αποθέματος σε μηδέν για όλα τα προϊόντα αυτής της
επιχείρησης που δεν υπάρχουν στο ανεβασμένο αρχείο.
order_cycles:
unsaved_changes: "Έχετε μη αποθηκευμένες αλλαγές"
create_failure: "Η δημιουργία κύκλου παραγγελίας απέτυχε"
update_success: 'Ο κύκλος παραγγελιών σας ενημερώθηκε.'
update_failure: "Η ενημέρωση του κύκλου παραγγελίας απέτυχε"
@@ -3677,7 +3690,7 @@ el:
import_date: "Ημερομηνία εισαγωγής"
delivery: "Διανομή"
temperature_controlled: "Ελεγχόμενη θερμοκρασία"
new_product: "Καινουργιο ΠΡΟΪΟΝ"
new_product: "Καινούργιο προϊόν"
administration: "Διαχείριση"
logged_in_as: "Συνδεδεμένος ως"
account: "Λογαριασμός"
@@ -3744,10 +3757,6 @@ el:
delivery: "Υπογράφηκε, σφραγίστηκε, παραδόθηκε"
start_date: "Ημερομηνία έναρξης"
successfully_removed: "Καταργήθηκε επιτυχώς"
taxonomy_edit: "Επεξεργασία ταξινόμησης"
taxonomy_tree_error: "Παρουσιάστηκε σφάλμα κατά την ενημέρωση του δέντρου ταξονομίας. "
taxonomy_tree_instruction: "Κάντε δεξί κλικ σε ένα αντικείμενο για να προσθέσετε, μετονομάσετε, αφαιρέσετε ή επεξεργαστείτε."
tree: "Δέντρο"
updating: "Ενημέρωση"
your_order_is_empty_add_product: "Η παραγγελία σας είναι κενή, αναζητήστε και προσθέστε ένα προϊόν παραπάνω"
add_product: "Προσθήκη Προϊόντος"
@@ -3863,9 +3872,7 @@ el:
abbreviation: "Συντομογραφία"
new_state: "Νέα Πολιτεία"
payment_methods: "τρόποι πληρωμής"
taxonomies: "Ταξινομίες"
new_taxonomy: "Νέα Ταξινομία"
back_to_taxonomies_list: "Επιστροφή στη λίστα ταξινομιών"
taxons: "Κατηγορίες προϊόντος"
shipping_methods: "Τρόποι αποστολής"
shipping_method: "Τρόπος Αποστολής"
shipment: "Αποστολή"
@@ -4234,8 +4241,8 @@ el:
image_upload_error: "Παρακαλώ ανεβάστε την εικόνα σε τύπο αρχείου JPG, PNG, GIF, SVG ή WEBP."
image_not_processable: "Η συνημμένη εικόνα δεν υποστηρίζεται."
new:
title: "Καινουργιο ΠΡΟΪΟΝ"
new_product: "Καινουργιο ΠΡΟΪΟΝ"
title: "Καινούργιο προϊόν"
new_product: "Καινούργιο προϊόν"
supplier: "Προμηθευτής"
supplier_select_placeholder: "Διαλέξτε ένα προμηθευτή"
product_name: "Ονομασία προϊόντος"
@@ -4348,9 +4355,10 @@ el:
total: "Σύνολο"
billing_address_name: "Όνομα"
taxons:
index:
title: "Κατηγορίες προϊόντος"
form:
name: Όνομα
permalink: Permalink
meta_title: Τίτλος Meta
meta_description: Περιγραφή Meta
meta_keywords: Λέξεις-κλειδιά Meta

View File

@@ -68,7 +68,7 @@ en:
spree/product:
name: "Product Name"
price: "Price"
primary_taxon: "Product Category"
primary_taxon_id: "Product Category"
shipping_category_id: "Shipping Category"
variant_unit: "Variant Unit"
variant_unit_name: "Variant Unit Name"
@@ -120,6 +120,8 @@ en:
attributes:
base:
card_expired: "has expired"
spree/product:
must_exist: 'must exist'
order_cycle:
attributes:
orders_close_at:
@@ -683,6 +685,8 @@ en:
terms_of_service_have_been_updated_html: "Open Food Network's Terms of Service have been updated: %{tos_link}"
terms_of_service: Read Terms of Service
accept_terms_of_service: Accept Terms of Service
# Pages
shopfront_settings:
embedded_shopfront_settings: "Embedded Shopfront Settings"
enable_embedded_shopfronts: "Enable Embedded Shopfronts"
@@ -739,6 +743,17 @@ en:
config_instructions_html: "Here you can configure the OFN Matomo integration. The Matomo URL below should point to the Matomo instance where the user tracking information will be sent to; if it is left empty, Matomo user tracking will be disabled. The Site ID field is not mandatory but useful if you are tracking more than one website on a single Matomo instance; it can be found on the Matomo instance console."
config_instructions_tag_manager_html: "Setting the Matomo Tag Manager URL enables Matomo Tag Manager. This tool allows you to set up analytics events. The Matomo Tag Manager URL is copied from the Install Code section of Matomo Tag Manager. Ensure you select the right container and environment as these options change the URL."
connected_app_settings:
edit:
title: "Connected app settings"
info_html: "Enabled apps will appear under Enterprise Settings > Connected Apps."
enabled_legend: "Enabled connected apps"
connected_apps_enabled:
discover_regen: Discover Regenerative portal
affiliate_sales_data: DFC anonymised orders API for research purposes
update:
resource: Connected app settings
customers:
index:
new_customer: "New Customer"
@@ -868,8 +883,10 @@ en:
filters:
search_products: Search for products
search_for_producers: Search for producers
select_producer: Select producer
all_producers: All producers
search_for_categories: Search for categories
select_category: Select category
all_categories: All categories
producers:
label: Producers
@@ -1358,28 +1375,45 @@ en:
custom_tab_content: "Content for custom tab"
connected_apps:
legend: "Connected apps"
title: "Discover Regenerative"
tagline: "Allow Discover Regenerative to publish your enterprise information."
enable: "Allow data sharing"
disable: "Stop sharing"
loading: "Loading"
need_to_be_manager: "Only managers can connect apps."
note: |
Your Open Food Network account is connected to Discover Regenerative.
Add or update information on your Discover Regenerative listing here.
link_label: "Manage listing"
description_html: |
<p>
Eligible producers can showcase their regenerative credentials,
farming practices and more through a profile listing.
Simplifying how buyers can find regenerative produce and connect
with producers of interest.
</p>
<p>
<a href="https://about.openfoodnetwork.org.au/regen-produce-portal/"
target="_blank"><b>Learn more about Discover Regenerative</b>
<i class="icon-external-link"></i></a>
</p>
affiliate_sales_data:
title: "INRAE / UFC QUE CHOISIR Research"
tagline: "Allow this research project to access your orders data anonymously"
enable: "Allow data sharing"
disable: "Stop sharing"
loading: "Loading"
need_to_be_manager: "Only managers can connect apps."
description_html: |
<p>
INRAE and UFC QUE CHOISIR are teaming up to study food prices in short food systems and compare them with prices in the supermarket, for a given set of products. The data that is used by INRAE is mixed with data coming from other short food chain platforms in France. No individual product prices will be publicly disclosed through this project.
</p>
<p>
<a href="https://apropos.coopcircuits.fr/"
target="_blank"><b>Learn more about this research project</b>
<i class="icon-external-link"></i></a>
</p>
discover_regen:
title: "Discover Regenerative"
tagline: "Allow Discover Regenerative to publish your enterprise information."
enable: "Allow data sharing"
disable: "Stop sharing"
loading: "Loading"
need_to_be_manager: "Only managers can connect apps."
note: |
Your Open Food Network account is connected to Discover Regenerative.
Add or update information on your Discover Regenerative listing here.
link_label: "Manage listing"
description_html: |
<p>
Eligible producers can showcase their regenerative credentials,
farming practices and more through a profile listing.
Simplifying how buyers can find regenerative produce and connect
with producers of interest.
</p>
<p>
<a href="https://about.openfoodnetwork.org.au/regen-produce-portal/"
target="_blank"><b>Learn more about Discover Regenerative</b>
<i class="icon-external-link"></i></a>
</p>
actions:
edit_profile: Settings
properties: Properties
@@ -1472,6 +1506,11 @@ en:
choose_products_from: "Choose Products From:"
re_notify_producers: Re notify producers
notify_producers_tip: This will send an email to each producer with the list of their orders.
date_time_warning_modal_content:
title: 'Orders are linked to this order cycle.'
content: 'If you wish to create a new order cycle, it is recommended to duplicate the order cycle first and then change the dates.'
proceed: 'Proceed anyway'
cancel: 'Cancel'
incoming:
incoming: "Incoming"
supplier: "Supplier"
@@ -3664,6 +3703,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
This will set stock level to zero on all products for this
enterprise that are not present in the uploaded file.
order_cycles:
unsaved_changes: "You have unsaved changes"
create_failure: "Failed to create order cycle"
update_success: 'Your order cycle has been updated.'
update_failure: "Failed to update order cycle"
@@ -3925,10 +3965,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using
delivery: "Signed, sealed, delivered"
start_date: "Start date"
successfully_removed: "Successfully Removed"
taxonomy_edit: "Taxonomy edit"
taxonomy_tree_error: "There was an error updating the taxonomy tree."
taxonomy_tree_instruction: "Right-click on an item to add, rename, remove or edit."
tree: "Tree"
updating: "Updating"
your_order_is_empty_add_product: "Your order is empty, please search for and add a product above"
add_product: "Add Product"
@@ -4052,10 +4088,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
new_state: "New State"
payment_methods: "Payment Methods"
taxonomies: "Taxonomies"
new_taxonomy: "New Taxonomy"
back_to_taxonomies_list: "Back to Taxonomies List"
taxons: "Product Categories"
shipping_methods: "Shipping Methods"
shipping_method: "Shipping Method"
@@ -4548,9 +4581,20 @@ See the %{link} to find out more about %{sitename}'s features and to start using
total: "Total"
billing_address_name: "Name"
taxons:
back_to_list: "Back to Product Categeory List"
index:
title: "Product Categories"
new_taxon: 'New product category'
new:
title: "New Product Category"
edit:
title: "Edit Product Category"
destroy:
delete_taxon:
success: "Successfully deleted the product category"
error: "Unable to delete the product category"
form:
name: Name
permalink: Permalink
meta_title: Meta Title
meta_description: Meta Description
meta_keywords: Meta Keywords

View File

@@ -28,7 +28,7 @@ en_AU:
spree/product:
name: "Product Name"
price: "Price"
primary_taxon: "Product Category"
primary_taxon_id: "Product Category"
shipping_category_id: "Shipping Category"
variant_unit: "Variant Unit"
variant_unit_name: "Variant Unit Name"
@@ -943,16 +943,19 @@ en_AU:
customers: Customer
active: Active?
connected_apps:
tagline: "By clicking Allow data sharing, you are sharing data between Open Food Network and the Discover Regenerative Portal, and agreeing to make specific data public on the Portal, which will also be publicly available on the API.\nIMPORTANT: Before you stop sharing and remove your listing, please first contact hello@regenerative.org.au to request a copy of your Discover Regenerative data."
loading: "Loading"
description_html: |
<p>
Discover Regenerative is a showcase of Australias Regenerative Farmers, their produce/products, outcomes and achievements. It simplifies how business-to-business (B2B) / wholesale buyers can find regenerative produce and directly connect with Producers.
</p>
<p>
<a href="https://regenerative.org.au/" target="_blank"><b>Visit Discover Regenerative</b>
<i class="icon-external-link"></i></a>
</p>
affiliate_sales_data:
loading: "Loading"
discover_regen:
tagline: "By clicking Allow data sharing, you are sharing data between Open Food Network and the Discover Regenerative Portal, and agreeing to make specific data public on the Portal, which will also be publicly available on the API.\nIMPORTANT: Before you stop sharing and remove your listing, please first contact hello@regenerative.org.au to request a copy of your Discover Regenerative data."
loading: "Loading"
description_html: |
<p>
Discover Regenerative is a showcase of Australias Regenerative Farmers, their produce/products, outcomes and achievements. It simplifies how business-to-business (B2B) / wholesale buyers can find regenerative produce and directly connect with Producers.
</p>
<p>
<a href="https://regenerative.org.au/" target="_blank"><b>Visit Discover Regenerative</b>
<i class="icon-external-link"></i></a>
</p>
actions:
edit_profile: Settings
properties: Properties
@@ -1050,6 +1053,8 @@ en_AU:
back_to_list: "Back To List"
save_and_back_to_list: "Save and Back to List"
choose_products_from: "Choose Products From:"
date_time_warning_modal_content:
cancel: 'Cancel'
incoming:
incoming: "Incoming"
supplier: "Supplier"
@@ -2929,6 +2934,7 @@ en_AU:
This will set stock level to zero on all products for this
enterprise that are not present in the uploaded file.
order_cycles:
unsaved_changes: "You have unsaved changes"
create_failure: "Failed to create order cycle"
update_success: 'Your order cycle has been updated.'
update_failure: "Failed to update order cycle"
@@ -3230,9 +3236,7 @@ en_AU:
abbreviation: "Abbreviation"
new_state: "New State"
payment_methods: "Payment Methods"
taxonomies: "Taxonomies"
new_taxonomy: "New Taxonomy"
back_to_taxonomies_list: "Back to Taxonomies List"
taxons: "Product Categories"
shipping_methods: "Shipping Methods"
shipping_method: "Shipping Method"
shipment: "Shipment"
@@ -3651,9 +3655,10 @@ en_AU:
total: "Total"
billing_address_name: "Name"
taxons:
index:
title: "Product Categories"
form:
name: Name
permalink: Permalink
description: Description
general_settings:
edit:

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