Compare commits

...

292 Commits

Author SHA1 Message Date
Maikel Linke
af3aed827a Update all locales with the latest Transifex translations 2024-08-30 09:59:49 +10:00
Maikel
f73be6447e Merge pull request #12824 from chahmedejaz/task/12823-fully-enable-admin-style-v3
[BUU] Fully enable admin_style_v3
2024-08-30 09:56:23 +10:00
Filipe
98eabc9d0f Merge pull request #12826 from chahmedejaz/bugfix/12815-fix-inconsistent-unit-values
Fix Inconsistent Behavior When Editing Products to mg Units in Hungarian Locale
2024-08-29 17:47:44 -06:00
Filipe
169cbbe1a1 Merge pull request #12793 from rioug/12768_fix_bulk_coop_report
Fix bulk coop report
2024-08-29 15:20:48 -06:00
Konrad
afc4c1e967 Merge pull request #12760 from wandji20/wb-OFN-12744
UX improvements for creation of new products [OFN-12744]
2024-08-29 17:22:36 +02:00
Rachel Arnould
d76c4bddb0 Merge pull request #12806 from drummer83/typo
Fix typos in "category" and unify capitals on "Back To Xyz List" buttons
2024-08-29 16:40:35 +02:00
Konrad
ae993784d8 Merge pull request #12813 from chahmedejaz/task/12810-increase-price-column-width
[BUU] Fix the too Narrow Price field
2024-08-29 15:22:27 +02:00
Filipe
d1abe22c32 Merge pull request #12805 from mkllnk/update-wicked-pdf-config-syntax
Update deprecated WickedPdf config syntax
2024-08-28 21:35:40 -06:00
Filipe
2817b8891e Merge pull request #12814 from dacook/buu/cell-padding
Increase column space in bulk products table
2024-08-28 21:30:03 -06:00
Filipe
ab87610d91 Merge pull request #12807 from kernal053/fix-broken-column-after-cloning
Fix broken column after cloning product
2024-08-28 21:03:53 -06:00
David Cook
54252f5444 Add comment 2024-08-29 09:42:59 +10:00
Ahmed Ejaz
7b6b0dbb78 12815: use en formatting for unit value conversion 2024-08-29 03:36:46 +05:00
Maikel
b2e15f52cf Merge pull request #12822 from johansenja/include-coverage-assets
Fix artifact path for simplecov report upload
2024-08-29 08:10:38 +10:00
Ahmed Ejaz
5d18c48b6c 12823: fully enable admin_style_v3 flag 2024-08-29 02:09:29 +05:00
Konrad
0c2dcbc50d Merge pull request #12812 from chahmedejaz/bugfix/12809-irresponsive-products-column-widths
[BUU] Fix Table width not responsive to the amount of selected columns
2024-08-28 16:45:07 +02:00
Joseph Johansen
4a028b2238 Fix artifact path for simplecov report upload 2024-08-28 11:09:01 +01:00
Maikel
43a366005c Merge pull request #12798 from johansenja/enable-simplecov
Set up code coverage metrics with simplecov
2024-08-28 12:07:53 +10:00
Maikel Linke
64470e977a Avoid name clash in simplecov task
A variable and a method were called the same.
Also made method calls more obvious with parenthesis.
2024-08-28 11:31:01 +10:00
Maikel Linke
a696c66857 Clean up tmp dir after test and avoid collisions
Best viewed ignoring whitespace changes.
2024-08-28 11:27:42 +10:00
Maikel Linke
cfeb0afbd4 Update all locales with the latest Transifex translations 2024-08-28 09:45:24 +10:00
Maikel Linke
4968e3dc8d Update all locales with the latest Transifex translations 2024-08-28 09:12:52 +10:00
David Cook
5324747f89 Reduce cell padding
This is closer to the original design:
* 6px between inputs
* 6px vertical padding on condensed rows
* 12px vertical padding on relaxed rows

Note that 'relaxed' rows are now smaller than the regular rows, which was not the original intention. But we haven't got spare time to do a broader review of table styles right now.
2024-08-26 16:53:19 +10:00
Gaetan Craig-Riou
ef2856d169 Remove added eventListener on disconnect
It's good practise to remove added event listener to avoid memory leak
2024-08-26 11:15:26 +10:00
Ahmed Ejaz
d9c79ee49c 12810: increase price width
- make it to 10% which makes sure that any price value acceptable by the system is displayed fully
- Reduce On Hand to 8% to make up for some space for the above
2024-08-24 17:37:59 +05:00
Ahmed Ejaz
d1f9b0855d 12809: fix the class name for the producer column in product 2024-08-24 02:05:04 +05:00
drummer83
b82726e7ba Unify the capital letters of the "Back To Xyz List" buttons and update specs
I decided to use the most frequently used version as the default, which is every word beginning with a capital letter
2024-08-23 13:23:57 +02:00
drummer83
7e7ab2e36d Fix typo in "categeory" (additional e) and update specs 2024-08-23 13:20:46 +02:00
kernal053
e35a5179bb Fix broken column after cloning product 2024-08-23 16:01:56 +05:30
Joseph Johansen
85385a1989 Rename uploads so combined report is listed first alphabetically 2024-08-23 11:26:45 +01:00
Joseph Johansen
a816814819 Update CI workflow to upload results and call rake task 2024-08-23 11:26:41 +01:00
wandji20
94b98867d8 Revert use of searchableDropdownComponent for product unit 2024-08-23 09:57:37 +01:00
wandji20
35ef1b9c7f Refactor new product dropdown to use SeachableDropdown component [OFN-12744] 2024-08-23 09:57:37 +01:00
wandji20
8badfb2505 Allow extra attributes to be passed to searchable dropdown component [OFN-12744] 2024-08-23 09:57:37 +01:00
wandji20
d61acd2cc1 Unify error messages and display on new product form [OFN-12744] 2024-08-23 09:57:37 +01:00
wandji20
7417cee20a Fix leaked trix editor event listener [OFN-12744] 2024-08-23 09:57:37 +01:00
Maikel Linke
d489c77efe Update deprecated WickedPdf config syntax
Avoids warning:

> WickedPdf.config= is deprecated and will be removed in future versions. Use WickedPdf.configure instead.
2024-08-23 15:57:59 +10:00
Maikel
e2423ad612 Merge pull request #12800 from filipefurtad0/adds_retry_option_on_edit_spec
Adds retry option to flaky edit_spec.rb
2024-08-23 12:02:59 +10:00
filipefurtad0
8b036113d9 Update all locales with the latest Transifex translations 2024-08-22 17:33:21 -06:00
Maikel
7f09044ae1 Merge pull request #12755 from johansenja/optimise-shops-page6
Optimise shops page: Enable injected enterprise data to be scoped to specific enterprise ids
2024-08-23 09:26:22 +10:00
Maikel
e9c7e1778c Merge pull request #12782 from mkllnk/reports
Add fallback report loading in case websockets fail
2024-08-23 09:23:42 +10:00
filipefurtad0
32cd14ef54 Adds slep(2) 2024-08-22 15:55:31 -06:00
filipefurtad0
ad585f1eab Adds retry option to flaky test case
...does so on another flaky test case
2024-08-22 15:55:31 -06:00
Filipe
d9368c1bfc Merge pull request #12781 from wandji20/wb-OFN-12775
Add warning popup to order cycle list [OFN-12775]
2024-08-22 15:39:27 -06:00
wandji20
b6bfb4e866 Refactor order cycle same_dates method 2024-08-22 22:21:17 +01:00
wandji20
4d222c61c6 Improve readability of order_cycle_set process method 2024-08-22 22:17:12 +01:00
wandji20
d599cf77a2 Fix failing specs 2024-08-22 22:17:12 +01:00
wandji20
8f7505d53d Refactor oc datetime content partial and include warning modal in oc list [OFN-12775] 2024-08-22 22:17:12 +01:00
wandji20
867e17301f Support passing oc confirmation params for oc list [OFN-12775] 2024-08-22 22:17:12 +01:00
wandji20
95135ca526 Move order_cycle datetime verification logic to service files [OFN-12775] 2024-08-22 22:17:12 +01:00
wandji20
de063fecb1 Move same_datetime_value method to OrderCycle model [OFN-12775] 2024-08-22 22:17:12 +01:00
Filipe
ef9ca33913 Merge pull request #12772 from drummer83/E500_sub
Display admin order page instead of shopfront order page to avoid error 500
2024-08-22 13:26:20 -06:00
Konrad
2710eafc33 Merge pull request #12779 from EdwardLi-coder/clearer_error_message_and_clean_up
Clearer error message and clean up for Product Categories
2024-08-22 18:15:50 +02:00
Joseph Johansen
4718fdb0be Optimise Spree::Taxon.supplied_taxons 2024-08-22 17:41:00 +02:00
Joseph Johansen
ce6ae04147 Add spec for confirming correct values when scoped 2024-08-22 17:41:00 +02:00
johansenja
1621f97fdb Use subject method in spec
Co-authored-by: Gaetan Craig-Riou <40413322+rioug@users.noreply.github.com>
2024-08-22 17:41:00 +02:00
Joseph Johansen
96f9894f41 Add enterprise_ids to cache key 2024-08-22 17:41:00 +02:00
Joseph Johansen
66b519bd1c Undo minor unneeded changes 2024-08-22 17:41:00 +02:00
Joseph Johansen
1b8e256e8a Add unit tests 2024-08-22 17:41:00 +02:00
Joseph Johansen
b73e529bfc Scope injected enterprise properties to specific enterprises 2024-08-22 17:41:00 +02:00
Konrad
25b1620707 Merge pull request #12743 from wandji20/wb-OFN-12214
(Fix) chore(deps): bump wicked_pdf from 2.6.3 to 2.8.0 [OFN-12214]
2024-08-22 17:34:20 +02:00
Joseph Johansen
5f9b14df9f Implement rake task to combine results 2024-08-21 13:02:31 +01:00
Joseph Johansen
922b853e3a Define specs for rake task to combine results 2024-08-21 13:02:31 +01:00
Joseph Johansen
8d747a2508 Enable coverage in base_spec_helper 2024-08-21 13:02:31 +01:00
Gaetan Craig-Riou
a50be52cde Merge pull request #12792 from openfoodfoundation/dependabot/npm_and_yarn/elliptic-6.5.7
Bump elliptic from 6.5.4 to 6.5.7
2024-08-21 09:56:19 +10:00
Gaetan Craig-Riou
d62d002bc5 Merge pull request #12780 from dacook/optimise-12714
Optimise subscriptions admin
2024-08-21 09:50:27 +10:00
Maikel
0c7448ba43 Merge pull request #12726 from mkllnk/order-stock-spec
Track (negative) stock for on-demand products and overrides
2024-08-20 15:05:16 +10:00
Gaetan Craig-Riou
24afd40414 Fix bulk coop supplier report 2024-08-20 14:32:35 +10:00
Maikel
524aec7868 Merge pull request #12788 from openfoodfoundation/dependabot/npm_and_yarn/mrujs-1.0.2
Bump mrujs from 1.0.1 to 1.0.2
2024-08-20 14:30:47 +10:00
David Cook
f2eb4b05f4 Avoid copying gigantic array 2024-08-20 14:00:13 +10:00
David Cook
ffaf1b4ea0 Cache distributor 2024-08-20 14:00:13 +10:00
David Cook
eb547f4861 Add test on number of db queries
Hmm, I think I seen an opportunity to clean up already.
2024-08-20 14:00:13 +10:00
David Cook
c9daca22d5 Rename spec to match class name 2024-08-20 14:00:13 +10:00
dependabot[bot]
7b22740289 Bump elliptic from 6.5.4 to 6.5.7
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.4 to 6.5.7.
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.4...v6.5.7)

---
updated-dependencies:
- dependency-name: elliptic
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-20 03:52:13 +00:00
Maikel
66c8a5c424 Merge pull request #12789 from chahmedejaz/bugfix/12783-fix-artifact-upload-names-conflict
Fix Artifact Upload Conflicts with Unique Node-Based Names
2024-08-20 13:51:13 +10:00
David Cook
cfeac651b6 Merge pull request #12785 from filipefurtad0/spec_for_#12768
Reproduces S2 bug #12768
2024-08-20 13:45:07 +10:00
EdwardLi-coder
05315ff8e0 delete spree.new_taxon 2024-08-20 08:11:49 +08:00
EdwardLi-coder
c4ee6b14ff clear error message and clean up 2024-08-20 08:11:49 +08:00
filipefurtad0
a78f46259c Asserts on the flash warning first
The warning first displays "Saving..." before confirming changes are saved.
I'm not entirelly sure, but it seems that asserting on this first, before asserting on other page elements stabilizes the spec.
2024-08-19 13:58:03 -06:00
filipefurtad0
1e79fde236 Reproduces S2 bug #12768 2024-08-19 13:58:03 -06:00
Ahmed Ejaz
a9fe52a4ff Revert "12783 - validate artifact upload"
This reverts commit 075f5499f8.
2024-08-19 23:29:12 +05:00
Ahmed Ejaz
075f5499f8 12783 - validate artifact upload 2024-08-19 23:16:39 +05:00
Ahmed Ejaz
ed61f7e7bc 12783: use unique artifact name based on node index 2024-08-19 22:57:04 +05:00
dependabot[bot]
bd6019036e Bump mrujs from 1.0.1 to 1.0.2
Bumps [mrujs](https://github.com/KonnorRogers/mrujs) from 1.0.1 to 1.0.2.
- [Changelog](https://github.com/KonnorRogers/mrujs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KonnorRogers/mrujs/compare/v1.0.1...v1.0.2)

---
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-19 09:31:52 +00:00
Konrad
0bbc3d2758 Merge pull request #12766 from mkllnk/magick-dep
Remove direct dependency on MiniMagick
2024-08-18 18:39:48 +02:00
Konrad
ae6182579b Merge pull request #12762 from EdwardLi-coder/change_colour_of_complete_order
change colour of "complete order"
2024-08-18 15:08:46 +02:00
Konrad
1e05811917 Merge pull request #12745 from johansenja/optimise-shops-page5
Improve effiency of OrderCycle.earliest_closing_times
2024-08-18 14:40:49 +02:00
Konrad
5f86a26f42 Merge pull request #12733 from wandji20/wb-OFN-6567
Update product variant unit display name, price, and total price width on different screen sizes [OFN-6567]
2024-08-18 13:25:24 +02:00
Konrad
3f1b907ef2 Merge pull request #12740 from wandji20/wb-OFN-12532-v1
Pluralize admin products search result [OFN-12532-v1]
2024-08-18 12:18:18 +02:00
Maikel Linke
d9c296cdb3 Stabilise flaky report specs
It looks like we have a new race condition that may only be a problem in
specs. If you trigger one report, it displays via websockets and then
you trigger the next report, there may still be some Javascript active
that displays the first report while the second one is loading. I'm not
sure if users would navigate that fast though.

To minimise the problem, I adjusted the polling to leave more room for
the default websockets response.
2024-08-16 17:08:57 +10:00
Maikel Linke
23aa762be2 Add fallback report loading in case websockets fail
This also resolves a race condition scenario. Even if the report gets
rendered via websockets before the controller response is rendered then
the fallback script loads the report again. It's not the most beautiful
but probably okay until we replace websockts altogether.

I'm leaving websockets in at the moment because it can render the report
much quicker than polling can.
2024-08-16 15:24:34 +10:00
Maikel Linke
61f2954973 Add TurboPower Rails gem for nice helpers
The helpers are more convenient but also allow us to add options like
smooth scrolling. I thought that looked nicer and is less confusing.

Please note that the `scroll_into_view` helper uses the `targets`
attribute instead of `target`. That attribute needs CSS selectors with a
leading `#` for ids.
2024-08-16 14:37:57 +10:00
Maikel Linke
d354317c73 Replace cable_ready report loading w/ Turbo stream
I'm adding TurboPower for the scroll_into_view action. It adds all the
nice CableReady actions to Turbo Streams.

Note that I omitted `block: "start"` because that option is the default
in Javascript. And the generic `action` method doesn't support
parameters like this anyway. I'll work on that in the next commit.

I also re-introduced a race condition by rendering the "loading"
indicator after triggering the report rendering job. I'm planning to
resolve that later.
2024-08-16 14:37:57 +10:00
Maikel Linke
19ef047193 Create observable reports blob early
This will allow us to check for completion of the report later in case
websockets fail.
2024-08-16 14:37:57 +10:00
Maikel Linke
037eb456c0 Remove unused controller ivar 2024-08-16 14:37:57 +10:00
Maikel Linke
aed78f3138 Simplify reports controller code branching 2024-08-16 14:37:57 +10:00
Maikel Linke
c31416c536 Separate showing and rendering report 2024-08-16 14:37:57 +10:00
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
drummer83
f154de66f9 Display admin order page instead of shopfront order page to avoid error 500 2024-08-14 14:44:59 +02:00
wandji20
4a30493716 Improve code style [OFN-12214] 2024-08-13 18:29:27 +01:00
wandji20
f325857e1f Strip end of long invoice table header names due to names not properly parsed when converting pdf to text [OFN-12214] 2024-08-13 18:23:27 +01:00
wandji20
58872a7017 Include mail stylsheet tag in invoice pdf files and mailer layout [OFN-12214] 2024-08-13 18:23:18 +01:00
wandji20
7392079d4d Move mail related styles to asset pipeline [OFN-12214] 2024-08-13 17:11:29 +01:00
wandji20
506126c1d3 Bump wicked_pdf to version 2.8.1 2024-08-13 17:11:29 +01:00
wandji20
fa004d0897 Remove wicked pdf stylsheet include tag in order report pdf [OFN-12214] 2024-08-13 17:11:29 +01:00
dependabot[bot]
db7add88fe chore(deps): bump wicked_pdf from 2.6.3 to 2.8.0
Bumps [wicked_pdf](https://github.com/mileszs/wicked_pdf) from 2.6.3 to 2.8.0.
- [Release notes](https://github.com/mileszs/wicked_pdf/releases)
- [Changelog](https://github.com/mileszs/wicked_pdf/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mileszs/wicked_pdf/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-13 17:11:29 +01:00
Ahmed Ejaz
b14cd08990 12698 - keep old UI URL as it is 2024-08-13 14:23:39 +05:00
Maikel Linke
f21aca234c Remove direct dependency on MiniMagick
We still depend on it as long as we set it as image processor but now we
can switch to another image processor without changing the code around
error handling.

We now rescue from unknown errors during image processing which should
make the app more robust.
2024-08-13 15:25:58 +10:00
EdwardLi-coder
93a6ff4b50 remove background-color 2024-08-13 09:38:20 +08: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
EdwardLi-coder
97a72dfde7 change colour of "complete order" 2024-08-12 12:01:02 +08: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
Joseph Johansen
5ca7f40a4e Add unit test 2024-08-06 16:12:13 +01:00
Joseph Johansen
a2f4df191a Improve effiency of OrderCycle.earliest_closing_times 2024-08-06 16:12:13 +01: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
wandji20
b49da46842 Pluralize admin products search result [OFN-12532-v1] 2024-08-06 08:52:51 +01: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
wandji20
2d24593403 Update product variant unit display name, price, and total price widths on different screen sizes [OFN-6567] 2024-08-02 13:03:42 +01: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 Linke
2201d2e8c2 VariantOverride with on_demand now overriding stock
Otherwise we would try to take stock from the producer stock level
without respecting their on-demand settings. So from now on:
If stock level or on_demand are set on the override then it's not using
producer stock levels.
2024-08-02 14:40:17 +10:00
Maikel Linke
b6c407971d Allow on-demand VariantOverride to track stock
We allowed this for producer stock and need to do the same for inventory
stock. This will allow us to create backorders for missing, but promised
stock.
2024-08-02 14:40:17 +10:00
Maikel Linke
cd8dc41b15 Update stock specs and add pending cases 2024-08-02 14:40:17 +10:00
Maikel Linke
a1887bdc76 Update stock levels of on-demand items
We weren't bothering with stock when items were on demand anyway. But we
want to track stock now so that we can backorder more when local stock
levels become negative.
2024-08-02 14:40:17 +10:00
Maikel Linke
e9f89362f4 Remove validation of positive stock when on demand
We weren't allowing negative stock to stop any bug from accidentally
drawing too much stock. But now we want to implement a backordering
logic that depends on negative stock levels to know how much is needed
to replenish stock levels.
2024-08-02 14:40:17 +10:00
Maikel Linke
675b7febdf Test stock logic on variant level
VariantOverrides are bolted onto variants to change their logic.
2024-08-02 14:40:17 +10:00
Maikel Linke
90fdf59415 Test current stock logic on shipment level
During checkout, stock is adjusted when a shipment is finalised. The
chain is:

* Order state change to complete.
* Trigger Order#finalize! which updates shipments.
* Trigger Shipment#finalize! which adjusts stock on the variant.
* A variant holds stock in stock items or in a variant override.
2024-08-02 14:40:17 +10: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
315 changed files with 4595 additions and 8375 deletions

View File

@@ -3,7 +3,7 @@ name: Build
on:
workflow_dispatch:
push:
branches-ignore:
branches-ignore:
- 'dependabot/**'
pull_request:
@@ -47,7 +47,7 @@ jobs:
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
with:
redis-version: 6
- name: Set up Ruby
@@ -81,11 +81,19 @@ jobs:
# RSpec split test files by test examples feature - it's optional
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/controllers/**/*_spec.rb}"
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/controllers/**/*_spec.rb}"
run: |
git show --no-patch # the commit being tested (which is often a merge due to actions/checkout@v3)
bin/rake knapsack_pro:rspec
- name: Save SimpleCov file
uses: actions/upload-artifact@v3
with:
name: simplecov-chunk-controllers-${{ matrix.ci_node_index }}
path: coverage/*.*
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
if-no-files-found: ignore
models:
runs-on: ubuntu-22.04
services:
@@ -116,7 +124,7 @@ jobs:
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
with:
redis-version: 6
- name: Set up Ruby
@@ -141,10 +149,18 @@ jobs:
# RSpec split test files by test examples feature - it's optional
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/models/**/*_spec.rb}"
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/models/**/*_spec.rb}"
run: |
bin/rake knapsack_pro:rspec
- name: Save SimpleCov file
uses: actions/upload-artifact@v3
with:
name: simplecov-chunk-models-${{ matrix.ci_node_index }}
path: coverage/*.*
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
if-no-files-found: ignore
system_admin:
runs-on: ubuntu-22.04
services:
@@ -175,7 +191,7 @@ jobs:
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
with:
redis-version: 6
- name: Set up Ruby
@@ -209,16 +225,24 @@ jobs:
# RSpec split test files by test examples feature - it's optional
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/admin/**/*_spec.rb}"
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/admin/**/*_spec.rb}"
run: |
bin/rake knapsack_pro:queue:rspec
- name: Archive failed tests screenshots
if: failure()
- name: Save SimpleCov file
uses: actions/upload-artifact@v3
with:
name: failed-tests-screenshots
name: simplecov-chunk-system-admin-${{ matrix.ci_node_index }}
path: coverage/*.*
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
if-no-files-found: ignore
- name: Archive failed tests screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: failed-admin_${{ matrix.ci_node_index }}-tests-screenshots
path: tmp/capybara/screenshots/*.png
retention-days: 7
if-no-files-found: ignore
@@ -247,13 +271,13 @@ jobs:
ci_node_total: [12]
# Indexes for parallel jobs (starting from zero).
# E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
steps:
- uses: actions/checkout@v3
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
with:
redis-version: 6
- name: Set up Ruby
@@ -287,16 +311,24 @@ jobs:
# RSpec split test files by test examples feature - it's optional
# https://knapsackpro.com/faq/question/how-to-split-slow-rspec-test-files-by-test-examples-by-individual-it
#KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/consumer/**/*_spec.rb}"
KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/consumer/**/*_spec.rb}"
run: |
bin/rake knapsack_pro:queue:rspec
- name: Archive failed tests screenshots
if: failure()
- name: Save SimpleCov file
uses: actions/upload-artifact@v3
with:
name: failed-tests-screenshots
name: simplecov-chunk-system-consumer-${{ matrix.ci_node_index }}
path: coverage/*.*
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
if-no-files-found: ignore
- name: Archive failed tests screenshots
if: failure()
uses: actions/upload-artifact@v4
with:
name: failed-consumer_${{ matrix.ci_node_index }}-tests-screenshots
path: tmp/capybara/screenshots/*.png
retention-days: 7
if-no-files-found: ignore
@@ -331,7 +363,7 @@ jobs:
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
with:
redis-version: 6
- name: Set up Ruby
@@ -371,13 +403,12 @@ jobs:
run: |
bin/rake knapsack_pro:rspec
- name: Archive failed tests screenshots
if: failure()
- name: Save SimpleCov file
uses: actions/upload-artifact@v3
with:
name: failed-tests-screenshots
path: tmp/capybara/screenshots/*.png
retention-days: 7
name: simplecov-chunk-engines-${{ matrix.ci_node_index }}
path: coverage/*.*
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
if-no-files-found: ignore
test_the_rest:
@@ -410,7 +441,7 @@ jobs:
- name: Setup redis
uses: supercharge/redis-github-action@1.4.0
with:
with:
redis-version: 6
- name: Set up Ruby
@@ -448,6 +479,14 @@ jobs:
run: |
bin/rake knapsack_pro:rspec
- name: Save SimpleCov file
uses: actions/upload-artifact@v3
with:
name: simplecov-chunk-the-rest-${{ matrix.ci_node_index }}
path: coverage/*.*
retention-days: 2 # doesn't need to be long, because it's the combined results that matter
if-no-files-found: ignore
non_knapsack_jest_karma:
runs-on: ubuntu-22.04
services:
@@ -485,3 +524,38 @@ jobs:
- name: Run jest tests
run: yarn jest
collate_simplecov_results:
runs-on: ubuntu-22.04
needs:
- controllers
- models
- engines
- system_admin
- system_consumer
- test_the_rest
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Download individual results from individual runners
uses: actions/download-artifact@v3
with:
pattern: simplecov-chunk-*
path: tmp/simplecov
merge-multiple: true
- name: collate results from each of the workers
run: bundle exec rake 'simplecov:collate_results[tmp/simplecov]'
- name: Upload collated results
uses: actions/upload-artifact@v3
with:
name: combined-simplecov-report
path: coverage/**/*.*
retention-days: 7
if-no-files-found: ignore

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

@@ -14,4 +14,6 @@ SimpleCov.start 'rails' do
add_filter '/log'
add_filter '/db'
add_filter '/lib/tasks/sample_data/'
formatter SimpleCov::Formatter::SimpleFormatter
end

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'
@@ -105,6 +104,7 @@ gem 'sidekiq-scheduler'
gem "cable_ready"
gem "stimulus_reflex"
gem "turbo_power"
gem "turbo-rails"
gem 'combine_pdf'

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)
@@ -787,6 +785,8 @@ GEM
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
railties (>= 6.0.0)
turbo_power (0.6.2)
turbo-rails (>= 1.3.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
@@ -837,7 +837,7 @@ GEM
websocket-extensions (0.1.5)
whenever (1.0.0)
chronic (>= 0.6.3)
wicked_pdf (2.6.3)
wicked_pdf (2.8.1)
activesupport
wkhtmltopdf-binary (0.12.6.7)
xml-simple (1.1.8)
@@ -863,7 +863,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
@@ -976,6 +975,7 @@ DEPENDENCIES
stripe
timecop
turbo-rails
turbo_power
valid_email2
validates_lengths_from_database
vcr

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

@@ -1,7 +1,11 @@
angular.module("admin.orderCycles").controller "OrderCyclesCtrl", ($scope, $q, Columns, StatusMessage, RequestMonitor, OrderCycles, Enterprises, Schedules, Dereferencer) ->
$scope.RequestMonitor = RequestMonitor
$scope.columns = Columns.columns
$scope.saveAll = -> OrderCycles.saveChanges($scope.order_cycles_form)
$scope.saveAll = ($event) ->
trigger_action = $($event.target).data('trigger-action')
confirm = $($event.target).data('confirm')
OrderCycles.saveChanges($scope.order_cycles_form, { trigger_action, confirm })
$scope.ordersCloseAtLimit = -31 # days
$scope.resetSelectFilters = ->

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

@@ -29,13 +29,13 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
deferred.reject(response)
deferred.promise
saveChanges: (form) ->
saveChanges: (form, params = {}) ->
changed = {}
for id, orderCycle of @byID when not @saved(orderCycle)
changed[Object.keys(changed).length] = @changesFor(orderCycle)
if Object.keys(changed).length > 0
StatusMessage.display('progress', "Saving...")
OrderCycleResource.bulkUpdate { order_cycle_set: { collection_attributes: changed } }, (data) =>
OrderCycleResource.bulkUpdate { order_cycle_set: { collection_attributes: changed }, confirm: params['confirm'], trigger_action: params['trigger_action'] }, (data) =>
for orderCycle in data
delete orderCycle.coordinator
delete orderCycle.producers
@@ -47,8 +47,10 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
, (response) =>
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])
else if (response.data.trigger_action)
StatusMessage.display('notice', t('js.order_cycles.unsaved_changes'), response.data.trigger_action)
else
StatusMessage.display('failure', "Oh no! I was unable to save your changes.")
StatusMessage.display('failure', t('js.order_cycles.bulk_save_error'))
saved: (order_cycle) ->
@diff(order_cycle).length == 0

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

@@ -0,0 +1 @@
@import './mail/all.scss';

View File

@@ -0,0 +1,3 @@
@import '../../../webpacker/css/admin/globals/palette.scss';
@import 'email';
@import 'payments_list';

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

@@ -11,7 +11,8 @@ class SearchableDropdownComponent < ViewComponent::Base
selected_option:,
placeholder_value:,
include_blank: false,
aria_label: ''
aria_label: '',
other_attrs: {}
)
@f = form
@name = name
@@ -20,11 +21,13 @@ class SearchableDropdownComponent < ViewComponent::Base
@placeholder_value = placeholder_value
@include_blank = include_blank
@aria_label = aria_label
@other_attrs = other_attrs
end
private
attr_reader :f, :name, :options, :selected_option, :placeholder_value, :include_blank, :aria_label
attr_reader :f, :name, :options, :selected_option, :placeholder_value, :include_blank,
:aria_label, :other_attrs
def classes
"fullwidth #{remove_search_plugin? ? 'no-input' : ''}"

View File

@@ -1 +1 @@
= f.select name, options_for_select(options, selected_option), { include_blank: }, class: classes, data:, 'aria-label': aria_label
= f.select name, options_for_select(options, selected_option), { include_blank: }, class: classes, data:, 'aria-label': aria_label, **other_attrs

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

@@ -2,6 +2,8 @@
module Admin
class OrderCyclesController < Admin::ResourceController
class DateTimeChangeError < StandardError; end
include ::OrderCyclesHelper
include PaperTrailLogging
@@ -62,9 +64,7 @@ module Admin
end
def update
@order_cycle_form = OrderCycles::FormService.new(@order_cycle, order_cycle_params,
spree_current_user)
@order_cycle_form = set_order_cycle_form
if @order_cycle_form.save
update_nil_subscription_line_items_price_estimate(@order_cycle)
respond_to do |format|
@@ -77,6 +77,9 @@ module Admin
elsif request.format.json?
render json: { errors: @order_cycle.errors.full_messages }, status: :unprocessable_entity
end
rescue DateTimeChangeError
render json: { trigger_action: params[:trigger_action] },
status: :unprocessable_entity
end
def bulk_update
@@ -90,6 +93,9 @@ module Admin
order_cycle = order_cycle_set.collection.find{ |oc| oc.errors.present? }
render json: { errors: order_cycle.errors.full_messages }, status: :unprocessable_entity
end
rescue DateTimeChangeError
render json: { trigger_action: params[:trigger_action] },
status: :unprocessable_entity
end
def bulk_update_nil_subscription_line_items_price_estimate
@@ -235,7 +241,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
@@ -270,7 +276,10 @@ module Admin
end
def order_cycle_set
@order_cycle_set ||= Sets::OrderCycleSet.new(@order_cycles, order_cycle_bulk_params)
@order_cycle_set ||= Sets::OrderCycleSet.new(
@order_cycles, { **order_cycle_bulk_params,
confirm_datetime_change: params[:confirm], error_class: DateTimeChangeError }
)
end
def require_order_cycle_set_params
@@ -294,5 +303,14 @@ module Admin
collection_attributes: [:id] + PermittedAttributes::OrderCycle.basic_attributes
).to_h.with_indifferent_access
end
def set_order_cycle_form
OrderCycles::FormService.new(
@order_cycle, order_cycle_params.merge(
{ confirm_datetime_change: params[:order_cycle][:confirm],
error_class: DateTimeChangeError }
), spree_current_user
)
end
end
end

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

@@ -6,7 +6,7 @@ module Admin
include ReportsActions
helper ReportsHelper
before_action :authorize_report, only: [:show]
before_action :authorize_report, only: [:show, :create]
# Define model class for Can? permissions
def model_class
@@ -20,14 +20,17 @@ module Admin
end
def show
@report = report_class.new(spree_current_user, params, render: render_data?)
@rendering_options = rendering_options # also stores user preferences
@report = report_class.new(spree_current_user, params, render: false)
@rendering_options = rendering_options
if render_data?
render_in_background
else
show_report
end
show_report
end
def create
@report = report_class.new(spree_current_user, params, render: true)
update_rendering_options
render_in_background
end
private
@@ -54,31 +57,15 @@ module Admin
@variant_serialized = Api::Admin::VariantSerializer.new(variant)
end
def render_data?
request.post?
end
def render_in_background
cable_ready[ScopedChannel.for_id(params[:uuid])]
.inner_html(
selector: "#report-go",
html: helpers.button(t(:go), "report__submit-btn", "submit", disabled: true)
).inner_html(
selector: "#report-table",
html: render_to_string(partial: "admin/reports/loading")
).scroll_into_view(
selector: "#report-table",
block: "start"
).broadcast
@blob = ReportBlob.create_for_upload_later!(report_filename)
ReportJob.perform_later(
report_class:, user: spree_current_user, params:,
format: report_format,
filename: report_filename,
blob: @blob,
channel: ScopedChannel.for_id(params[:uuid]),
)
head :no_content
end
end
end

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

@@ -88,14 +88,10 @@ module ReportsActions
display_header_row: false
}
end
update_rendering_options
@rendering_options
end
def update_rendering_options
return unless request.post?
@rendering_options.update(
rendering_options.update(
options: {
fields_to_show: params[:fields_to_show],
display_summary_row: params[:display_summary_row].present?,

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

@@ -61,15 +61,6 @@ module ApplicationHelper
classes << shopfront_layout
end
def pdf_stylesheet_pack_tag(source)
if running_in_development?
options = { media: "all", host: "#{Webpacker.dev_server.host}:#{Webpacker.dev_server.port}" }
stylesheet_pack_tag(source, **options)
else
wicked_pdf_stylesheet_pack_tag(source)
end
end
def cache_with_locale(key = nil, options = {}, &block)
cache(cache_key_with_locale(key, I18n.locale), options) do
yield(block)

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

@@ -8,11 +8,13 @@ module InjectionHelper
include OrderCyclesHelper
def inject_enterprises(enterprises = nil)
enterprises ||= default_enterprise_query
inject_json_array(
"enterprises",
enterprises || default_enterprise_query,
enterprises,
Api::EnterpriseSerializer,
enterprise_injection_data,
enterprise_injection_data(enterprises.map(&:id)),
)
end
@@ -57,15 +59,16 @@ module InjectionHelper
inject_json_array "enterprises",
enterprises_and_relatives,
Api::EnterpriseSerializer,
enterprise_injection_data
enterprise_injection_data(enterprises_and_relatives.map(&:id))
end
def inject_group_enterprises(group)
enterprises = group.enterprises.activated.visible.all
inject_json_array(
"enterprises",
group.enterprises.activated.visible.all,
enterprises,
Api::EnterpriseSerializer,
enterprise_injection_data,
enterprise_injection_data(enterprises.map(&:id)),
)
end
@@ -73,7 +76,7 @@ module InjectionHelper
inject_json "currentHub",
current_distributor,
Api::EnterpriseSerializer,
enterprise_injection_data
enterprise_injection_data(current_distributor ? [current_distributor.id] : nil)
end
def inject_current_order
@@ -153,7 +156,9 @@ module InjectionHelper
Enterprise.activated.includes(address: [:state, :country]).all
end
def enterprise_injection_data
@enterprise_injection_data ||= { data: OpenFoodNetwork::EnterpriseInjectionData.new }
def enterprise_injection_data(enterprise_ids)
{
data: OpenFoodNetwork::EnterpriseInjectionData.new(enterprise_ids)
}
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

@@ -9,12 +9,12 @@ class ReportJob < ApplicationJob
NOTIFICATION_TIME = 5.seconds
def perform(report_class:, user:, params:, format:, filename:, channel: nil)
def perform(report_class:, user:, params:, format:, blob:, channel: nil)
start_time = Time.zone.now
report = report_class.new(user, params, render: true)
result = report.render_as(format)
blob = ReportBlob.create!(filename, result)
blob.store(result)
execution_time = Time.zone.now - start_time

View File

@@ -6,14 +6,14 @@
# `count_on_hand` can either be: nil or a number
#
# This means that a variant override can be in six different stock states
# but only three of them are valid.
# but only four of them are valid.
#
# | on_demand | count_on_hand | stock_overridden? | use_producer_stock_settings? | valid? |
# |-----------|---------------|-------------------|------------------------------|--------|
# | 1 | nil | false | false | true |
# | 1 | nil | true | false | true |
# | 0 | x | true | false | true |
# | nil | nil | false | true | true |
# | 1 | x | ? | ? | false |
# | 1 | x | true | false | true |
# | 0 | nil | ? | ? | false |
# | nil | x | ? | ? | false |
#
@@ -27,7 +27,6 @@ module StockSettingsOverrideValidation
def require_compatible_on_demand_and_count_on_hand
disallow_count_on_hand_if_using_producer_stock_settings
disallow_count_on_hand_if_on_demand
require_count_on_hand_if_limited_stock
end
@@ -39,14 +38,6 @@ module StockSettingsOverrideValidation
errors.add(:count_on_hand, error_message)
end
def disallow_count_on_hand_if_on_demand
return unless on_demand? && count_on_hand.present?
error_message = I18n.t("count_on_hand.on_demand_but_count_on_hand_set",
scope: i18n_scope_for_stock_settings_override_validation_error)
errors.add(:count_on_hand, error_message)
end
def require_count_on_hand_if_limited_stock
return unless on_demand == false && count_on_hand.blank?

View File

@@ -96,7 +96,7 @@ module VariantStock
# Here we depend only on variant.total_on_hand and variant.on_demand.
# This way, variant_overrides only need to override variant.total_on_hand and variant.on_demand.
def fill_status(quantity)
on_hand = if total_on_hand >= quantity || on_demand
on_hand = if total_on_hand.to_i >= quantity || on_demand
quantity
else
[0, total_on_hand].max
@@ -112,8 +112,7 @@ module VariantStock
#
# This enables us to override this behaviour for variant overrides
def move(quantity, originator = nil)
# Don't change variant stock if variant is on_demand or has been deleted
return if on_demand || deleted_at
return if deleted_at
raise_error_if_no_stock_item_available

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

@@ -477,7 +477,7 @@ class Enterprise < ApplicationRecord
return unless image.variable?
image_variant_url_for(image.variant(name))
rescue ActiveStorage::Error, MiniMagick::Error, ActionView::Template::Error => e
rescue StandardError => e
Bugsnag.notify "Enterprise ##{id} #{image.try(:name)} error: #{e.message}"
Rails.logger.error(e.message)

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
@@ -147,17 +148,20 @@ class OrderCycle < ApplicationRecord
# Find the earliest closing times for each distributor in an active order cycle, and return
# them in the format {distributor_id => closing_time, ...}
def self.earliest_closing_times
Hash[
Exchange.
outgoing.
joins(:order_cycle).
merge(OrderCycle.active).
group('exchanges.receiver_id').
select("exchanges.receiver_id AS receiver_id,
MIN(order_cycles.orders_close_at) AS earliest_close_at").
map { |ex| [ex.receiver_id, ex.earliest_close_at.to_time] }
]
#
# Optionally, specify some distributor_ids as a parameter to scope the results
def self.earliest_closing_times(distributor_ids = nil)
cycles = Exchange.
outgoing.
joins(:order_cycle).
merge(OrderCycle.active).
group('exchanges.receiver_id')
cycles = cycles.where(receiver_id: distributor_ids) if distributor_ids.present?
cycles.pluck("exchanges.receiver_id AS receiver_id",
"MIN(order_cycles.orders_close_at) AS earliest_close_at")
.to_h
end
def attachable_distributor_payment_methods
@@ -313,6 +317,13 @@ class OrderCycle < ApplicationRecord
coordinator.sells == 'own'
end
def same_datetime_value(attribute, string)
return true if self[attribute].blank? && string.blank?
return false if self[attribute].blank? || string.blank?
DateTime.parse(string).to_fs(:short) == self[attribute]&.to_fs(:short)
end
private
def opening?

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

@@ -5,7 +5,7 @@ class ReportBlob < ActiveStorage::Blob
# AWS S3 limits URL expiry to one week.
LIFETIME = 1.week
def self.create!(filename, content)
def self.create_locally!(filename, content)
create_and_upload!(
io: StringIO.new(content),
filename:,
@@ -15,11 +15,34 @@ class ReportBlob < ActiveStorage::Blob
)
end
def self.create_for_upload_later!(filename)
# ActiveStorage discourages modifying a blob later but we need a blob
# before we know anything about the report file. It enables us to use the
# same blob in the controller to read the result.
create_before_direct_upload!(
filename:,
byte_size: 0,
checksum: "0",
content_type: content_type(filename),
service_name: :local,
).tap do |blob|
ActiveStorage::PurgeJob.set(wait: LIFETIME).perform_later(blob)
end
end
def self.content_type(filename)
MIME::Types.of(filename).first&.to_s || "application/octet-stream"
end
def store(content)
io = StringIO.new(content)
upload(io, identify: false)
save!
end
def result
return if checksum == "0"
@result ||= download.force_encoding(Encoding::UTF_8)
end

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
@@ -245,7 +244,7 @@ module Spree
# Reports page
can [:admin, :index, :show], ::Admin::ReportsController
can [:admin, :show, :customers, :orders_and_distributors, :group_buys, :payments,
can [:admin, :show, :create, :customers, :orders_and_distributors, :group_buys, :payments,
:orders_and_fulfillment, :products_and_inventory, :order_cycle_management,
:packing, :enterprise_fee_summary, :bulk_coop], :report
end
@@ -325,7 +324,7 @@ module Spree
end
# Reports page
can [:admin, :index, :show], ::Admin::ReportsController
can [:admin, :index, :show, :create], ::Admin::ReportsController
can [:admin, :customers, :group_buys, :sales_tax, :payments,
:orders_and_distributors, :orders_and_fulfillment, :products_and_inventory,
:order_cycle_management, :xero_invoices, :enterprise_fee_summary, :bulk_coop], :report

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

@@ -33,7 +33,7 @@ module Spree
return self.class.default_image_url(size) unless attachment.attached?
image_variant_url_for(variant(size))
rescue ActiveStorage::Error, MiniMagick::Error, ActionView::Template::Error => e
rescue StandardError => e
Bugsnag.notify "Product ##{viewable_id} Image ##{id} error: #{e.message}"
Rails.logger.error(e.message)

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
@@ -262,9 +263,12 @@ module Spree
# Format as per WeightsAndMeasures (todo: re-orgnaise maybe after product/variant refactor)
def variant_unit_with_scale
# Our code is based upon English based number formatting with a period `.`
scale_clean = ActiveSupport::NumberHelper.number_to_rounded(variant_unit_scale,
precision: nil,
strip_insignificant_zeros: true)
significant: false,
strip_insignificant_zeros: true,
locale: :en)
[variant_unit, scale_clean].compact_blank.join("_")
end
@@ -288,6 +292,15 @@ 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?
errors.add(:primary_taxon_id, :blank) unless Spree::Taxon.find_by(id: primary_taxon_id)
errors.add(:supplier_id, :blank) unless Enterprise.find_by(id: supplier_id)
end
def update_units
return unless saved_change_to_variant_unit? || saved_change_to_variant_unit_name?

View File

@@ -87,16 +87,20 @@ module Spree
# Return the services (pickup, delivery) that different distributors provide, in the format:
# {distributor_id => {pickup: true, delivery: false}, ...}
def self.services
Hash[
Spree::ShippingMethod.
joins(:distributor_shipping_methods).
group('distributor_id').
select("distributor_id").
select("BOOL_OR(spree_shipping_methods.require_ship_address = 'f') AS pickup").
select("BOOL_OR(spree_shipping_methods.require_ship_address = 't') AS delivery").
map { |sm| [sm.distributor_id.to_i, { pickup: sm.pickup, delivery: sm.delivery }] }
]
#
# Optionally, specify some distributor_ids as a parameter to scope the results
def self.services(distributor_ids = nil)
methods = Spree::ShippingMethod.joins(:distributor_shipping_methods).group('distributor_id')
if distributor_ids.present?
methods = methods.where(distributor_shipping_methods: { distributor_id: distributor_ids })
end
methods.
pluck(Arel.sql("distributor_id"),
Arel.sql("BOOL_OR(spree_shipping_methods.require_ship_address = 'f') AS pickup"),
Arel.sql("BOOL_OR(spree_shipping_methods.require_ship_address = 't') AS delivery")).
to_h { |(distributor_id, pickup, delivery)| [distributor_id.to_i, { pickup:, delivery: }] }
end
def self.backend

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,40 +23,21 @@ 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
taxons = {}
#
# Optionally, specify some enterprise_ids to scope the results
def self.supplied_taxons(enterprise_ids = nil)
taxons = Spree::Taxon.joins(variants: :supplier)
Spree::Taxon.
joins(variants: :supplier).
select('spree_taxons.*, enterprises.id AS enterprise_id').
each do |t|
taxons[t.enterprise_id.to_i] ||= Set.new
taxons[t.enterprise_id.to_i] << t.id
end
taxons = taxons.where(enterprises: { id: enterprise_ids }) if enterprise_ids.present?
taxons
.pluck('spree_taxons.id, enterprises.id AS enterprise_id')
.each_with_object({}) do |(taxon_id, enterprise_id), collection|
collection[enterprise_id.to_i] ||= Set.new
collection[enterprise_id.to_i] << taxon_id
end
end
# Find all the taxons of distributed products for each enterprise, indexed by enterprise.
@@ -72,7 +45,9 @@ module Spree
# or :current taxons (distributed in an open order cycle).
#
# Format: {enterprise_id => [taxon_id, ...]}
def self.distributed_taxons(which_taxons = :all)
#
# Optionally, specify some enterprise_ids to scope the results
def self.distributed_taxons(which_taxons = :all, enterprise_ids = nil)
ents_and_vars = ExchangeVariant.joins(exchange: :order_cycle).merge(Exchange.outgoing)
.select("DISTINCT variant_id, receiver_id AS enterprise_id")
@@ -85,18 +60,14 @@ module Spree
INNER JOIN (#{ents_and_vars.to_sql}) AS ents_and_vars
ON spree_variants.id = ents_and_vars.variant_id")
if enterprise_ids.present?
taxons = taxons.where(ents_and_vars: { enterprise_id: enterprise_ids })
end
taxons.each_with_object({}) do |t, ts|
ts[t.enterprise_id.to_i] ||= Set.new
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

@@ -15,7 +15,9 @@ class VariantOverride < ApplicationRecord
# Need to ensure this can be set by the user.
validates :default_stock, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
validates :price, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
validates :count_on_hand, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
validates :count_on_hand, numericality: {
greater_than_or_equal_to: 0, unless: :on_demand?
}, allow_nil: true
default_scope { where(permission_revoked_at: nil) }
@@ -36,9 +38,8 @@ class VariantOverride < ApplicationRecord
end
def stock_overridden?
# If count_on_hand is present, it means on_demand is false
# See StockSettingsOverrideValidation for details
count_on_hand.present?
# Testing for not nil because for a boolean `false.present?` is false.
!on_demand.nil? || !count_on_hand.nil?
end
def use_producer_stock_settings?

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

@@ -7,7 +7,7 @@ module Api
attributes :orders_close_at, :active
def orders_close_at
options[:data].earliest_closing_times[object.id]
options[:data].earliest_closing_times[object.id]&.to_time
end
def active

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

@@ -7,6 +7,8 @@ module OrderCycles
class FormService
def initialize(order_cycle, order_cycle_params, user)
@order_cycle = order_cycle
@confirm_datetime_change = order_cycle_params.delete :confirm_datetime_change
@error_class = order_cycle_params.delete :error_class
@order_cycle_params = order_cycle_params
@specified_params = order_cycle_params.keys
@user = user
@@ -21,6 +23,9 @@ module OrderCycles
end
def save
# Check that order cycle datetime values changed if it has existing orders
verify_datetime_change!
schedule_ids = build_schedule_ids
order_cycle.assign_attributes(order_cycle_params)
return false unless order_cycle.valid?
@@ -229,5 +234,16 @@ module OrderCycles
DistributorShippingMethod.where(distributor_id: user_distributors_ids)
.pluck(:id)
end
def verify_datetime_change!
return unless @confirm_datetime_change
return unless @order_cycle.orders.exists?
return if @order_cycle.same_datetime_value(:orders_open_at,
@order_cycle_params[:orders_open_at]) &&
@order_cycle.same_datetime_value(:orders_close_at,
@order_cycle_params[:orders_close_at])
raise @error_class
end
end
end

View File

@@ -9,7 +9,7 @@ module PermittedAttributes
:unit_description, :variant_unit_name,
:display_as, :sku, :group_buy, :group_buy_unit_size,
:taxon_ids, :primary_taxon_id, :tax_category_id, :supplier_id,
:meta_keywords, :notes, :inherits_properties,
:meta_keywords, :notes, :inherits_properties, :shipping_category_id,
{ product_properties_attributes: [:id, :property_name, :value],
variants_attributes: [PermittedAttributes::Variant.attributes],
image_attributes: [:attachment] }

View File

@@ -3,7 +3,31 @@
module Sets
class OrderCycleSet < ModelSet
def initialize(collection, attributes = {})
@confirm_datetime_change = attributes.delete :confirm_datetime_change
@error_class = attributes.delete :error_class
super(OrderCycle, collection, attributes)
end
def process(order_cycle, attributes)
if @confirm_datetime_change &&
order_cycle.orders.exists? &&
datetime_value_changed(order_cycle, attributes)
raise @error_class
end
super
end
private
def datetime_value_changed(order_cycle, attributes)
# return true if either key is present in params and change in values detected
return true if attributes.key?(:orders_open_at) &&
!order_cycle.same_datetime_value(:orders_open_at, attributes[:orders_open_at])
attributes.key?(:orders_close_at) &&
!order_cycle.same_datetime_value(:orders_close_at, attributes[:orders_close_at])
end
end
end

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

@@ -26,9 +26,15 @@ class WeightsAndMeasures
def self.variant_unit_options
available_units_sorted.flat_map do |measurement, measurement_info|
measurement_info.filter_map do |scale, unit_info|
# Our code is based upon English based number formatting
# Some language locales like +hu+ uses a comma(,) for decimal separator
# While in English, decimal separator is represented by a period.
# e.g. en: 0.001, hu: 0,001
# Hence the results become "weight_0,001" for hu while or code recognizes "weight_0.001"
scale_clean =
ActiveSupport::NumberHelper.number_to_rounded(scale, precision: nil, significant: false,
strip_insignificant_zeros: true)
strip_insignificant_zeros: true,
locale: :en)
[
"#{I18n.t(measurement)} (#{unit_info['name']})", # Label (eg "Weight (g)")
"#{measurement}_#{scale_clean}", # Scale ID (eg "weight_1")

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,21 @@
.flex-column-gap-1
%h6
= t('.title')
%div{ style: 'font-size: 1rem;' }
= t('.content')
%p.modal-actions.justify-end.gap-1
- if action == 'simple_update'
%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')
- if action == 'bulk_update'
%button.button.secondary{ "ng-click": "saveAll($event)", type: "button", style: "display: none;", data: { action: 'click->modal#close', trigger_action: 'bulk_save' } }
= 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', action: 'simple_update'

View File

@@ -23,12 +23,20 @@
.thirteen.columns.alpha &nbsp;
%columns-dropdown{ action: "#{controller_name}_#{action_name}" }
%form{ name: 'order_cycles_form' }
%save-bar{ dirty: "order_cycles_form.$dirty", persist: "false" }
%input.red{ type: "button", value: t(:save_changes), "ng-click": "saveAll()", "ng-disabled": "!order_cycles_form.$dirty" }
%table.index#listing_order_cycles{ "ng-show": 'orderCycles.length > 0' }
= render 'admin/order_cycles/header' #, simple_index: simple_index
%tbody
= render 'admin/order_cycles/row' #, simple_index: simple_index
= render 'admin/order_cycles/loading_flash'
= render 'admin/order_cycles/show_more'
%div{ data: { controller: 'order-cycle-form' } }
%form{ name: 'order_cycles_form' }
%save-bar{ dirty: "order_cycles_form.$dirty", persist: "false" }
%input.red{ type: "button", value: t(:save_changes), "ng-click": "saveAll($event)", "ng-disabled": "!order_cycles_form.$dirty",
data: { confirm: "true", 'trigger-action': 'bulk_save' } }
%table.index#listing_order_cycles{ "ng-show": 'orderCycles.length > 0' }
= render 'admin/order_cycles/header' #, simple_index: simple_index
%tbody
= render 'admin/order_cycles/row' #, simple_index: simple_index
= render 'admin/order_cycles/loading_flash'
= render 'admin/order_cycles/show_more'
%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', action: 'bulk_update'

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

@@ -25,7 +25,7 @@
-# empty
%td.col-on_hand.align-right
-# empty
%td.col-on_hand.align-right
%td.col-producer.align-right
-# empty
%td.col-category.align-left
-# empty

View File

@@ -1,10 +1,10 @@
#sort
%div.pagination-description
- if pagy.present?
= t(".pagination.total_html", total: pagy.count, from: pagy.from, to: pagy.to)
= t(".pagination.products_total_html", count: 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

@@ -16,13 +16,13 @@
%table.products{ 'data-column-preferences-target': "table" }
%colgroup
-# The `min-width` property works in Chrome but not Firefox so is considered progressive enhancement.
%col.col-image{ width:"56px" }= # (image size + padding)
%col.col-image{ width:"44px" }= # (image size + padding)
%col.col-name{ style:"min-width: 6em" }= # (grow to fill)
%col.col-sku{ width:"8%", style:"min-width: 6em" }
%col.col-unit_scale{ width:"8%" }
%col.col-unit{ width:"8%" }
%col.col-price{ width:"5%", style:"min-width: 5em" }
%col.col-on_hand{ width:"10%"}
%col.col-price{ width:"10%", style:"min-width: 5em" }
%col.col-on_hand{ width:"8%" }
%col.col-producer{ style:"min-width: 6em" }= # (grow to fill)
%col.col-category{ width:"8%" }
%col.col-tax_category{ width:"8%" }

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

@@ -0,0 +1,47 @@
.download.hidden
= link_to t("admin.reports.download.button"), file_url, target: "_blank", class: "button icon icon-file"
:javascript
(function () {
const tryDownload = function() {
const link = document.querySelector(".download a");
// If the report was already rendered via web sockets:
if (link == null) return;
fetch(link.href).then((response) => {
if (response.ok) {
response.blob().then((blob) => blob.text()).then((text) => {
const loading = document.querySelector(".loading");
if (loading == null) return;
loading.remove();
document.querySelector("#report-go button").disabled = false;
if (link.href.endsWith(".html")) {
// This replaces the hidden download button with the report:
link.parentElement.outerHTML = text;
} else {
// Or just show the download button when it's ready:
document.querySelector(".download").classList.remove("hidden")
}
});
} else {
setTimeout(tryDownload, 2000);
}
});
}
/*
A lot of reports are rendered within 250ms. Others take at least
2.5 seconds. There's a big gap in between. Observed on:
https://openfoodnetwork.org.au/admin/sidekiq/metrics/ReportJob?period=8h
https://openfoodnetwork.org.uk/admin/sidekiq/metrics/ReportJob?period=8h
https://coopcircuits.fr/admin/sidekiq/metrics/ReportJob?period=8h
But let's leave the timed response to websockets for now and just poll
as a backup mechanism.
*/
setTimeout(tryDownload, 3000);
})();

View File

@@ -0,0 +1,6 @@
= turbo_stream.update "report-go" do
= button t(:go), "report__submit-btn", "submit", disabled: true
= turbo_stream.update "report-table" do
= render "admin/reports/loading"
= render "admin/reports/fallback_display", file_url: @blob.expiring_service_url
= turbo_stream.scroll_into_view("#report-table", behavior: "smooth")

View File

@@ -3,7 +3,7 @@
- content_for :minimal_js, true
= form_for @report.search, { url: url_for, data: { remote: "true" } } do |f|
= form_for @report.search, { url: url_for, data: { turbo: "true" } } do |f|
= hidden_field_tag "uuid", request.uuid
%fieldset.no-border-bottom.print-hidden

View File

@@ -5,7 +5,7 @@
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
%title
= Spree::Config[:site_name]
= stylesheet_pack_tag 'mail'
= stylesheet_link_tag 'mail'
%body{:bgcolor => "#FFFFFF" }
- unless @hide_ofn_navigation
%table.head-wrap{:bgcolor => "#f2f2f2"}

View File

@@ -1,8 +1,8 @@
= cache_with_locale do
.small-4.medium-4.large-5.columns.variant-name
.small-3.columns.variant-name
.inline{"ng-if" => "::variant.display_name"} {{ ::variant.display_name }}
.variant-unit {{ ::variant.unit_to_display }}
.small-3.medium-3.large-2.columns.variant-price
.small-4.medium-3.columns.variant-price
%price-breakdown{"price-breakdown" => "_", variant: "variant",
"price-breakdown-append-to-body" => "true",
"price-breakdown-placement" => "bottom",
@@ -16,7 +16,7 @@
key: "'js.shopfront.unit_price_tooltip'"}
{{ variant.unit_price_price | localizeCurrency }}&nbsp;/&nbsp;{{ variant.unit_price_unit }}
.medium-2.large-2.columns.total-price
.medium-3.columns.total-price
%span{"ng-class" => "{filled: variant.line_item.total_price}"}
{{ variant.line_item.total_price | localizeCurrency }}
= render partial: "shop/products/shop_variant_no_group_buy"

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,4 +1,4 @@
= pdf_stylesheet_pack_tag "mail"
= wicked_pdf_stylesheet_link_tag "mail"
%table{:width => "100%"}
%tbody

View File

@@ -1,4 +1,4 @@
= pdf_stylesheet_pack_tag "mail"
= wicked_pdf_stylesheet_link_tag "mail"
%table{:width => "100%"}
%tbody

View File

@@ -1,4 +1,4 @@
= pdf_stylesheet_pack_tag "mail"
= wicked_pdf_stylesheet_link_tag "mail"
%table{:width => "100%"}
%tbody

View File

@@ -1,6 +1,12 @@
= f.field_container :primary_taxon do
= f.field_container :primary_taxon_id do
= f.label :primary_taxon_id, t('.product_category')
%span.required *
%br
= f.collection_select(:primary_taxon_id, Spree::Taxon.order(:name), :id, :name, {:include_blank => true}, {:class => "select2 fullwidth"})
= render(SearchableDropdownComponent.new(form: f,
name: :primary_taxon_id,
aria_label: t('.product_category'),
options: Spree::Taxon.select(:name, :id).order(:name).pluck(:name, :id),
selected_option: @product.primary_taxon_id,
include_blank: true,
placeholder_value: t('.search_for_categories')))
= f.error_message_on :primary_taxon_id

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