Compare commits

..

267 Commits

Author SHA1 Message Date
Rachel Arnould
7caaeffe80 Merge pull request #12206 from cyrillefr/Invoices-Several-tax-rates-are-showing-up-on-the-invoice-for-the-same-product
Fix incorrect results for multiple tax rates in report
2024-03-11 10:31:09 +01:00
cyrillefr
7d99197dde Requested changes: original fix moved up in code
- instead of selecting out unapplied tax rates in the total tax
    method, did it in the query_result instead. Reverted the
    total_excl_tax method to its initial state.
  - spec and logic of testing affected also.
2024-03-11 10:13:46 +01:00
cyrillefr
62739c0458 Requested changes in spec
- use of new service instead of manually advancing an order
2024-03-11 10:13:46 +01:00
cyrillefr
7fdf1a110d Fix incorrect results for multiple tax rates in report
- total_excl_tax would sum amounts and taxes without
    knowledge if taxes rates were really applied or not
  - spec shows use case described in issue 12066
2024-03-11 10:13:46 +01:00
filipefurtad0
07a43fecdf Update all locales with the latest Transifex translations 2024-03-08 11:48:31 +00:00
Maikel
b27e0b5339 Merge pull request #12228 from openfoodfoundation/dependabot/bundler/json-jwt-1.16.6
chore(deps): bump json-jwt from 1.16.5 to 1.16.6
2024-03-08 11:39:43 +11:00
Maikel
61f29a4ebf Merge pull request #12226 from openfoodfoundation/dependabot/bundler/rubocop-rspec-2.27.1
chore(deps-dev): bump rubocop-rspec from 2.27.0 to 2.27.1
2024-03-08 11:39:06 +11:00
Filipe
9abaf90907 Merge pull request #12233 from dacook/buu/unit-scale-basic-12005
[BUU] Unit Scale - basic implementation
2024-03-07 17:20:45 +00:00
Filipe
de9446f5f3 Merge pull request #12167 from mkllnk/haml-up
Update Haml syntax and gem to version 6
2024-03-07 15:36:29 +00:00
Rachel Arnould
cd9bef4f7b Merge pull request #12172 from abdellani/12067-fix-invoice-render-multiple-tax-rates
fix invoice render multiple tax rates
2024-03-07 10:53:52 +01:00
Maikel
b4385623b2 Merge pull request #12236 from openfoodfoundation/dependabot/bundler/i18n-1.14.3
chore(deps): bump i18n from 1.14.1 to 1.14.3
2024-03-07 14:45:45 +11:00
Maikel
a256d01440 Merge pull request #12224 from dacook/rubocop-negation-matcher
Add Rubocop negation matcher
2024-03-07 14:41:20 +11:00
Rachel Arnould
5f302f347a Merge pull request #12189 from abdellani/11829-remove-alternative-invoice-when-invoice-feature-is-enabled
hide alternative invoice checkbox if invoices feature is enabled
2024-03-06 11:25:38 +01:00
dependabot[bot]
c0db3eb6ff chore(deps): bump i18n from 1.14.1 to 1.14.3
Bumps [i18n](https://github.com/ruby-i18n/i18n) from 1.14.1 to 1.14.3.
- [Release notes](https://github.com/ruby-i18n/i18n/releases)
- [Changelog](https://github.com/ruby-i18n/i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ruby-i18n/i18n/compare/v1.14.1...v1.14.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-06 09:35:21 +00:00
David Cook
29d3b34776 Increase dropdown height 2024-03-06 17:12:15 +11:00
David Cook
8612f7baab Only add extra padding on alignment edge
Saves a few precious pixels on the other edge.
2024-03-06 14:10:54 +11:00
David Cook
e770f10f2b Tomselect has minimum width 2024-03-06 14:10:54 +11:00
David Cook
cbcf388acc Ensure gap between fields wrapped over a line 2024-03-06 14:10:51 +11:00
David Cook
133c9c0609 Add descriptions for taxomony tree
Better late than never.
2024-03-06 13:41:22 +11:00
David Cook
864b95612a Show error message on variant_unit_name
Now passing options through to the error tag
2024-03-06 13:41:22 +11:00
David Cook
e8bd8389b5 Remove unused parameters
They're being silently discarded. I checked, and those classes weren't needed anyway. (theres' no conditions to even show an error in the second case, but nevermind..)
2024-03-06 13:41:22 +11:00
David Cook
38766f5256 Show variant_unit_name for 'items' 2024-03-06 13:41:22 +11:00
David Cook
e52b8daf50 Refactor: DRY 2024-03-06 13:41:22 +11:00
David Cook
b3cf977c96 Add unit name (items) field 2024-03-06 13:41:22 +11:00
David Cook
bfd6319cf2 Mark tom-select as changed
Thankfully I was able to use basic DOM features, so there's no coupling of the logic with tom-select.

It wasn't going to be simple to get tom-select to listen for the 'changed' class on the original select, so I found a simple solution with a CSS sibling selector instead.
2024-03-06 13:41:22 +11:00
David Cook
af748158aa Hide chevron until hover to allow a bit more space for text 2024-03-06 13:41:22 +11:00
David Cook
864b876a9a Add tom-select with naked style
The rem units are converted to em to make the padding relative to the chevron size. This means different font sizes will Just Work.
2024-03-06 13:41:22 +11:00
David Cook
822054b748 Use capybara helper to find field
This is more flexible and can find a field based on name, id or aria-label
2024-03-06 13:41:22 +11:00
David Cook
4b2406c9c2 Add unit scale dropdown 2024-03-06 13:41:17 +11:00
David Cook
8f0e9c9f5c Remove unnecessary selector
I can't see any reason that fieldsets, which are containers, should share styles with inputs. Maybe font styles, but everything looks fine still.
2024-03-06 13:01:44 +11:00
David Cook
958288b223 Move input styles to form stylesheet
A better way to arrange it, and as a bonus it makes the selectors simpler, yay!
2024-03-06 13:01:44 +11:00
David Cook
2ef9e34f28 Re-arrange imperial units
Who would have guessed it was this complicated.

Fingers crossed this doesn't break any other functionality...
2024-03-06 13:01:43 +11:00
David Cook
ea0067946d Generate variant unit options in Ruby
This re-implements Angular JS function VariantUnitManager.variantUnitOptions()

Well.. almost. See next commit.
2024-03-06 13:01:43 +11:00
David Cook
a1135f7db7 Move unit scale to separate column
This is because it's going to move from product to variant soon, as part of Product Refactor.
2024-03-06 13:01:43 +11:00
David Cook
8f31d8799f Adjust column widths
Table layout is tricky. I had originally hoped that the table would allow us to use min/max width. But that simply doesn't work with `table-layout: fixed`. So we need to set preconfigured widths.

Now I think that table layout doesn't bring any benefit, so I think we should consider switching to flexbox or grid. ButI'll wait until all elements are in place before trying anything new.
2024-03-06 13:01:43 +11:00
David Cook
3e0d54f5f8 Fix Layout/LineLength
Ha, `not_to have` is one character longer..
2024-03-06 09:20:22 +11:00
David Cook
ea0967e22e Safely autocorrect Capybara/NegationMatcher 2024-03-06 09:20:22 +11:00
David Cook
0a70d70118 Add rubocop Capybara/NegationMatcher
And remove other config which was actually disabled already.
2024-03-06 09:20:22 +11:00
Filipe
af9f07f496 Merge pull request #12194 from cyrillefr/Replace-dropdown_controller-with-generic-toggle-control_controller
Re-implement dropdown controller with html details element
2024-03-05 16:28:29 +00:00
Filipe
cd7a9c606e Merge pull request #12208 from abdellani/11673-add-a-coder-for-every-serialized-attribute
add for every serialized attribute a coder
2024-03-05 15:41:45 +00:00
dependabot[bot]
e95a58f735 chore(deps): bump json-jwt from 1.16.5 to 1.16.6
Bumps [json-jwt](https://github.com/nov/json-jwt) from 1.16.5 to 1.16.6.
- [Release notes](https://github.com/nov/json-jwt/releases)
- [Changelog](https://github.com/nov/json-jwt/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nov/json-jwt/compare/v1.16.5...v1.16.6)

---
updated-dependencies:
- dependency-name: json-jwt
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 20:28:10 +00:00
dependabot[bot]
0f0ec729f1 chore(deps-dev): bump rubocop-rspec from 2.27.0 to 2.27.1
Bumps [rubocop-rspec](https://github.com/rubocop/rubocop-rspec) from 2.27.0 to 2.27.1.
- [Release notes](https://github.com/rubocop/rubocop-rspec/releases)
- [Changelog](https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rspec/compare/v2.27.0...v2.27.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 09:47:53 +00:00
Gaetan Craig-Riou
9ab775c774 Merge pull request #12221 from mkllnk/rspec-sql
Use new rspec-sql gem
2024-03-04 11:37:38 +11:00
David Cook
5440c0dc65 Merge pull request #12223 from openfoodfoundation/dependabot/bundler/rubocop-rspec-2.27.0
chore(deps-dev): bump rubocop-rspec from 2.26.1 to 2.27.0
2024-03-04 10:20:49 +11:00
David Cook
2fa681ae8a Merge pull request #12203 from feruzoripov/queries/naming
Standardize Naming Conventions for Query-Related Services in `app/queries`
2024-03-04 10:15:49 +11:00
Feruz Oripov
1f299c84bc Merge branch 'master' into queries/naming 2024-03-02 16:32:50 +05:00
Feruz Oripov
3bf76c81aa Update specs 2024-03-02 16:11:26 +05:00
dependabot[bot]
d761ddabb7 chore(deps-dev): bump rubocop-rspec from 2.26.1 to 2.27.0
Bumps [rubocop-rspec](https://github.com/rubocop/rubocop-rspec) from 2.26.1 to 2.27.0.
- [Release notes](https://github.com/rubocop/rubocop-rspec/releases)
- [Changelog](https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rspec/compare/v2.26.1...v2.27.0)

---
updated-dependencies:
- dependency-name: rubocop-rspec
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-01 09:35:47 +00:00
Maikel Linke
60b86e1d64 Replace custom query counter with new gem rspec-sql 2024-03-01 11:44:25 +11:00
Maikel Linke
58490c26c1 Add rspec-sql gem 2024-03-01 11:42:03 +11:00
Maikel
a692fc9d12 Merge pull request #12218 from openfoodfoundation/dependabot/bundler/jwt-2.8.1
chore(deps): bump jwt from 2.8.0 to 2.8.1
2024-03-01 08:25:29 +11:00
Maikel
3795880fcd Merge pull request #12216 from openfoodfoundation/dependabot/bundler/rack-2.2.8.1
chore(deps): bump rack from 2.2.8 to 2.2.8.1
2024-03-01 08:15:13 +11:00
Filipe
6cd79e66ad Merge pull request #12192 from openfoodfoundation/filipefurtad0_remove_zenhub_reference
Update README.md
2024-02-29 19:54:26 +00:00
dependabot[bot]
2fff568ef9 chore(deps): bump jwt from 2.8.0 to 2.8.1
Bumps [jwt](https://github.com/jwt/ruby-jwt) from 2.8.0 to 2.8.1.
- [Release notes](https://github.com/jwt/ruby-jwt/releases)
- [Changelog](https://github.com/jwt/ruby-jwt/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jwt/ruby-jwt/compare/v2.8.0...v2.8.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-29 09:57:42 +00:00
David Cook
a9d586952d Update all locales with the latest Transifex translations 2024-02-29 14:35:08 +11:00
dependabot[bot]
bbc4603106 chore(deps): bump rack from 2.2.8 to 2.2.8.1
Bumps [rack](https://github.com/rack/rack) from 2.2.8 to 2.2.8.1.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v2.2.8...v2.2.8.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-29 01:38:02 +00:00
David Cook
5cfac3d2c7 Add comments 2024-02-29 10:10:57 +11:00
Maikel
8e29bc1a03 Merge pull request #12213 from openfoodfoundation/dependabot/bundler/dotenv-3.1.0
chore(deps): bump dotenv from 3.0.3 to 3.1.0
2024-02-29 09:01:43 +11:00
Maikel
9ba43c64d7 Merge pull request #12210 from abdellani/11673-redirect-will-no-longer-have-body
on redirect, the body will no longer include the target link
2024-02-29 08:50:52 +11:00
Filipe
ce2712f780 Merge pull request #12168 from rioug/11670-refund-stripe-payment-complete-order
Refund stripe payment when an order is complete
2024-02-28 18:08:50 +00:00
dependabot[bot]
7652c72bd6 chore(deps): bump dotenv from 3.0.3 to 3.1.0
Bumps [dotenv](https://github.com/bkeepers/dotenv) from 3.0.3 to 3.1.0.
- [Release notes](https://github.com/bkeepers/dotenv/releases)
- [Changelog](https://github.com/bkeepers/dotenv/blob/main/Changelog.md)
- [Commits](https://github.com/bkeepers/dotenv/compare/v3.0.3...v3.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-28 09:58:26 +00:00
cyrillefr
f62b32a3b9 Requested changes after review
- modified css to increase clicking area
  - modified spec to more straightfoward and more user oriented link
2024-02-28 08:15:34 +01:00
David Cook
f4e6095466 Merge pull request #12204 from dacook/rubocop-autocorrect-more
Disable RSpec cops by default
2024-02-28 17:30:22 +11:00
David Cook
2d09c23456 Disable Rails cops by default
There was just too much. Some of them seem over the top, while others look like they could be really helpful.
But we don't have time to evaluate them all right now.
2024-02-28 16:25:32 +11:00
David Cook
6f2b29eeec Move rspec styleguide to separate file 2024-02-28 16:17:49 +11:00
Gaetan Craig-Riou
8e56e076a3 Re record VCR cassettes after rebase 2024-02-28 15:26:51 +11:00
Gaetan Craig-Riou
48ba23af1c Notify BugSnag when something unexpected happens 2024-02-28 15:16:09 +11:00
Gaetan Craig-Riou
b5beeead74 Remove stripe stub for refund scenario 2024-02-28 15:13:40 +11:00
Gaetan Craig-Riou
e5cd8e5216 Log error when something goes wrong
Plus spec.
The old implementation would swallow the error, all we had was a flash
message feedback
2024-02-28 15:13:40 +11:00
Gaetan Craig-Riou
f634855826 Add request spec for Spree::Admin::PaymentsController 2024-02-28 15:13:40 +11:00
Gaetan Craig-Riou
8fb3f9a8b8 Remove "ujs-navigate": "false" from link
It somehow was causing a double loading of the page meaning flash
messages were lost. I suspect it's related to turbo/turbo link, but
I am not sure.
2024-02-28 15:13:40 +11:00
Gaetan Craig-Riou
e0e89e6452 Finally remove StripePaymentIntentsGateway decorator
Add spec for Spree::Gateway::StripeSCA#void
It also partially fix 11670, refund of Stripe payment should now work
for complete order
2024-02-28 15:13:40 +11:00
David Cook
7f77de89fc Explicitly load required file
This will be required if fixing FactoryBot/FactoryClassName
I'm not 100% sure about that rule yet, but figured this fix was worth keeping.
2024-02-28 09:37:34 +11:00
Gaetan Craig-Riou
7b5bc45d6c Merge pull request #12205 from openfoodfoundation/dependabot/bundler/dotenv-3.0.3
chore(deps): bump dotenv from 3.0.2 to 3.0.3
2024-02-28 09:20:36 +11:00
Mohamed ABDELLANI
091023baf7 on redirect, the body will no longer include the target link
for more details:
c2e756a944
2024-02-27 19:18:49 +01:00
Mohamed ABDELLANI
ca13b0154c add for every serialized attribute a coder 2024-02-27 18:59:50 +01:00
dependabot[bot]
29f9d1e374 chore(deps): bump dotenv from 3.0.2 to 3.0.3
Bumps [dotenv](https://github.com/bkeepers/dotenv) from 3.0.2 to 3.0.3.
- [Release notes](https://github.com/bkeepers/dotenv/releases)
- [Changelog](https://github.com/bkeepers/dotenv/blob/main/Changelog.md)
- [Commits](https://github.com/bkeepers/dotenv/compare/v3.0.2...v3.0.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-27 09:36:15 +00:00
Gaetan Craig-Riou
0b93c1b92b Merge pull request #12190 from openfoodfoundation/dependabot/bundler/stripe-10.10.0
chore(deps): bump stripe from 10.9.0 to 10.10.0
2024-02-27 10:27:42 +11:00
Gaetan Craig-Riou
cabf9a6502 Update Stripe API recordings for new version 2024-02-27 10:18:40 +11:00
Gaetan Craig-Riou
6d6f79ffae Merge pull request #12200 from openfoodfoundation/dependabot/bundler/rubocop-rspec-2.26.1
chore(deps-dev): bump rubocop-rspec from 2.23.2 to 2.26.1
2024-02-27 10:13:29 +11:00
Gaetan Craig-Riou
a90d944404 Merge pull request #12199 from openfoodfoundation/dependabot/bundler/webmock-3.23.0
chore(deps-dev): bump webmock from 3.21.2 to 3.23.0
2024-02-27 10:09:00 +11:00
Gaetan Craig-Riou
d2af6279f4 Merge pull request #12197 from openfoodfoundation/dependabot/bundler/listen-3.9.0
chore(deps-dev): bump listen from 3.8.0 to 3.9.0
2024-02-27 10:07:36 +11:00
Gaetan Craig-Riou
a8a1f45f1a Merge pull request #12196 from openfoodfoundation/dependabot/npm_and_yarn/karma-6.4.3
chore(deps-dev): bump karma from 6.4.2 to 6.4.3
2024-02-27 10:06:44 +11:00
Gaetan Craig-Riou
8e5adcd3a6 Merge pull request #12186 from openfoodfoundation/dependabot/bundler/view_component-3.11.0
chore(deps): bump view_component from 3.10.0 to 3.11.0
2024-02-27 09:54:30 +11:00
Gaetan Craig-Riou
a786d08df4 Merge pull request #12182 from openfoodfoundation/dependabot/npm_and_yarn/ip-1.1.9
chore(deps): bump ip from 1.1.8 to 1.1.9
2024-02-27 09:53:09 +11:00
Gaetan Craig-Riou
e1a6cb1d28 Merge pull request #12187 from openfoodfoundation/dependabot/npm_and_yarn/hotwired/turbo-8.0.3
chore(deps): bump @hotwired/turbo from 8.0.2 to 8.0.3
2024-02-27 09:52:23 +11:00
David Cook
cb1f877117 Layout/LineLength
Manual fix, for some reason rubocop couldn't fix these automatically
2024-02-27 09:51:58 +11:00
Feruz Oripov
c2d8bdd414 cops 2024-02-27 01:01:22 +05:00
Feruz Oripov
3cf75fce72 cops 2024-02-27 00:29:59 +05:00
Feruz Oripov
67cd6ea6ed cops 2024-02-26 23:44:58 +05:00
Feruz Oripov
ef17fd7d80 Cleanup 2024-02-26 23:41:48 +05:00
Feruz Oripov
ff6830f954 Update OutstandingBalanceQuery 2024-02-26 23:37:11 +05:00
Feruz Oripov
81f40a99d9 Update CustomersWithBalanceQuery 2024-02-26 23:25:33 +05:00
Feruz Oripov
d4f37a3daa Update CompleteVisibleOrdersQuery 2024-02-26 23:08:21 +05:00
Feruz Oripov
f8c0edd68b Update CompleteOrdersWithBalanceQuery 2024-02-26 23:05:25 +05:00
dependabot[bot]
b3d9aafcde chore(deps-dev): bump rubocop-rspec from 2.23.2 to 2.26.1
Bumps [rubocop-rspec](https://github.com/rubocop/rubocop-rspec) from 2.23.2 to 2.26.1.
- [Release notes](https://github.com/rubocop/rubocop-rspec/releases)
- [Changelog](https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rspec/compare/v2.23.2...v2.26.1)

---
updated-dependencies:
- dependency-name: rubocop-rspec
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 09:48:06 +00:00
dependabot[bot]
116c5d41d3 chore(deps-dev): bump webmock from 3.21.2 to 3.23.0
Bumps [webmock](https://github.com/bblimke/webmock) from 3.21.2 to 3.23.0.
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.21.2...v3.23.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 09:47:00 +00:00
dependabot[bot]
2c7d8745d9 chore(deps-dev): bump listen from 3.8.0 to 3.9.0
Bumps [listen](https://github.com/guard/listen) from 3.8.0 to 3.9.0.
- [Release notes](https://github.com/guard/listen/releases)
- [Commits](https://github.com/guard/listen/compare/v3.8.0...v3.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 09:44:48 +00:00
dependabot[bot]
6649039881 chore(deps-dev): bump karma from 6.4.2 to 6.4.3
Bumps [karma](https://github.com/karma-runner/karma) from 6.4.2 to 6.4.3.
- [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.2...v6.4.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 09:38:36 +00:00
Gaetan Craig-Riou
965d8d20a6 Merge pull request #12195 from rioug/fix-github-action-linter
Fix github action linter
2024-02-26 20:37:54 +11:00
Gaetan Craig-Riou
927acf01f6 Fix reviewdog extension config
We need to use a string list of extensions as shown in the doc:
https://github.com/reviewdog/action-rubocop?tab=readme-ov-file#example-usage
2024-02-26 20:25:49 +11:00
Gaetan Craig-Riou
e749c614a0 Merge pull request #11500 from dacook/rubocop-rspec
Add RSpec cops
2024-02-26 11:56:57 +11:00
cyrillefr
b08623df23 Sytem specs + controller spec
- controller spec is lighter since it is based on an html element
2024-02-25 16:43:57 +01:00
cyrillefr
428b9b273c Replace old dropdown controller by new one
- menu items line are unchanged only beggining of file modified
2024-02-25 16:43:57 +01:00
cyrillefr
884d6f15ff Replace a divs controller by an html details one
- checked_controller close details element on checkboxes
  - dropdown_controller.js is to rebuild controller from many divs
    to be hidden and visible to an html detail elmnt one
  - details html element styling
2024-02-25 16:43:57 +01:00
Filipe
6e73558e66 Update README.md
Removes reference to Zenhub on the README.md from the main project repo.
2024-02-23 11:28:18 +00:00
dependabot[bot]
31d8f49c26 chore(deps): bump stripe from 10.9.0 to 10.10.0
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 10.9.0 to 10.10.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v10.9.0...v10.10.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-23 09:28:10 +00:00
David Cook
250f7be8a0 Re-organise spec 2024-02-23 12:36:42 +11:00
David Cook
b758bf0735 Fix spec 2024-02-23 12:36:10 +11:00
David Cook
2107aeded1 Un-safely autocorrect RSpec/ExpectChange 2024-02-23 12:17:09 +11:00
David Cook
eaacaf42aa Enforce block style for rspec .change
As discussed in https://github.com/openfoodfoundation/openfoodnetwork/pull/11208#discussion_r1280049281
2024-02-23 12:09:50 +11:00
David Cook
800bab5303 Regenerate Rubocop's TODO file: with new RSpec rules
Wow, so much offences
2024-02-23 12:05:46 +11:00
David Cook
0091a60a6e Install rubocop-rspec
Why not enforce more consistency in our specs also?

Some of them generated way too many violations, so I relaxed them a bit.
2024-02-23 12:03:55 +11:00
David Cook
715e8253ff Disable buggy cop
Although it says it supports safe autocorrection, it requires a manual fix. I was going to manually fix the violation, but found it didn't really make the code more readable. So i'm making the call to get rid of it 🔥
2024-02-23 11:28:23 +11:00
David Cook
6bb48f2c74 Sort/format yaml
I found a plugin that promised to retain comments while sorting, so gave it a try: https://marketplace.visualstudio.com/items?itemName=PascalReitermann93.vscode-yaml-sort

It didn't really save any time, because some comments were still stripped so I had to manually fix it up. Also it reprocesses the yaml and removed other formatting like extra line breaks. So I wouldn't recommend it for this case.

Still, it could be useful for maintaining formatting of a large yaml file like our I18n file.
2024-02-23 11:21:46 +11:00
David Cook
6a2d2c581b Cleanup comments
(to make sorting with a plugin easier)

These settings have been here long enough that I think we can safely say they're accepted. There's no need to have a separate category of contested settings anyway in my opinion.
2024-02-23 11:13:50 +11:00
Maikel Linke
676f64cc4b Update all locales with the latest Transifex translations 2024-02-23 11:11:16 +11:00
Maikel
55aa324028 Link to new Ready to Go column
Instead of Zenhub.
2024-02-23 11:09:33 +11:00
David Cook
68cc9ed2fe Safely autocorrect Layout/EmptyLinesAroundBlockBody
Inspecting 1540 files
.........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................C.............................................................................................................................................................................................................................................................................................................................................................C............................................................................

Offenses:

spec/lib/stripe/payment_intent_validator_spec.rb:7:1: C: [Corrected] Layout/EmptyLinesAroundBlockBody: Extra empty line detected at block body beginning.
spec/system/admin/products_v3/products_spec.rb:219:1: C: [Corrected] Layout/EmptyLinesAroundBlockBody: Extra empty line detected at block body end.

1540 files inspected, 2 offenses detected, 2 offenses corrected
2024-02-23 10:02:23 +11:00
David Cook
5a7258c58e Regenerate Rubocop's TODO file 2024-02-23 10:00:18 +11:00
Mohamed ABDELLANI
335c2475ab hide alternative invoice checkbox if invoices feature is enabled 2024-02-22 20:09:43 +01:00
dependabot[bot]
277d185918 chore(deps): bump @hotwired/turbo from 8.0.2 to 8.0.3
Bumps [@hotwired/turbo](https://github.com/hotwired/turbo) from 8.0.2 to 8.0.3.
- [Release notes](https://github.com/hotwired/turbo/releases)
- [Commits](https://github.com/hotwired/turbo/compare/v8.0.2...v8.0.3)

---
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-02-22 09:51:00 +00:00
dependabot[bot]
655fb77ce3 chore(deps): bump view_component from 3.10.0 to 3.11.0
Bumps [view_component](https://github.com/viewcomponent/view_component) from 3.10.0 to 3.11.0.
- [Release notes](https://github.com/viewcomponent/view_component/releases)
- [Changelog](https://github.com/ViewComponent/view_component/blob/main/docs/CHANGELOG.md)
- [Commits](https://github.com/viewcomponent/view_component/compare/v3.10.0...v3.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 09:39:08 +00:00
Maikel Linke
ba51641271 Symbolise hash keys in HAML files
This was done by the haml-up script.
2024-02-22 15:01:14 +11:00
Maikel Linke
1ad58b214b Write symbols instead of hash rockets in HAML 2024-02-22 15:01:14 +11:00
Maikel Linke
e2ec3a642c Style flatten tree logic 2024-02-22 15:01:14 +11:00
Maikel Linke
66c6994d78 Fix typo in spec 2024-02-22 15:01:14 +11:00
Maikel Linke
2cf8a6dcb9 Skip haml-up spec with newer versions 2024-02-22 15:01:14 +11:00
Maikel Linke
7a767ab037 Make haml aware of custom boolean attributes 2024-02-22 15:01:13 +11:00
dependabot[bot]
cf7e0eb2cc Bump haml from 5.2.2 to 6.3.0
Bumps [haml](https://github.com/haml/haml) from 5.2.2 to 6.3.0.
- [Release notes](https://github.com/haml/haml/releases)
- [Changelog](https://github.com/haml/haml/blob/main/CHANGELOG.md)
- [Commits](https://github.com/haml/haml/compare/v5.2.2...v6.3.0)

---
updated-dependencies:
- dependency-name: haml
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-22 15:01:13 +11:00
Maikel Linke
c097f2b622 Upgrade HAML syntax with script 2024-02-22 15:01:13 +11:00
Maikel Linke
4516d90ede Add script to upgrade HAML syntax
[skip-ci]
2024-02-22 15:01:13 +11:00
Maikel
d2b1511397 Merge pull request #12160 from mkllnk/oidc-tokens
Store OIDC tokens to call DFC APIs
2024-02-22 10:34:32 +11:00
Maikel Linke
008e384f14 Simplify oidc_user factory
Now you can build in memory only as well.
2024-02-22 10:22:00 +11:00
Maikel Linke
4d8bb25f86 Allow enterprise users to disconnect their OIDC account 2024-02-22 10:21:58 +11:00
Maikel Linke
0813f43b49 Better wording for OIDC connection 2024-02-22 10:15:07 +11:00
Maikel Linke
a9b72c8095 Comment on rare upsert usage 2024-02-22 10:15:07 +11:00
Maikel Linke
6d9c5a9c66 Allow user to get new OIDC refresh token
The refresh token is usually valid for a year but it can be revoked at
any time. When we try to use it and it's expired, we should remove it
from the account record and notify the user. They can then refresh the
authorisation.
2024-02-22 10:15:07 +11:00
Maikel Linke
a89b22e397 Allow user to disconnect OIDC account
This makes testing much easier. But probably also good for users to
revoke any access via OIDC apps. It also enables users to then connect
to a different account, or just renew the current connection.
2024-02-22 10:15:07 +11:00
Maikel Linke
4f3ae4f2a4 Spec OIDC setup flow 2024-02-22 10:15:07 +11:00
Maikel Linke
07a8617143 Store OIDC account data in new model 2024-02-22 10:15:07 +11:00
Maikel Linke
6c0d15b6f9 Migrate existing OIDC account data 2024-02-22 10:15:07 +11:00
Maikel Linke
b4ee24368c Add model for OIDC accounts
The provider name and uid are currently stored on the user model but
it's better to move them to their own table. They are only needed in
certain situations, only some users have an account and we are now
storing a lot more.
2024-02-22 10:15:07 +11:00
Maikel Linke
4d680e5fd1 Use recorded auth hash including all tokens
We want to store the access and refresh token as well.
2024-02-22 10:15:07 +11:00
Maikel Linke
60dc710760 Refactor OIDC callback spec
* Clarify that it's a request spec, not testing a controller directly.
* Use `before` block to avoid side effects changing config at load time.
* Better name the test action as request instead of plain "subject".
* Move assignments into `before` block instead of variable.
2024-02-22 10:15:07 +11:00
Maikel Linke
26f4ebc8f9 Remove unnecessary test code 2024-02-22 10:15:07 +11:00
David Cook
0be0e88646 Merge pull request #12175 from mkllnk/spring-rubocop
Add rubocop binstub for spring support
2024-02-22 10:13:16 +11:00
David Cook
cbb1e41bbc Merge pull request #12174 from mkllnk/user-factory
Simplify user factory around admin role
2024-02-22 10:08:28 +11:00
David Cook
59c3bd02c7 Merge pull request #12173 from filipefurtad0/vcr_stripe_profile_storer_spec
[Stripe testing] Replaces stubs for VCR calls on profile_storer_spec.rb
2024-02-22 10:06:52 +11:00
Mohamed ABDELLANI
f4395a9d18 test display_line_item_tax_rate 2024-02-21 20:55:49 +01:00
filipefurtad0
89848efd23 Replaces stubs for VCR calls
Remove calling StripeStubs helper
2024-02-21 10:48:53 +00:00
dependabot[bot]
f564d22941 chore(deps): bump ip from 1.1.8 to 1.1.9
Bumps [ip](https://github.com/indutny/node-ip) from 1.1.8 to 1.1.9.
- [Commits](https://github.com/indutny/node-ip/compare/v1.1.8...v1.1.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-20 22:43:09 +00:00
Gaetan Craig-Riou
4ac2830ce6 Merge pull request #12177 from openfoodfoundation/dependabot/bundler/webmock-3.21.2
chore(deps-dev): bump webmock from 3.20.0 to 3.21.2
2024-02-21 09:42:28 +11:00
filipefurtad0
b91719d63c Removes reference to STRIPE_ACCOUNT
THe connected account is created a few lines below, and this env variable is not needed
2024-02-20 15:15:54 +00:00
dependabot[bot]
ccda70723d chore(deps-dev): bump webmock from 3.20.0 to 3.21.2
Bumps [webmock](https://github.com/bblimke/webmock) from 3.20.0 to 3.21.2.
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.20.0...v3.21.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-20 09:37:03 +00:00
Maikel Linke
0ce75ec6e9 Add rubocop binstub for spring support
I observed a significant speed-up on the second run. The first run seems
to be a lot slower though. Additional output suggests that it's now
loading the Rails environment which it doesn't do without spring.

```
time bundle exec rubocop Gemfile
0m2.496s

time rubocop Gemfile # not always right version
0m1.999s

time ./bin/rubocop Gemfile
0m7.543s

time ./bin/rubocop Gemfile
0m0.670s
```
2024-02-20 14:44:56 +11:00
Maikel Linke
e423015f0a Treat enterprises as normal user attribute in factory 2024-02-20 14:00:19 +11:00
Maikel Linke
af085c223d Simplify user factory around admin role
The original Spree user factory was adding the admin role by default.
Since we don't do that anymore, we don't need to remove it for normal
users. We also need to add it only once to admin users.
2024-02-20 12:58:04 +11:00
Maikel
87daf4eb79 Merge pull request #12171 from openfoodfoundation/dependabot/bundler/sidekiq-7.2.2
chore(deps): bump sidekiq from 7.2.1 to 7.2.2
2024-02-20 09:53:54 +11:00
Maikel
741f5dfc83 Merge pull request #12170 from openfoodfoundation/dependabot/bundler/jwt-2.8.0
chore(deps): bump jwt from 2.7.1 to 2.8.0
2024-02-20 09:53:09 +11:00
Mohamed ABDELLANI
f44a4356c5 remove 0.0% if no tax rate applied to line items 2024-02-19 23:43:21 +01:00
Konrad
2477a63f36 Merge pull request #12103 from basilawwad/selecting-OC-should-redirect-to-shop
Modify default hash tabs controller to redirect users to shopping panel when an OC is selected.
2024-02-19 21:51:19 +01:00
Mohamed ABDELLANI
59a9034108 remove tax rates from line_items data presenter 2024-02-19 12:36:24 +01:00
Mohamed ABDELLANI
56fe7f5e21 fix tax rates listing in invoices 2024-02-19 12:32:11 +01:00
Filipe
7926ce0c79 Merge pull request #12122 from rioug/remove-stripe-decorator
Remove stripe decorator
2024-02-19 11:28:55 +00:00
Mohamed ABDELLANI
91ecdb0eb9 remove tax_rates from line_items serializer 2024-02-19 11:35:09 +01:00
dependabot[bot]
f8908d0cf3 chore(deps): bump sidekiq from 7.2.1 to 7.2.2
Bumps [sidekiq](https://github.com/sidekiq/sidekiq) from 7.2.1 to 7.2.2.
- [Changelog](https://github.com/sidekiq/sidekiq/blob/main/Changes.md)
- [Commits](https://github.com/sidekiq/sidekiq/compare/v7.2.1...v7.2.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 09:49:49 +00:00
dependabot[bot]
f961e2c38e chore(deps): bump jwt from 2.7.1 to 2.8.0
Bumps [jwt](https://github.com/jwt/ruby-jwt) from 2.7.1 to 2.8.0.
- [Release notes](https://github.com/jwt/ruby-jwt/releases)
- [Changelog](https://github.com/jwt/ruby-jwt/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jwt/ruby-jwt/compare/v2.7.1...v2.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 09:48:44 +00:00
Gaetan Craig-Riou
cb83ad688e Remove old vcr stripe cassettes 2024-02-19 15:44:20 +11:00
Gaetan Craig-Riou
02019f7cae Re recorde vcr cassette after rebase 2024-02-19 11:01:20 +11:00
Gaetan Craig-Riou
848767d50f Per review, clean up test set up 2024-02-19 10:58:31 +11:00
Gaetan Craig-Riou
89236f4c2f Per review, create a Stripe account
It's better to avoid hard coded stripe entities
2024-02-19 10:58:31 +11:00
Gaetan Craig-Riou
ef1d2fdb4d Clean up cassettes
* remove old cassettes left over from a rebase
* re recorded cassettes with the lastest Stripe version
2024-02-19 10:58:31 +11:00
Gaetan Craig-Riou
657f71c357 Further refactor payment specs
- remove any stub_request
- use intance_double of ActiveMerchant::Billing::Response
2024-02-19 10:58:31 +11:00
Gaetan Craig-Riou
8832f2fef6 Refactor #credit spec
Model spec shouldn't know about the undelying call to stripe. Replaced
request stubs by payment method stubs.
Consolidate #credit spec in one `describe` block
2024-02-19 10:58:31 +11:00
Gaetan Craig-Riou
edc40c9ea9 Refactor Spree::Gateway::StripeSCA
- fix confusing comment
- rename parameter to better reflect usage
2024-02-19 10:58:31 +11:00
Gaetan Craig-Riou
0af9ccd17a Add test for #credit
it uses ActiveMerchant::Billing::StripePaymentIntentsGateway#refund,
we covering the last scenario that previously used the decorator.
2024-02-19 10:58:31 +11:00
Gaetan Craig-Riou
549610bc35 Finally remove StripePaymentIntentsGateway decorator
Add spec for Spree::Gateway::StripeSCA#void
It also partially fix 11670, refund of Stripe payment should now work
for complete order
2024-02-19 10:58:31 +11:00
Gaetan Craig-Riou
214e8b85ea StripePaymentIntentsGateway decorator, remove create_intent 2024-02-19 10:53:53 +11:00
Gaetan Craig-Riou
765ec81725 StripePaymentIntentsGateway decorator, remove capture 2024-02-19 10:53:53 +11:00
Gaetan Craig-Riou
84f53abdfe StripePaymentIntentsGateway decorator, remove store 2024-02-19 10:53:53 +11:00
Gaetan Craig-Riou
8a0c32eec0 Improve Stripe::ProfileStorer specs
* Use `with_stripe_setup` helper
* add the request failing scenario
2024-02-19 10:53:53 +11:00
Gaetan Craig-Riou
62fbaa8a6e Update Stripe payment intents decorator
- copied the relevant code from the new Active Merchant version
- Add spec to cover the scenario of saving a card when paying by card
- Fix Stripe stub.

I used stripe stubs for the new scenario because storing a card on
stripe depends on some client side interaction with Stripe. We can't
capture that with VCR.
2024-02-19 10:53:53 +11:00
dependabot[bot]
fad37318b3 chore(deps): bump activemerchant from 1.123.0 to 1.133.0
Bumps [activemerchant](https://github.com/activemerchant/active_merchant) from 1.123.0 to 1.133.0.
- [Release notes](https://github.com/activemerchant/active_merchant/releases)
- [Changelog](https://github.com/activemerchant/active_merchant/blob/master/CHANGELOG)
- [Commits](https://github.com/activemerchant/active_merchant/compare/v1.123.0...v1.133.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 10:53:53 +11:00
Maikel
4bb1afcc8f Merge pull request #12166 from openfoodfoundation/dependabot/bundler/stripe-10.9.0
chore(deps): bump stripe from 10.8.0 to 10.9.0
2024-02-19 10:22:53 +11:00
Maikel Linke
7eccce138b Update Stripe API recordings for new version 2024-02-19 10:02:05 +11:00
Maikel
17186a5974 Merge pull request #12165 from openfoodfoundation/dependabot/bundler/dotenv-3.0.2
chore(deps): bump dotenv from 3.0.1 to 3.0.2
2024-02-19 09:57:32 +11:00
Rachel Arnould
39b83eae19 Merge pull request #12133 from dacook/buu/new-variant-11066
[BUU] Create a new variant inline
2024-02-16 14:32:17 +01:00
Rachel Arnould
a3af15dbae Merge pull request #12162 from isidzukuri/12003_improve_error_messageg_when_no_products_are_changed
Improve error message by not displaying the first part of the second …
2024-02-16 11:24:52 +01:00
Filipe
49ebcc23b3 Merge pull request #12159 from mkllnk/capybara-wait-time
Reduce Capybara wait time during development
2024-02-16 09:37:28 +00:00
dependabot[bot]
ba9f79c684 chore(deps): bump stripe from 10.8.0 to 10.9.0
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 10.8.0 to 10.9.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v10.8.0...v10.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-16 09:17:53 +00:00
dependabot[bot]
f0ecef193d chore(deps): bump dotenv from 3.0.1 to 3.0.2
Bumps [dotenv](https://github.com/bkeepers/dotenv) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/bkeepers/dotenv/releases)
- [Changelog](https://github.com/bkeepers/dotenv/blob/main/Changelog.md)
- [Commits](https://github.com/bkeepers/dotenv/compare/v3.0.1...v3.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-16 09:11:42 +00:00
basilawwad
08111f9a2c added shop target and activateshoppanel function
Remove Pending Message

Update shopping_spec.rb

Update shopping_spec.rb
2024-02-16 09:27:21 +03:00
David Cook
52dbe408dc Merge pull request #12161 from mkllnk/reset
Add rake task to reset queued jobs
2024-02-16 12:17:19 +11:00
David Cook
fbbc47a8d8 Merge pull request #12153 from rioug/12150-dfc-add-state-to-address
[DFC] Add state to address
2024-02-16 10:30:28 +11:00
David Cook
c8af09e0a9 Merge pull request #12152 from mkllnk/record-stripe-commit
(Semi-)automatically commit new Stripe recordings
2024-02-16 10:17:52 +11:00
David Cook
7164cbd0bd Don't validate numericality if blank
This avoids unnecessary second message when left blank:
> can't be blank
> is not a number

Ok this is a little confusing. Why is there a  separate presence check above, and why is it only for measurable units, when we still require a number for _all_ units? Because, for 'items', we allow a blank value then auto-set it to 1.
I don't know if it's really necessary, but that's how it currently works...
2024-02-16 08:51:53 +11:00
David Cook
915a5ce66b Listen for changes on added fields
Finally, we can add new variants!

Requires updated stimulus-rails-nested-form
2024-02-16 08:51:49 +11:00
Maikel
5a0694acbb Merge pull request #12163 from openfoodfoundation/dependabot/bundler/dotenv-3.0.1
chore(deps): bump dotenv from 3.0.0 to 3.0.1
2024-02-16 08:03:54 +11:00
dependabot[bot]
afef8b0a82 chore(deps): bump dotenv from 3.0.0 to 3.0.1
Bumps [dotenv](https://github.com/bkeepers/dotenv) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/bkeepers/dotenv/releases)
- [Changelog](https://github.com/bkeepers/dotenv/blob/main/Changelog.md)
- [Commits](https://github.com/bkeepers/dotenv/compare/v3.0.0...v3.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-15 09:54:10 +00:00
isidzukuri
ae9229ec7a Merge branch 'master' into 12003_improve_error_messageg_when_no_products_are_changed 2024-02-15 09:36:53 +02:00
isidzukuri
0c02b5d9bd fix spec 2024-02-15 09:24:02 +02:00
isidzukuri
b9eea88f5c more precise spec for error message wording 2024-02-15 09:20:32 +02:00
isidzukuri
c0e820e447 Improve error message by not displaying the first part of the second sentence if no changes were counted 2024-02-15 09:14:52 +02:00
David Cook
0662708247 Use forked gem until contributions are made upstream 2024-02-15 17:32:08 +11:00
David Cook
3706b6d1da Make actions target optional
This is to make testing simpler, but it is strictly optional anyway.
2024-02-15 17:32:08 +11:00
David Cook
765ee0ed78 refactor js 2024-02-15 17:32:08 +11:00
David Cook
1df0eca4d1 Click button to add form
Now we can fill out the form, but in most cases we can't submit it because it's not marked as 'changed'.
2024-02-15 17:32:08 +11:00
David Cook
6cca7a4a3a Refactor HAML
Making use of nested hash to DRY it up
2024-02-15 17:32:08 +11:00
David Cook
6e5154b922 add stimulus-rails-nested-form
The official instructions (https://www.stimulus-components.com/docs/stimulus-rails-nested-form) don't quite work, because of an issue with this component (https://stackoverflow.com/a/76715129). So we work around for now by using the umd file instead.
2024-02-15 17:32:08 +11:00
David Cook
977ea47487 move new variant form to template
it can be activated with JS, once I can get that compoent working..

◉ Best viewed with whitespace ignored
2024-02-15 17:32:08 +11:00
David Cook
5253aeab17 Add unit_value so we can create new variants for producuts by weight/volume 2024-02-15 17:31:50 +11:00
David Cook
eff92b076f Add new variant form
And with the benefit of time travel, a feature spec from the future which will show us where we're heading.
2024-02-15 17:20:38 +11:00
David Cook
831d786d44 Fix existing specs
Gotta wait for server response before making expectations. This reveals that one test was incomplete, oops.
2024-02-15 17:04:14 +11:00
Maikel Linke
78bfd47ad3 Add rake task to reset queued jobs
Please note that the spec is using Redis as Sidekiq does. This revealed
that Sidekiq wasn't set up for jobs in the test environment properly.
2024-02-15 16:51:10 +11:00
Maikel
c15bf61099 Merge pull request #12156 from isidzukuri/issue_12062_fix_flacky_tax_rate_finder_spec
Improve random name generation in factories related to tax_rate_factory
2024-02-15 15:43:05 +11:00
Maikel
0e92bf33dc Merge pull request #12154 from openfoodfoundation/dependabot/bundler/letter_opener-1.9.0
chore(deps-dev): bump letter_opener from 1.8.1 to 1.9.0
2024-02-15 15:41:12 +11:00
David Cook
ec0e8b80eb Add specs for creating variants
This already works, but we want to make sure it stays that way!
2024-02-15 14:57:13 +11:00
Maikel Linke
3f98e2e559 Reduce Capybara wait time during development
In test-driven development, you run tests and expect them to fail.
Waiting for the results unnecessarily long just slows down development.

And even though CI can be slow, we should aim for good performance of
our code. Long wait times can hide performance bottle necks.

If anyone struggles with the default value, we can add an environment
variable to adjust the wait time to your machine in .env.test.local. But
this may just work for everyone.
2024-02-15 13:11:51 +11:00
David Cook
d812815913 Fix: use correct parameter name
Before, the index was defaulting to the record id, but we want to have a sequential index to guarantee the order always stays the same.
And more importantly, we'll need it for new records that don't have an ID yet.
2024-02-15 11:00:59 +11:00
David Cook
7e186091ff Ensure un-changed field error state shows
When there is a required field that can't be empty. I knew these complex styles would come back to bite me.

◉ Best viewed with whitespace ignored
2024-02-15 10:36:45 +11:00
David Cook
c65771eac6 Add new 'naked' button
I couldn't think of a better name.
2024-02-15 10:36:45 +11:00
David Cook
50b325c944 Annotate and arrange scss 2024-02-15 10:36:45 +11:00
David Cook
024f324027 Refactor: move rows to partials
This file was too big and it's about to get bigger.
2024-02-15 10:36:45 +11:00
Konrad
8751cc37f3 Merge pull request #12126 from cyrillefr/Replace-remote_toggle_controller-with-generic-toggle_control_controller
Replace remote_toggle with method inside generic controller
2024-02-15 00:32:05 +01:00
Konrad
6e54b1e726 Merge pull request #12116 from cillian/apply-fees-on-shipments-create
Make sure fees are applied when adding the first item to a back office order
2024-02-14 23:53:54 +01:00
Konrad
7cd7d2e8ea Merge pull request #12132 from rioug/9290-capture-payment-ignore-order-change
Fix capturing order payment ignore order changes
2024-02-14 23:00:49 +01:00
isidzukuri
cffe573203 improve random name generation in factories related to tax_rate_factory 2024-02-14 18:41:28 +02:00
Rachel Arnould
164bac63e0 Merge pull request #12130 from dacook/buu/modal-styles-11065
[BUU] Image modal styles
2024-02-14 16:12:32 +01:00
dependabot[bot]
0af3e8afcb chore(deps-dev): bump letter_opener from 1.8.1 to 1.9.0
Bumps [letter_opener](https://github.com/ryanb/letter_opener) from 1.8.1 to 1.9.0.
- [Changelog](https://github.com/ryanb/letter_opener/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ryanb/letter_opener/compare/v1.8.1...v1.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-14 09:17:52 +00:00
Gaetan Craig-Riou
a5bc1d5c48 Add region to address via DfcProvider::Address
Plus spec and documentation
2024-02-14 16:05:57 +11:00
Gaetan Craig-Riou
17b13e75a8 Add DfcProvider::Address
Add our own address to include `region`, currently not supported
by the DFC connector.
`region` is already included in the next branch of data-model-uml:
729eba31a5
To me removed once the DFC connector is updated
2024-02-14 16:05:48 +11:00
David Cook
6f4e071a28 Update template: Ensure we confirm with next release manager 2024-02-14 14:35:04 +11:00
David Cook
1d9364ade6 Merge pull request #12148 from openfoodfoundation/dependabot/bundler/dotenv-rails-3.0.0
chore(deps): bump dotenv-rails from 2.8.1 to 3.0.0
2024-02-14 14:21:11 +11:00
Maikel Linke
28309c1910 (Semi-)automatically commit new Stripe recordings
This script is used by a developer whenever the Stripe gem is bumped by
Dependabot. I found myself always doing the same commands and thought
that they could be automated.

I'm not going as far as pushing back to the branch but we might do that
in the future?
2024-02-14 13:54:38 +11:00
Gaetan Craig-Riou
affadbc05c Update all locales with the latest Transifex translations 2024-02-14 13:33:28 +11:00
Maikel
4197611ad2 Merge pull request #12141 from openfoodfoundation/dependabot/bundler/stripe-10.8.0
chore(deps): bump stripe from 10.6.0 to 10.8.0
2024-02-14 11:40:16 +11:00
Maikel Linke
96469cb58a Update stripe cassettes 2024-02-14 11:16:59 +11:00
Gaetan Craig-Riou
930aac97eb Replacing dotenv-rails by dotenv
From dotenv V3 changelog:
> The dotenv-rails gem is now superfluous. It's not technically
  deprecated yet and will continue to work, but the dotenv gem does the
  same thing. bkeepers/dotenv#468
2024-02-14 09:25:52 +11:00
Gaetan Craig-Riou
2213487b99 Merge pull request #12147 from openfoodfoundation/dependabot/npm_and_yarn/floating-ui/dom-1.6.3
chore(deps): bump @floating-ui/dom from 1.6.2 to 1.6.3
2024-02-14 09:04:53 +11:00
dependabot[bot]
e19d3d09dc chore(deps): bump dotenv-rails from 2.8.1 to 3.0.0
Bumps [dotenv-rails](https://github.com/bkeepers/dotenv) from 2.8.1 to 3.0.0.
- [Release notes](https://github.com/bkeepers/dotenv/releases)
- [Changelog](https://github.com/bkeepers/dotenv/blob/main/Changelog.md)
- [Commits](https://github.com/bkeepers/dotenv/compare/v2.8.1...v3.0.0)

---
updated-dependencies:
- dependency-name: dotenv-rails
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-13 09:22:42 +00:00
dependabot[bot]
1260ee281e chore(deps): bump @floating-ui/dom from 1.6.2 to 1.6.3
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.6.2 to 1.6.3.
- [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.3/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-02-13 09:11:30 +00:00
Maikel
41ebdc0c29 Merge pull request #12144 from openfoodfoundation/dependabot/npm_and_yarn/floating-ui/dom-1.6.2
chore(deps): bump @floating-ui/dom from 1.6.1 to 1.6.2
2024-02-13 11:48:11 +11:00
Maikel
13b6296764 Merge pull request #12143 from openfoodfoundation/dependabot/npm_and_yarn/jasmine-core-5.1.2
chore(deps-dev): bump jasmine-core from 5.1.1 to 5.1.2
2024-02-13 11:46:12 +11:00
Filipe
850918dac5 Merge pull request #12112 from chahmedejaz/bugfix/12085-fix-customer-search-autofill-issue
Fix Customer Search Autofill Issue
2024-02-12 12:29:28 +00:00
dependabot[bot]
942b4eea30 chore(deps): bump @floating-ui/dom from 1.6.1 to 1.6.2
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.6.1 to 1.6.2.
- [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.2/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-02-12 09:41:12 +00:00
Gaetan Craig-Riou
78a1726bdc Merge pull request #12142 from openfoodfoundation/dependabot/npm_and_yarn/hotwired/turbo-8.0.2
chore(deps): bump @hotwired/turbo from 7.3.0 to 8.0.2
2024-02-12 11:29:57 +11:00
Gaetan Craig-Riou
dc2fe0471d Merge pull request #12140 from openfoodfoundation/dependabot/bundler/redis-5.1.0
chore(deps): bump redis from 5.0.8 to 5.1.0
2024-02-12 11:19:33 +11:00
dependabot[bot]
2c0f8f2610 chore(deps-dev): bump jasmine-core from 5.1.1 to 5.1.2
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 5.1.1 to 5.1.2.
- [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.1...v5.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-09 09:47:15 +00:00
dependabot[bot]
527246ab98 chore(deps): bump @hotwired/turbo from 7.3.0 to 8.0.2
Bumps [@hotwired/turbo](https://github.com/hotwired/turbo) from 7.3.0 to 8.0.2.
- [Release notes](https://github.com/hotwired/turbo/releases)
- [Commits](https://github.com/hotwired/turbo/compare/v7.3.0...v8.0.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-09 09:46:46 +00:00
dependabot[bot]
8a9c4f83c5 chore(deps): bump stripe from 10.6.0 to 10.8.0
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 10.6.0 to 10.8.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v10.6.0...v10.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-09 09:30:05 +00:00
dependabot[bot]
c614123339 chore(deps): bump redis from 5.0.8 to 5.1.0
Bumps [redis](https://github.com/redis/redis-rb) from 5.0.8 to 5.1.0.
- [Changelog](https://github.com/redis/redis-rb/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/redis-rb/compare/v5.0.8...v5.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-09 09:28:19 +00:00
Gaetan Craig-Riou
5fd36e7eed Fix SubscriptionConfirmJob spec
Fix the payment stubbing, payment `process_offline!` was stubbed to
return true and payment `completed?` was also stubbed to return true.
`process_offline!` did not change the payment status in the database,
meaning that any call to 'order.pending_payments' after that would
return the payment which should have been processed offline, and
therefore completed. This created some unwanted side effect, resulting
in the test breaking.
2024-02-07 15:27:51 +11:00
Gaetan Craig-Riou
c11d30eb13 Refactor order updater spec
Re organise the specs based on the method we are testing, it makes
the spec file more readable.

Best viewed with whitespace hidden
2024-02-07 14:46:26 +11:00
Gaetan Craig-Riou
7da516b637 Update pending payment for completed order
Update pending payment for cash order, so we can take into account any
changes affecting order toral (shipments, line item quantity etc...).
This is to allow payment capture to cover the order total, not just
the amount due at checkout.
2024-02-07 14:46:19 +11:00
Gaetan Craig-Riou
e6fba74a87 Make update_pending_payment private
It's not used anywhere in the code, there is no reason for it to be
public
2024-02-07 14:44:59 +11:00
David Cook
5e4dd3864f Update image and modal size
Using a new 'fit' modal size.

On smaller screens, we need to allow the image to shrink. That's a good general rule, but I was hesitant to make it a global rule..
2024-02-07 12:48:44 +11:00
David Cook
98cfc68c3a Add option for modal class 2024-02-07 12:28:43 +11:00
David Cook
d24348d0f2 Increase button size
And fix alignment for smaller screens.
2024-02-07 10:13:17 +11:00
cyrillefr
f8cb98f43e Replace remote_toggle with method inside generic controller
- put former remote toggle ctrller toggle method
   in new toggleAdvancedSettings in more generic toggle ctrller
 - modified acordingly the 2 associated views
 - put former test code in more generic ctrller test file
 - deleted now useless ctrller + test files
2024-02-06 17:02:23 +01:00
Gaetan Craig-Riou
75355b0359 Add test to cover updating pending payments 2024-02-06 16:47:18 +11:00
David Cook
b3692d7468 Remove min-height for ModalComponent 2024-02-06 15:00:29 +11:00
David Cook
6189feadaa Prevent modal covered by scrollbar
Using units relative to the document, rather than the screen.

I don't think that remaining min-height should be there at all, but reveal-modal is used a lot so I don't know for sure.
2024-02-06 14:56:39 +11:00
David Cook
784f74f466 Align buttons to the right 2024-02-06 14:51:13 +11:00
David Cook
8c6d3a27ec Move modal action styles to parent component
They were already being shared with a HelpModalComponent in fact.
2024-02-06 14:34:36 +11:00
Cillian O'Ruanaidh
da71f711c0 Make sure fees are applied when adding the first item to a back office order 2024-02-02 13:11:15 +00:00
Ahmed Ejaz
a6431bdec6 12085: fix customer search autofill issue 2024-02-02 01:58:35 +05:00
475 changed files with 12797 additions and 6812 deletions

View File

@@ -1,6 +1,8 @@
# ENV vars for the test environment
# Override locally with `.env.test.local`
OFN_REDIS_JOBS_URL="redis://localhost:6379/2"
SECRET_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
STRIPE_INSTANCE_SECRET_KEY="bogus_key"
STRIPE_CUSTOMER="bogus_customer"

View File

@@ -39,11 +39,11 @@ assignees: ''
</details>
- [ ] Notify [#instance-managers]:
> @instance_managers The new release has been deployed.
- [ ] Nudge next release manager
- [ ] [Create issue] for next release and confirm with next release manager in [#core-devs].
The full process is described at https://github.com/openfoodfoundation/openfoodnetwork/wiki/Releasing.
[Ready To Go]: #zenhub
[Ready To Go]: https://github.com/orgs/openfoodfoundation/projects/8?filterQuery=status%3A%22Ready+to+go+%F0%9F%9A%80%22
[Transifex pull request]: https://github.com/openfoodfoundation/openfoodnetwork/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+head%3Atransifex
[Draft new release]: https://github.com/openfoodfoundation/openfoodnetwork/releases/new?tag=v&title=v+Code+Name&body=Congrats%0A%0ADescription%0A%0A
[releases]: https://github.com/openfoodfoundation/openfoodnetwork/releases
@@ -51,3 +51,5 @@ The full process is described at https://github.com/openfoodfoundation/openfoodn
[#testing]: https://openfoodnetwork.slack.com/app_redirect?channel=C02TZ6X00
[Deploy to Staging]: https://github.com/openfoodfoundation/openfoodnetwork/actions/workflows/stage.yml
[#global-community]: https://app.slack.com/client/T02G54U79/C59ADD8F2
[Create issue]: https://github.com/openfoodfoundation/openfoodnetwork/issues/new?assignees=&labels=&projects=&template=release.md&title=Release
[#core-devs]: https://openfoodnetwork.slack.com/archives/GK2T38QPJ

View File

@@ -18,7 +18,7 @@ jobs:
uses: reviewdog/action-rubocop@v2
with:
rubocop_version: gemfile
rubocop_extensions: rubocop-rails:gemfile
rubocop_extensions: rubocop-rails:gemfile rubocop-rspec:gemfile
reporter: github-pr-check
level: error
fail_on_error: true

View File

@@ -4,7 +4,9 @@
#
# The configuration is split into three files. Look into those files for more details.
#
require: rubocop-rails
require:
- rubocop-rails
- rubocop-rspec
inherit_from:
# The automatically generated todo list to ignore all current violations.
@@ -13,9 +15,10 @@ inherit_from:
# The relaxed style rules as a common starting point which we can refine.
- .rubocop_relaxed_styleguide.yml
# Our Open Food Network style guide. If you want to see all violations,
# Our Open Food Network style guides. If you want to see all violations,
# then use only that configuration:
#
# bundle exec rubocop -c .rubocop_styleguide.yml
#
- .rubocop_styleguide.yml
- .rubocop_rspec_styleguide.yml

View File

@@ -0,0 +1,21 @@
# OFN styleguide for rubocop-rspec
# Because there are so many, we will disable by default, and enable rules as needed.
Capybara:
Enabled: false
RSpec:
Enabled: false
FactoryBot:
Enabled: false
# Enabled rules
Capybara/NegationMatcher:
Enabled: true
EnforcedStyle: not_to
RSpec/ExpectChange:
Enabled: true
EnforcedStyle: block

View File

@@ -5,22 +5,55 @@ AllCops:
NewCops: enable
SuggestExtensions: false
Exclude:
- 'bin/**/*'
- 'db/**/*'
- 'config/**/*'
- 'script/**/*'
- 'vendor/**/*'
- 'node_modules/**/*'
- bin/**/*
- db/**/*
- config/**/*
- script/**/*
- vendor/**/*
- node_modules/**/*
# Excluding: inadequate Naming/FileName rule rejects GemFile name with camelcase
- 'engines/web/Gemfile'
- engines/web/Gemfile
## OFN SETTINGS
#
# Cop settings that have been agreed upon by the OFN community
Bundler/DuplicatedGem:
Enabled: false
Layout/LineLength:
Enabled: true
Max: 100
Layout/MultilineMethodCallIndentation:
Enabled: true
EnforcedStyle: indented
# Don't think this is a big issue, mostly picking up RPSEC scope definitions
# with lamdas and RSpec '.to change{}' blocks
Lint/AmbiguousBlockAssociation:
Enabled: false
Lint/MissingSuper:
Exclude:
- app/components/**/*
Lint/RaiseException:
Enabled: true
Lint/StructNewOverride:
Enabled: true
# Heaps of offences (> 100) in specs, mostly in situations where two or more
# instances of a model are required, but only one is referenced. Difficult to
# fix without making the spec look messy or rewriting it.
# Should definitely fix at some point.
Lint/UselessAssignment:
Exclude:
- spec/**/*
Metrics:
Enabled: true
Metrics/AbcSize:
Max: 30 # default 17
Metrics/BlockLength:
AllowedMethods: [
"class_eval",
@@ -46,13 +79,31 @@ Metrics/BlockLength:
"xdescribe",
]
Metrics/MethodLength:
Enabled: true
Max: 25 # default 10
Metrics/ParameterLists:
CountKeywordArgs: false
Metrics/PerceivedComplexity:
Enabled: true
Max: 14 # default 8
Naming/PredicateName:
Enabled: false
Naming/VariableNumber:
AllowedIdentifiers:
- street_address_1
- street_address_2
AllowedPatterns:
- _v[\d]+
Rails/ApplicationRecord:
Exclude:
# Migrations should not contain application code:
- "db/migrate/*.rb"
- db/migrate/*.rb
# Allow many-to-many associations without explicit model.
# - It avoids the additional code of a model class.
@@ -61,23 +112,23 @@ Rails/ApplicationRecord:
Rails/HasAndBelongsToMany:
Enabled: false
Rails/SkipsModelValidations:
AllowedMethods:
- "touch"
- "touch_all"
- "update_all"
- "update_attribute"
- "update_column"
- "update_columns"
Rails/OutputSafety:
Exclude:
- 'spec/**/*'
- spec/**/*
Rails/SkipsModelValidations:
AllowedMethods:
- touch
- touch_all
- update_all
- update_attribute
- update_column
- update_columns
Style/Documentation:
Enabled: false
Style/StringLiterals:
Style/FormatStringToken:
Enabled: false
Style/HashSyntax:
@@ -87,62 +138,5 @@ Style/HashSyntax:
Style/Send:
Enabled: true
Layout/MultilineMethodCallIndentation:
Enabled: true
EnforcedStyle: indented
Layout/LineLength:
Enabled: true
Max: 100
Lint/RaiseException:
Enabled: true
Lint/StructNewOverride:
Enabled: true
Naming/VariableNumber:
AllowedIdentifiers:
- street_address_1
- street_address_2
AllowedPatterns:
- _v[\d]+
Bundler/DuplicatedGem:
Enabled: false
## TEMPORARY/CONTESTED SETTINGS
#
# These are still to be decided upon, but recommended for inclusion by
# oeoeaio after scrutinising offenses the codebase
# Don't think this is a big issue, mostly picking up RPSEC scope definitions
# with lamdas and RSpec '.to change{}' blocks
Lint/AmbiguousBlockAssociation:
Enabled: false
# Heaps of offences (> 100) in specs, mostly in situations where two or more
# instances of a model are required, but only one is referenced. Difficult to
# fix without making the spec look messy or rewriting it.
# Should definitely fix at some point.
Lint/UselessAssignment:
Exclude:
- spec/**/*
Lint/MissingSuper:
Exclude:
- 'app/components/**/*'
Metrics/AbcSize:
Max: 30 # default 17
Metrics/MethodLength:
Enabled: true
Max: 25 # default 10
Metrics/PerceivedComplexity:
Enabled: true
Max: 14 # default 8
Naming/PredicateName:
Style/StringLiterals:
Enabled: false

View File

@@ -1,26 +1,16 @@
# This configuration was generated by
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp`
# using RuboCop version 1.59.0.
# using RuboCop version 1.60.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
# URISchemes: http, https
Layout/LineLength:
Exclude:
- 'app/models/spree/payment.rb'
- 'spec/system/admin/tag_rules_spec.rb'
# Offense count: 17
# Offense count: 16
# Configuration parameters: AllowedMethods.
# AllowedMethods: enums
Lint/ConstantDefinitionInBlock:
Exclude:
- 'lib/active_merchant/billing/gateways/stripe_payment_intents_decorator.rb'
- 'lib/tasks/import_product_images.rake'
- 'lib/tasks/users.rake'
- 'spec/controllers/spree/admin/base_controller_spec.rb'
@@ -153,8 +143,8 @@ Metrics/AbcSize:
- 'lib/tasks/enterprises.rake'
- 'spec/services/order_checkout_restart_spec.rb'
# Offense count: 44
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
# Offense count: 9
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
# AllowedMethods: refine
Metrics/BlockLength:
Exclude:
@@ -164,26 +154,6 @@ Metrics/BlockLength:
- 'app/models/spree/shipment.rb'
- 'lib/spree/core/controller_helpers/common.rb'
- 'lib/tasks/data.rake'
- 'spec/factories.rb'
- 'spec/factories/address_factory.rb'
- 'spec/factories/enterprise_factory.rb'
- 'spec/factories/line_item_factory.rb'
- 'spec/factories/order_cycle_factory.rb'
- 'spec/factories/order_factory.rb'
- 'spec/factories/product_factory.rb'
- 'spec/factories/shipment_factory.rb'
- 'spec/factories/shipping_method_factory.rb'
- 'spec/factories/subscription_factory.rb'
- 'spec/factories/user_factory.rb'
- 'spec/factories/variant_factory.rb'
- 'spec/requests/checkout/failed_checkout_spec.rb'
- 'spec/requests/checkout/stripe_sca_spec.rb'
- 'spec/support/cancan_helper.rb'
- 'spec/support/matchers/select2_matchers.rb'
- 'spec/support/matchers/table_matchers.rb'
- 'spec/system/consumer/shopping/checkout_spec.rb'
- 'spec/system/consumer/shopping/checkout_stripe_spec.rb'
- 'spec/system/consumer/shopping/variant_overrides_spec.rb'
# Offense count: 1
# Configuration parameters: CountBlocks, Max.
@@ -445,7 +415,7 @@ Rails/HasManyOrHasOneDependent:
- 'app/models/spree/tax_rate.rb'
- 'app/models/spree/variant.rb'
# Offense count: 25
# Offense count: 26
# Configuration parameters: Include.
# Include: app/helpers/**/*.rb
Rails/HelperInstanceVariable:
@@ -612,12 +582,11 @@ Rails/ResponseParsedBody:
- 'spec/controllers/spree/credit_cards_controller_spec.rb'
- 'spec/controllers/user_registrations_controller_spec.rb'
# Offense count: 2
# 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'
- 'spec/models/terms_of_service_file_spec.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
@@ -790,14 +759,6 @@ Style/ClassAndModuleChildren:
- 'spec/controllers/spree/admin/base_controller_spec.rb'
- 'spec/models/spree/payment_method_spec.rb'
# Offense count: 2
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: MaxUnannotatedPlaceholdersAllowed, AllowedMethods, AllowedPatterns.
# SupportedStyles: annotated, template, unannotated
# AllowedMethods: redirect
Style/FormatStringToken:
EnforcedStyle: unannotated
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
@@ -928,7 +889,12 @@ Style/PreferredHashMethods:
Style/RedundantArgument:
Exclude:
- 'engines/dfc_provider/app/services/authorization_control.rb'
- 'spec/support/query_counter.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Style/RedundantAssignment:
Exclude:
- 'spec/models/database_spec.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
@@ -995,7 +961,7 @@ Style/SlicingWithRange:
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
- 'lib/discourse/single_sign_on.rb'
# Offense count: 28
# Offense count: 25
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Mode.
Style/StringConcatenation:
@@ -1017,6 +983,5 @@ Style/StringConcatenation:
- 'spec/models/spree/line_item_spec.rb'
- 'spec/models/spree/product_spec.rb'
- 'spec/services/embedded_page_service_spec.rb'
- 'spec/support/api_helper.rb'
- 'spec/support/features/datepicker_helper.rb'
- 'spec/system/admin/products_spec.rb'

View File

@@ -5,7 +5,7 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
ruby File.read('.ruby-version').chomp
gem 'dotenv-rails', require: 'dotenv/rails-now' # Load ENV vars before other gems
gem 'dotenv', require: 'dotenv/load' # Load ENV vars before other gems
gem 'rails'
@@ -161,6 +161,7 @@ group :test, :development do
gem 'letter_opener', '>= 1.4.1'
gem 'rspec-rails', ">= 3.5.2"
gem 'rspec-retry', require: false
gem 'rspec-sql'
gem 'rswag'
gem 'shoulda-matchers'
gem 'stimulus_reflex_testing'
@@ -186,8 +187,10 @@ group :development do
gem 'rails-erd'
gem 'rubocop'
gem 'rubocop-rails'
gem 'rubocop-rspec'
gem 'spring'
gem 'spring-commands-rspec'
gem 'spring-commands-rubocop'
gem 'web-console'
gem 'rack-mini-profiler', '< 3.0.0'

View File

@@ -98,11 +98,12 @@ GEM
activejob (7.0.8)
activesupport (= 7.0.8)
globalid (>= 0.3.6)
activemerchant (1.123.0)
activemerchant (1.133.0)
activesupport (>= 4.2)
builder (>= 2.1.2, < 4.0.0)
i18n (>= 0.6.9)
nokogiri (~> 1.4)
rexml (~> 3.2.5)
activemodel (7.0.8)
activesupport (= 7.0.8)
activerecord (7.0.8)
@@ -174,7 +175,7 @@ GEM
bcp47_spec (0.2.1)
bcrypt (3.1.19)
bigdecimal (3.0.2)
bindata (2.4.15)
bindata (2.5.0)
bindex (0.8.1)
bootsnap (1.18.3)
msgpack (~> 1.2)
@@ -221,7 +222,7 @@ GEM
ruby-rc4 (>= 0.1.5)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
crack (0.4.6)
crack (1.0.0)
bigdecimal
rexml
crass (1.0.6)
@@ -258,10 +259,7 @@ GEM
diff-lcs (1.5.0)
digest (3.1.1)
docile (1.4.0)
dotenv (2.8.1)
dotenv-rails (2.8.1)
dotenv (= 2.8.1)
railties (>= 3.2)
dotenv (3.1.0)
email_validator (2.2.4)
activemodel
erubi (1.12.0)
@@ -286,7 +284,7 @@ GEM
webrick (~> 1.7)
websocket-driver (>= 0.6, < 0.8)
ffaker (2.23.0)
ffi (1.15.5)
ffi (1.16.3)
flipper (0.26.2)
concurrent-ruby (< 2)
flipper-active_record (0.26.2)
@@ -328,16 +326,18 @@ GEM
good_migrations (0.2.1)
activerecord (>= 3.1)
railties (>= 3.1)
haml (5.2.2)
temple (>= 0.8.0)
haml (6.3.0)
temple (>= 0.8.2)
thor
tilt
hashdiff (1.1.0)
hashery (2.1.2)
hashie (5.0.0)
highline (2.0.3)
htmlentities (4.3.4)
i18n (1.14.1)
i18n (1.14.3)
concurrent-ruby (~> 1.0)
racc (~> 1.7)
i18n-js (3.9.2)
i18n (>= 0.6.6)
image_processing (1.12.2)
@@ -361,7 +361,7 @@ GEM
railties (>= 3.2.16)
json (2.7.1)
json-canonicalization (1.0.0)
json-jwt (1.16.5)
json-jwt (1.16.6)
activesupport (>= 4.2)
aes_key_wrap
base64
@@ -382,16 +382,17 @@ GEM
rspec (>= 2.0, < 4.0)
jsonapi-serializer (2.2.0)
activesupport (>= 4.2)
jwt (2.7.1)
jwt (2.8.1)
base64
knapsack_pro (6.0.4)
rake
language_server-protocol (3.17.0.3)
launchy (2.5.0)
addressable (~> 2.7)
letter_opener (1.8.1)
launchy (2.5.2)
addressable (~> 2.8)
letter_opener (1.9.0)
launchy (>= 2.2, < 3)
link_header (0.0.8)
listen (3.8.0)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.22.0)
@@ -414,7 +415,7 @@ GEM
mini_magick (4.11.0)
mini_mime (1.1.5)
mini_portile2 (2.8.5)
minitest (5.22.1)
minitest (5.22.2)
monetize (1.13.0)
money (~> 6.12)
money (6.16.0)
@@ -505,7 +506,7 @@ GEM
railties (>= 4.2)
raabro (1.4.0)
racc (1.7.3)
rack (2.2.8)
rack (2.2.8.1)
rack-mini-profiler (2.3.4)
rack (>= 1.2.0)
rack-oauth2 (2.2.1)
@@ -580,9 +581,9 @@ GEM
rdoc (6.6.2)
psych (>= 4.0.0)
redcarpet (3.6.0)
redis (5.0.8)
redis (5.1.0)
redis-client (>= 0.17.0)
redis-client (0.19.1)
redis-client (0.20.0)
connection_pool
regexp_parser (2.9.0)
reline (0.4.1)
@@ -627,6 +628,9 @@ GEM
rspec-support (~> 3.12)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-sql (0.0.1)
activesupport
rspec
rspec-support (3.12.1)
rswag (2.13.0)
rswag-api (= 2.13.0)
@@ -654,13 +658,21 @@ GEM
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-ast (1.31.1)
parser (>= 3.3.0.4)
rubocop-capybara (2.20.0)
rubocop (~> 1.41)
rubocop-factory_bot (2.25.1)
rubocop (~> 1.41)
rubocop-rails (2.23.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rspec (2.27.1)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
ruby-graphviz (1.2.5)
rexml
ruby-progressbar (1.13.0)
@@ -684,7 +696,7 @@ GEM
semantic_range (3.0.0)
shoulda-matchers (6.1.0)
activesupport (>= 5.2.0)
sidekiq (7.2.1)
sidekiq (7.2.2)
concurrent-ruby (< 2)
connection_pool (>= 2.3.0)
rack (>= 2.2.4)
@@ -705,6 +717,8 @@ GEM
spring (4.1.3)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
spring-commands-rubocop (0.4.0)
spring (>= 1.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
@@ -733,7 +747,7 @@ GEM
stimulus_reflex (>= 3.3.0)
stringex (2.8.6)
stringio (3.1.0)
stripe (10.6.0)
stripe (10.10.0)
swd (2.0.3)
activesupport (>= 3)
attr_required (>= 0.0.5)
@@ -760,7 +774,7 @@ GEM
validates_lengths_from_database (0.8.0)
activerecord (>= 4)
vcr (6.2.0)
view_component (3.10.0)
view_component (3.11.0)
activesupport (>= 5.2.0, < 8.0)
concurrent-ruby (~> 1.0)
method_source (~> 1.0)
@@ -781,7 +795,7 @@ GEM
activesupport
faraday (~> 2.0)
faraday-follow_redirects
webmock (3.20.0)
webmock (3.23.0)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
@@ -846,7 +860,7 @@ DEPENDENCIES
devise-token_authenticatable
dfc_provider!
digest
dotenv-rails
dotenv
factory_bot_rails (= 6.2.0)
faraday
ffaker
@@ -912,11 +926,13 @@ DEPENDENCIES
roo
rspec-rails (>= 3.5.2)
rspec-retry
rspec-sql
rswag
rswag-api
rswag-ui
rubocop
rubocop-rails
rubocop-rspec
sd_notify
select2-rails!
shoulda-matchers
@@ -926,6 +942,7 @@ DEPENDENCIES
spreadsheet_architect
spring
spring-commands-rspec
spring-commands-rubocop
state_machines-activerecord
stimulus_reflex (= 3.5.0.rc3)
stimulus_reflex_testing

View File

@@ -32,7 +32,7 @@ We also have a [Super Admin Guide][super-admin-guide] to help with configuration
## Testing
If you'd like to help out with testing, please introduce yourself on the #testing channel on [Slack][slack-invite] and download the [ZenHub browser extension][zenhub] to view the development pipeline. Also, do have a look in our [Welcome New QAs board][welcome-qa] for some good first issues, both on manual and automated testing (RSpec/Capybara).
If you'd like to help out with testing, please introduce yourself on the #testing channel on [Slack][slack-invite]. Also, do have a look in our [Welcome New QAs board][welcome-qa] for some good first issues, both on manual and automated testing (RSpec/Capybara).
We use [BrowserStack](https://www.browserstack.com/) as a manual testing tool. BrowserStack provides open source projects with unlimited and free of charge accounts. A big thanks to them!
@@ -53,4 +53,3 @@ Copyright (c) 2012 - 2024 Open Food Foundation, released under the AGPL licence.
[super-admin-guide]: https://ofn-user-guide.gitbook.io/ofn-super-admin-guide
[welcome-dev]: https://github.com/orgs/openfoodfoundation/projects/5
[welcome-qa]: https://github.com/orgs/openfoodfoundation/projects/6
[zenhub]: https://www.zenhub.com/extension

View File

@@ -1,3 +1,2 @@
%li{ ng: { class: "{active: selector.active}" } }
%a{ "tooltip" => "{{selector.object.value}}", "tooltip-placement" => "bottom",
ng: { transclude: true, class: "{active: selector.active, 'has-tip': selector.object.value}" } }
%li{ "ng-class": "{active: selector.active}" }
%a{ tooltip: "{{selector.object.value}}", "tooltip-placement": "bottom", "ng-transclude": true, "ng-class": "{active: selector.active, 'has-tip': selector.object.value}" }

View File

@@ -1,8 +1,8 @@
.sixteen.columns.alpha.omega.alert-row{ ng: { show: '!dismissed' } }
.sixteen.columns.alpha.omega.alert-row{ "ng-show": '!dismissed' }
.fifteen.columns.pad.alpha
%span.message.text-big{ ng: { bind: 'message'} }
%span.message.text-big{ "ng-bind": 'message' }
&nbsp;&nbsp;&nbsp;
%input{ type: 'button', ng: { value: "buttonText", show: 'buttonText && buttonAction', click: "buttonAction()" } }
%input{ type: 'button', "ng-value": "buttonText", "ng-show": 'buttonText && buttonAction', "ng-click": "buttonAction()" }
.one.column.omega.pad.text-center
%a.close{ href: "#", ng: { click: "dismiss()" } }
%a.close{ href: "#", "ng-click": "dismiss()" }
&times;

View File

@@ -1,13 +1,13 @@
.ofn-drop-down.ofn-drop-down-v2.right#columns-dropdown{ ng: { controller: 'ColumnsDropdownCtrl' } }
.ofn-drop-down.ofn-drop-down-v2.right#columns-dropdown{ "ng-controller": 'ColumnsDropdownCtrl' }
.ofn-drop-down-label
= "&nbsp; #{t('admin.columns')}".html_safe
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
%div.menu{ 'ng-show' => "expanded" }
.menu_items
.menu_item{ ng: { repeat: "column in columns", click: "toggle(column);" } }
%input.redesigned-input{ type: "checkbox", ng: { checked: "column.visible" } }
.menu_item{ "ng-repeat": "column in columns", "ng-click": "toggle(column);" }
%input.redesigned-input{ type: "checkbox", "ng-checked": "column.visible" }
{{ column.name }}
%hr
%div.menu_item.text-center
%input.fullwidth.orange{ type: "button", ng: { value: "saved() ? 'Saved': 'Saving'", show: "saved() || saving", disabled: "saved()" } }
%input.fullwidth.red{ type: "button", :value => t('admin.column_save_as_default').html_safe, ng: { show: "!saved() && !saving", click: "saveColumnPreferences(action)"} }
%input.fullwidth.orange{ type: "button", "ng-value": "saved() ? 'Saved': 'Saving'", "ng-show": "saved() || saving", "ng-disabled": "saved()" }
%input.fullwidth.red{ type: "button", value: t('admin.column_save_as_default').html_safe, "ng-show": "!saved() && !saving", "ng-click": "saveColumnPreferences(action)" }

View File

@@ -1,8 +1,8 @@
#confirm-dialog{ ng: { class: "dialog_class" } }
#confirm-dialog{ "ng-class": "dialog_class" }
.message.clearfix.margin-bottom-30
.icon.text-center
%i.icon-question-sign
.text{ ng: { bind: "::message" } }
.text{ "ng-bind": "::message" }
.action-buttons.text-center
%button.cancel{ ng: { click: "close()", bind: "::cancelText" } }
%button.confirm.red{ ng: { click: "confirm()", bind: "::confirmText" } }
%button.cancel{ "ng-click": "close()", "ng-bind": "::cancelText" }
%button.confirm.red{ "ng-click": "confirm()", "ng-bind": "::confirmText" }

View File

@@ -1,12 +1,12 @@
#edit-address-dialog
%h2 {{ addressType === 'bill_address' ? "#{t('admin.customers.index.edit_bill_address')}" : "#{t('admin.customers.index.edit_ship_address')}" }}
%form{ name: 'edit_address_form', novalidate: true, ng: { submit: 'updateAddress()'}}
%form{ name: 'edit_address_form', novalidate: true, "ng-submit": 'updateAddress()' }
.row
{{ 'admin.customers.index.required_fileds' | t }}
(
%span.required *
)
.error{ ng: { repeat: "error in errors", bind: "error" } }
.error{ "ng-repeat": "error in errors", "ng-bind": "error" }
%table.no-borders
%tr
@@ -14,61 +14,55 @@
{{ 'first_name' | t }}
%span.required *
%td
%input{ type: 'text', name: 'firstname', required: true, ng: { model: 'address.firstname'} }
%input{ type: 'text', name: 'firstname', required: true, "ng-model": 'address.firstname' }
%tr
%td
{{ 'last_name' | t }}
%span.required *
%td
%input{ type: 'text', name: 'lastname', required: true, ng: { model: 'address.lastname'} }
%input{ type: 'text', name: 'lastname', required: true, "ng-model": 'address.lastname' }
%tr
%td
{{ 'address' | t }}
%span.required *
%td
%input{ type: 'text', name: 'address1', required: true, ng: { model: 'address.address1'} }
%input{ type: 'text', name: 'address1', required: true, "ng-model": 'address.address1' }
%tr
%td
{{ 'address2' | t }}
%td
%input{ type: 'text', name: 'address2', ng: { model: 'address.address2'} }
%input{ type: 'text', name: 'address2', "ng-model": 'address.address2' }
%tr
%td
{{ 'city' | t }}
%span.required *
%td
%input{ type: 'text', name: 'city', required: true, ng: { model: 'address.city'} }
%input{ type: 'text', name: 'city', required: true, "ng-model": 'address.city' }
%tr
%td
{{ 'postcode' | t }}
%span.required *
%td
%input{ type: 'text', name: 'zipcode', required: true, ng: { model: 'address.zipcode'} }
%input{ type: 'text', name: 'zipcode', required: true, "ng-model": 'address.zipcode' }
%tr
%td
{{ 'country' | t }}
%span.required *
%td
%input.ofn-select2.fullwidth#country_id{ type: 'number',
name: 'country_id', required: true,
placeholder: "{{ 'admin.customers.index.select_country' | t }}",
data: 'availableCountries', ng: { model: 'address.country_id' } }
%input.ofn-select2.fullwidth#country_id{ type: 'number', name: 'country_id', required: true, placeholder: "{{ 'admin.customers.index.select_country' | t }}", data: 'availableCountries', "ng-model": 'address.country_id' }
%tr
%td
{{ 'state' | t }}
%span.required *
%td
%input.ofn-select2.fullwidth#state_id{ type: 'number',
name: 'state_id', required: true,
placeholder: "{{ 'admin.customers.index.select_state' | t }}",
data: 'states', ng: { model: 'address.state_id' } }
%input.ofn-select2.fullwidth#state_id{ type: 'number', name: 'state_id', required: true, placeholder: "{{ 'admin.customers.index.select_state' | t }}", data: 'states', "ng-model": 'address.state_id' }
%tr
%td
{{ 'phone' | t }}
%span.required *
%td
%input{ type: 'text', name: 'phone', required: true, ng: { model: 'address.phone'} }
%input{ type: 'text', name: 'phone', required: true, "ng-model": 'address.phone' }
.text-center
%input.button.red.icon-plus{ type: 'submit', value: t('admin.customers.index.update_address')}

View File

@@ -1,9 +1,9 @@
#info-dialog{ ng: { class: "dialog_class" } }
#info-dialog{ "ng-class": "dialog_class" }
.message.clearfix.margin-bottom-30
.icon.text-center
%i{ ng: { class: "icon_class" } }
%i{ "ng-class": "icon_class" }
.text
{{ message }}
.action-buttons.text-center
%button{ ng: { click: "close()" } }
%button{ "ng-click": "close()" }
= t(:ok)

View File

@@ -1,15 +1,15 @@
%h4.modal-title
= t('js.admin.orders.index.compiling_invoices')
%p.message{ ng: { show: 'message' } }
%p.message{ "ng-show": 'message' }
{{message}}
%p.error{ ng: { show: 'error' } }
%p.error{ "ng-show": 'error' }
{{error}}
%img.spinner{ src: image_path("/spinning-circles.svg"), ng: { show: "loading" } }
%p{ ng: { show: "loading" } }
%img.spinner{ src: image_path("/spinning-circles.svg"), "ng-show": "loading" }
%p{ "ng-show": "loading" }
= t('js.admin.orders.index.please_wait')
%a.button{ target: '_blank', ng: { click: 'showBulkInvoice()', href: '/admin/orders/invoices/{{invoice_id}}', show: "!loading && !error" } }
%a.button{ target: '_blank', "ng-click": 'showBulkInvoice()', "ng-href": '/admin/orders/invoices/{{invoice_id}}', "ng-show": "!loading && !error" }
= t('js.admin.orders.index.view_file')

View File

@@ -1,10 +1,10 @@
%a.close-reveal-modal{"ng-click" => "$close()"}
%i.fa.fa-times-circle{'aria-hidden' => "true"}
%form#image_upload{ name: 'form', novalidate: true, enctype: 'multipart/form-data', multipart: true, ng: { controller: "ProductImageCtrl" } }
%form#image_upload{ name: 'form', novalidate: true, enctype: 'multipart/form-data', multipart: true, "ng-controller": "ProductImageCtrl" }
%div.image-preview
%img.spinner{ src: image_path("/spinning-circles.svg"), ng: { hide: "!imageUploader.isUploading" }}
%img.preview{ng: {src: "{{imagePreview}}", class: "{'faded': imageUploader.isUploading}"}}
%img.spinner{ src: image_path("/spinning-circles.svg"), "ng-hide": "!imageUploader.isUploading" }
%img.preview{ "ng-src": "{{imagePreview}}", "ng-class": "{'faded': imageUploader.isUploading}" }
%label{for: 'image-upload', class: 'button'} {{ 'admin.products.index.upload_an_image' | t }}
%input#image-upload{hidden: true, type: 'file', 'nv-file-select' => true, uploader: "imageUploader"}

View File

@@ -2,14 +2,14 @@
.text-normal.margin-bottom-30.text-center
{{ 'js.admin.customers.index.add_a_new_customer_for' | t:{ shop_name: CurrentShop.shop.name } }}
%form{ name: 'new_customer_form', novalidate: true, ng: { submit: "addCustomer()" }}
%form{ name: 'new_customer_form', novalidate: true, "ng-submit": "addCustomer()" }
.text-center.margin-bottom-30
%input.fullwidth{ type: 'email', name: 'email', required: true, placeholder: "{{ 'js.admin.customers.index.customer_placeholder' | t }}", ng: { model: "email" } }
%div{ ng: { show: "submitted && new_customer_form.$pristine" } }
.error{ ng: { show: "(new_customer_form.email.$error.email || new_customer_form.email.$error.required)" } }
%input.fullwidth{ type: 'email', name: 'email', required: true, placeholder: "{{ 'js.admin.customers.index.customer_placeholder' | t }}", "ng-model": "email" }
%div{ "ng-show": "submitted && new_customer_form.$pristine" }
.error{ "ng-show": "(new_customer_form.email.$error.email || new_customer_form.email.$error.required)" }
{{ 'js.admin.customers.index.valid_email_error' | t }}
.error{ ng: { repeat: "error in errors", bind: "error" } }
.error{ "ng-repeat": "error in errors", "ng-bind": "error" }
.text-center
%input.button.red.icon-plus{ type: 'submit', value: "{{ 'js.admin.customers.index.add_customer' | t }}" }

View File

@@ -4,7 +4,7 @@
.text-center.margin-bottom-30
-# %select.fullwidth{ 'select2-min-search' => 5, 'ng-model' => 'newRuleType', 'ng-options' => 'ruleType.id as ruleType.name for ruleType in availableRuleTypes' }
%input.ofn-select2.fullwidth{ :id => 'rule_type_selector', ng: { model: "ruleType" }, data: "ruleTypes", 'min-search' => "5" }
%input.ofn-select2.fullwidth{ id: 'rule_type_selector', data: "ruleTypes", "min-search": "5", "ng-model": "ruleType" }
.text-center
%input.button.red.icon-plus{ type: 'button', value: "{{ 'js.admin.new_tag_rule_dialog.add_rule' | t }}", ng: { click: 'addRule(tagGroup, ruleType)' } }
%input.button.red.icon-plus{ type: 'button', value: "{{ 'js.admin.new_tag_rule_dialog.add_rule' | t }}", "ng-click": 'addRule(tagGroup, ruleType)' }

View File

@@ -3,16 +3,16 @@
%td#available-order-cycles
{{ 'js.admin.order_cycles.schedules.available' | t }}
.order-cycles
.order-cycle{ ng: { repeat: 'orderCycle in orderCycles | available:selectedOrderCycles as availableOrderCycles', click: 'selections.available = orderCycle', dblclick: 'add(orderCycle)', class: '{selected: selections.available == orderCycle}' } }
.order-cycle{ "ng-repeat": 'orderCycle in orderCycles | available:selectedOrderCycles as availableOrderCycles', "ng-click": 'selections.available = orderCycle', "ng-dblclick": 'add(orderCycle)', "ng-class": '{selected: selections.available == orderCycle}' }
{{ orderCycle.name }}
%td#add-remove-buttons
%a.add.button{ href: 'javascript:void(0)', ng: { click: 'add()' } }
%a.add.button{ href: 'javascript:void(0)', "ng-click": 'add()' }
%i.icon-chevron-right
%a.remove.button{ href: 'javascript:void(0)', ng: { click: 'remove()' } }
%a.remove.button{ href: 'javascript:void(0)', "ng-click": 'remove()' }
%i.icon-chevron-left
%td#selected-order-cycles
{{ 'js.admin.order_cycles.schedules.selected' | t }}
.order-cycles
.order-cycle{ ng: { repeat: 'orderCycle in selectedOrderCycles', click: 'selections.selected = orderCycle', dblclick: 'remove(orderCycle)', class: '{selected: selections.selected == orderCycle}' } }
.order-cycle{ "ng-repeat": 'orderCycle in selectedOrderCycles', "ng-click": 'selections.selected = orderCycle', "ng-dblclick": 'remove(orderCycle)', "ng-class": '{selected: selections.selected == orderCycle}' }
{{ orderCycle.name }}
.error{ ng: { repeat: "error in errors", bind: "error" } }
.error{ "ng-repeat": "error in errors", "ng-bind": "error" }

View File

@@ -1,2 +1,2 @@
%td{ colspan: "{{columnCount}}", ng: { if: "template" } }
.panel{ ng: { include: "template" } }
%td{ colspan: "{{columnCount}}", "ng-if": "template" }
.panel{ "ng-include": "template" }

View File

@@ -1,7 +1,7 @@
.row.enterprise_package_panel{ ng: { controller: 'indexPackagePanelCtrl' } }
.row.enterprise_package_panel{ "ng-controller": 'indexPackagePanelCtrl' }
.alpha.eight.columns
%div{ ng: { if: "!enterprise.is_primary_producer", switch: "enterprise.sells" } }
.info{ ng: { switch: { when: "none" } } }
%div{ "ng-if": "!enterprise.is_primary_producer", "ng-switch": "enterprise.sells" }
.info{ "ng-switch-when": "none" }
%h3
{{ 'js.admin.panels.enterprise_package.hub_profile' | t }}
@@ -15,7 +15,7 @@
%p
{{ 'js.admin.panels.enterprise_package.hub_profile_text2' | t }}
.info{ ng: { switch: { when: "any" } } }
.info{ "ng-switch-when": "any" }
%h3
{{ 'js.admin.panels.enterprise_package.hub_shop' | t }}
@@ -28,7 +28,7 @@
%p
{{ 'js.admin.panels.enterprise_package.hub_shop_text3' | t }}
.info{ ng: { switch: { default: true } } }
.info{ "ng-switch-default": true }
%h3
{{ 'js.admin.panels.enterprise_package.choose_package' | t }}
%i.icon-arrow-right
@@ -40,8 +40,8 @@
%p
{{ 'js.admin.panels.enterprise_package.choose_package_text2' | t }}
%div{ ng: { if: "enterprise.is_primary_producer", switch: "enterprise.sells" } }
.info{ ng: { switch: { when: "none" } } }
%div{ "ng-if": "enterprise.is_primary_producer", "ng-switch": "enterprise.sells" }
.info{ "ng-switch-when": "none" }
%h3
{{ 'js.admin.panels.enterprise_package.profile_only' | t }}
@@ -58,7 +58,7 @@
%p
{{ 'js.admin.panels.enterprise_package.profile_only_text3' | t }}
.info{ ng: { switch: { when: "own" } } }
.info{ "ng-switch-when": "own" }
%h3
{{ 'js.admin.panels.enterprise_package.producer_shop' | t }}
@@ -68,7 +68,7 @@
%p
{{ 'js.admin.panels.enterprise_package.producer_shop_text2' | t }}
.info{ ng: { switch: { when: "any" } } }
.info{ "ng-switch-when": "any" }
%h3
{{ 'js.admin.panels.enterprise_package.producer_hub' | t }}
@@ -81,7 +81,7 @@
%p
{{ 'js.admin.panels.enterprise_package.producer_hub_text3' | t }}
.info{ ng: { switch: { default: true } } }
.info{ "ng-switch-default": true }
%h3
{{ 'js.admin.panels.enterprise_package.choose_package' | t }}
%i.icon-arrow-right
@@ -93,9 +93,9 @@
%p
{{ 'js.admin.panels.enterprise_package.choose_package_text2' | t }}
.omega.eight.columns{ ng: { switch: "enterprise.is_primary_producer" } }
%div{ ng: { switch: { when: "false" } } }
%a.button.selector.hub-profile{ ng: { click: "enterprise.owned && (enterprise.sells='none')", class: "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" } }
.omega.eight.columns{ "ng-switch": "enterprise.is_primary_producer" }
%div{ "ng-switch-when": "false" }
%a.button.selector.hub-profile{ "ng-click": "enterprise.owned && (enterprise.sells='none')", "ng-class": "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" }
.top
%h3
{{ 'js.admin.panels.enterprise_package.profile_only' | t }}
@@ -103,15 +103,15 @@
{{ 'js.admin.panels.enterprise_package.get_listing' | t }}
.bottom
{{ 'js.admin.panels.enterprise_package.always_free' | t }}
%a.button.selector.hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } }
%a.button.selector.hub{ "ng-click": "enterprise.owned && (enterprise.sells='any')", "ng-class": "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" }
.top
%h3
{{ 'js.admin.panels.enterprise_package.hub_shop' | t }}
%p
{{ 'js.admin.panels.enterprise_package.sell_produce_others' | t }}
%div{ ng: { switch: { when: "true" } } }
%a.button.selector.producer-profile{ ng: { click: "enterprise.owned && (enterprise.sells='none')", class: "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" } }
%div{ "ng-switch-when": "true" }
%a.button.selector.producer-profile{ "ng-click": "enterprise.owned && (enterprise.sells='none')", "ng-class": "{selected: enterprise.sells=='none', disabled: !enterprise.owned}" }
.top
%h3
{{ 'js.admin.panels.enterprise_package.profile_only' | t }}
@@ -119,27 +119,27 @@
{{ 'js.admin.panels.enterprise_package.get_listing' | t }}
.bottom
{{ 'js.admin.panels.enterprise_package.always_free' | t }}
%a.button.selector.producer-shop{ ng: { click: "enterprise.owned && (enterprise.sells='own')", class: "{selected: enterprise.sells=='own', disabled: !enterprise.owned}" } }
%a.button.selector.producer-shop{ "ng-click": "enterprise.owned && (enterprise.sells='own')", "ng-class": "{selected: enterprise.sells=='own', disabled: !enterprise.owned}" }
.top
%h3
{{ 'js.admin.panels.enterprise_package.producer_shop' | t }}
%p
{{ 'js.admin.panels.enterprise_package.sell_own_produce' | t }}
%a.button.selector.producer-hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } }
%a.button.selector.producer-hub{ "ng-click": "enterprise.owned && (enterprise.sells='any')", "ng-class": "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" }
.top
%h3
{{ 'js.admin.panels.enterprise_package.producer_hub' | t }}
%p
{{ 'js.admin.panels.enterprise_package.sell_both' | t }}
%a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } }
%span{ ng: {hide: "saved() || saving" } }
%a.button.update.fullwidth{ "ng-show": "enterprise.owned", "ng-class": "{disabled: saved() && !saving, saving: saving}", "ng-click": "save()" }
%span{ "ng-hide": "saved() || saving" }
{{ 'js.admin.panels.save' | t }}
%i.icon-save
%span{ ng: {show: "saved() && !saving" } }
%span{ "ng-show": "saved() && !saving" }
{{ 'js.admin.panels.saved' | t }}
%i.icon-ok-sign
%span{ ng: {show: "saving" } }
%span{ "ng-show": "saving" }
{{ 'js.admin.panels.saving' | t }}
%i.icon-refresh

View File

@@ -1,6 +1,6 @@
.row.enterprise_producer_panel{ ng: { controller: 'indexProducerPanelCtrl' } }
.row.enterprise_producer_panel{ "ng-controller": 'indexProducerPanelCtrl' }
.alpha.eight.columns
.info{ ng: { show: "enterprise.is_primary_producer==true" } }
.info{ "ng-show": "enterprise.is_primary_producer==true" }
%h3
{{ 'js.admin.panels.enterprise_producer.producer' | t }}
%p
@@ -8,7 +8,7 @@
%p
{{ 'js.admin.panels.enterprise_producer.producer_text2' | t }}
.info{ ng: { show: "enterprise.is_primary_producer==false" } }
.info{ "ng-show": "enterprise.is_primary_producer==false" }
%h3
{{ 'js.admin.panels.enterprise_producer.non_producer' | t }}
%p
@@ -17,7 +17,7 @@
{{ 'js.admin.panels.enterprise_producer.non_producer_text2' | t }}
.omega.eight.columns
%a.button.selector.producer{ ng: { click: 'enterprise.owned && changeToProducer()', class: "{selected: enterprise.is_primary_producer==true, disabled: !enterprise.owned}" } }
%a.button.selector.producer{ "ng-click": 'enterprise.owned && changeToProducer()', "ng-class": "{selected: enterprise.is_primary_producer==true, disabled: !enterprise.owned}" }
.top
%h3
{{ 'js.admin.panels.enterprise_producer.producer' | t }}
@@ -26,7 +26,7 @@
.bottom
{{ 'js.admin.panels.enterprise_producer.producer_example' | t }}
%a.button.selector.non-producer{ ng: { click: 'enterprise.owned && changeToNonProducer()', class: "{selected: enterprise.is_primary_producer==false, disabled: !enterprise.owned}" } }
%a.button.selector.non-producer{ "ng-click": 'enterprise.owned && changeToNonProducer()', "ng-class": "{selected: enterprise.is_primary_producer==false, disabled: !enterprise.owned}" }
.top
%h3
{{ 'js.admin.panels.enterprise_producer.non_producer' | t }}
@@ -35,13 +35,13 @@
.bottom
{{ 'js.admin.panels.enterprise_producer.non_producer_example' | t }}
%a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } }
%span{ ng: {hide: "saved() || saving" } }
%a.button.update.fullwidth{ "ng-show": "enterprise.owned", "ng-class": "{disabled: saved() && !saving, saving: saving}", "ng-click": "save()" }
%span{ "ng-hide": "saved() || saving" }
{{ 'js.admin.panels.save' | t }}
%i.icon-save
%span{ ng: {show: "saved() && !saving" } }
%span{ "ng-show": "saved() && !saving" }
{{ 'js.admin.panels.saved' | t }}
%i.icon-ok-sign
%span{ ng: {show: "saving" } }
%span{ "ng-show": "saving" }
{{ 'js.admin.panels.saving' | t }}
%i.icon-refresh

View File

@@ -1,10 +1,10 @@
.row.enterprise_status_panel{ ng: { controller: 'indexStatusPanelCtrl' } }
.row.enterprise_status_panel{ "ng-controller": 'indexStatusPanelCtrl' }
.alpha.omega.sixteen.columns
%h4.status-ok.text-center{ ng: { show: "issues.length == 0 && warnings.length == 0" } }
%h4.status-ok.text-center{ "ng-show": "issues.length == 0 && warnings.length == 0" }
%i.icon-ok-sign
{{ 'js.admin.panels.enterprise_status.status_title' | t:{ name: object.name } }}
%table{ ng: { show: "issues.length > 0 || warnings.length > 0" } }
%table{ "ng-show": "issues.length > 0 || warnings.length > 0" }
%thead
%th.severity
{{ 'js.admin.panels.enterprise_status.severity' | t }}
@@ -12,17 +12,17 @@
{{ 'js.admin.panels.enterprise_status.description' | t }}
%th.resolve
{{ 'js.admin.panels.enterprise_status.resolve' | t }}
%tr{ ng: { repeat: "issue in issues"} }
%tr{ "ng-repeat": "issue in issues" }
%td.severity
%i.icon-warning-sign.issue
%td.description
%span{ ng: { bind: "::issue.description" } }
%span{ "ng-bind": "::issue.description" }
%td.resolve
%div{ ng: { bind: { html: "issue.link" } } }
%tr{ ng: { repeat: "warning in warnings"} }
%div{ "ng-bind-html": "issue.link" }
%tr{ "ng-repeat": "warning in warnings" }
%td.severity
%i.icon-warning-sign.warning
%td.description
%span{ ng: { bind: "::warning.description" } }
%span{ "ng-bind": "::warning.description" }
%td.resolve
%div{ ng: { bind: { html: "warning.link" } } }
%div{ "ng-bind-html": "warning.link" }

View File

@@ -1,9 +1,9 @@
#save-bar.animate-show{ ng: { show: 'dirty || persist || StatusMessage.active()' } }
#save-bar.animate-show{ "ng-show": 'dirty || persist || StatusMessage.active()' }
.container
.seven.columns.alpha
%h5#status-message{ ng: { show: "StatusMessage.invalidMessage == ''", style: 'StatusMessage.statusMessage.style' } }
%h5#status-message{ "ng-show": "StatusMessage.invalidMessage == ''", "ng-style": 'StatusMessage.statusMessage.style' }
{{ StatusMessage.statusMessage.text || "&nbsp;" }}
%h5#status-message{ ng: { show: "StatusMessage.invalidMessage !== ''" }, style: 'color: #C85136' }
%h5#status-message{ style: 'color: #C85136', "ng-show": "StatusMessage.invalidMessage !== ''" }
{{ StatusMessage.invalidMessage || "&nbsp;" }}
.nine.columns.omega.text-right{ ng: { transclude: true } }
.nine.columns.omega.text-right{ "ng-transclude": true }

View File

@@ -1,24 +1,24 @@
#schedule-dialog
.text-normal.margin-bottom-30.text-center
%span{ ng: { hide: 'schedule.id' } }
%span{ "ng-hide": 'schedule.id' }
{{ 'js.admin.order_cycles.schedules.adding_a_new_schedule' | t }}
%span{ ng: { show: 'schedule.id' } }
%span{ "ng-show": 'schedule.id' }
{{ 'js.admin.order_cycles.schedules.updating_a_schedule' | t }}
%form{ name: 'schedule_form', novalidate: true, ng: { submit: "submit()" }}
%form{ name: 'schedule_form', novalidate: true, "ng-submit": "submit()" }
.text-center.margin-bottom-20
%input.fullwidth{ type: 'text', name: 'name', required: true, placeholder: "{{ 'js.admin.order_cycles.schedules.schedule_name_placeholder' | t }}", ng: { model: "schedule.name" } }
%div{ ng: { show: "submitted && schedule_form.$pristine" } }
.error{ ng: { show: "(schedule_form.name.$error.required)" } }
%input.fullwidth{ type: 'text', name: 'name', required: true, placeholder: "{{ 'js.admin.order_cycles.schedules.schedule_name_placeholder' | t }}", "ng-model": "schedule.name" }
%div{ "ng-show": "submitted && schedule_form.$pristine" }
.error{ "ng-show": "(schedule_form.name.$error.required)" }
{{ 'js.admin.order_cycles.schedules.name_required_error' | t }}
.order-cycles-selector.text-center.margin-bottom-30
.text-center
%input.button{ type: 'submit', value: "{{ 'js.admin.order_cycles.schedules.create_schedule' | t }}", ng: { hide: 'schedule.id' } }
%input.button{ type: 'submit', value: "{{ 'js.admin.order_cycles.schedules.update_schedule' | t }}", ng: { show: 'schedule.id' } }
%span{ ng: { show: 'schedule.id' } } or
%input.button.red{ type: 'button', value: "{{ 'js.admin.order_cycles.schedules.delete_schedule' | t }}", ng: { show: 'schedule.id', click: 'delete()'} }
%input.button{ type: 'button', value: "{{ 'actions.cancel' | t }}", ng: { click: 'close()' } }
%input.button{ type: 'submit', value: "{{ 'js.admin.order_cycles.schedules.create_schedule' | t }}", "ng-hide": 'schedule.id' }
%input.button{ type: 'submit', value: "{{ 'js.admin.order_cycles.schedules.update_schedule' | t }}", "ng-show": 'schedule.id' }
%span{ "ng-show": 'schedule.id' } or
%input.button.red{ type: 'button', value: "{{ 'js.admin.order_cycles.schedules.delete_schedule' | t }}", "ng-show": 'schedule.id', "ng-click": 'delete()' }
%input.button{ type: 'button', value: "{{ 'actions.cancel' | t }}", "ng-click": 'close()' }

View File

@@ -1,8 +1,8 @@
.tag-template
%div
%span.tag-with-rules{ ng: { if: "data.rules" }, "ofn-with-tip" => "{{ 'admin.tag_has_rules' | t:{num: data.rules} }}" }
%span.tag-with-rules{ "ofn-with-tip": "{{ 'admin.tag_has_rules' | t:{num: data.rules} }}", "ng-if": "data.rules" }
{{$getDisplayText()}}
%span{ ng: { if: "!data.rules" } }
%span{ "ng-if": "!data.rules" }
{{$getDisplayText()}}
%a.remove-button{ ng: {click: "$removeTag()"} }
%a.remove-button{ "ng-click": "$removeTag()" }
&#10006;

View File

@@ -1,11 +1,11 @@
.autocomplete-template
%span.tag-with-rules{ ng: { if: "data.rules" } }
%span.tag-with-rules{ "ng-if": "data.rules" }
{{$getDisplayText()}}
%span.tag-with-rules{ ng: { if: "data.rules == 1" } }
%span.tag-with-rules{ "ng-if": "data.rules == 1" }
&mdash;
{{ 'admin.has_one_rule' | t }}
%span.tag-with-rules{ ng: { if: "data.rules > 1" } }
%span.tag-with-rules{ "ng-if": "data.rules > 1" }
&mdash;
{{ 'admin.has_n_rules' | t:{ num: data.rules } }}
%span{ ng: { if: "!data.rules" } }
%span{ "ng-if": "!data.rules" }
{{$getDisplayText()}}

View File

@@ -1,7 +1,3 @@
%div
%input{ type: "number",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_calculator_attributes_preferred_flat_percent",
min: -100,
max: 100,
ng: { model: "rule.calculator.preferred_flat_percent" }, 'invert-number' => true }
%input{ type: "number", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_calculator_attributes_preferred_flat_percent", min: -100, max: 100, "invert-number": true, "ng-model": "rule.calculator.preferred_flat_percent" }
%span.text-normal %

View File

@@ -1,11 +1,5 @@
%div
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_order_cycles_visibility",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_order_cycles_visibility]",
ng: { model: "rule.preferred_matched_order_cycles_visibility", if: "!rule.is_default" },
data: 'visibilityOptions', "min-search" => 5 }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_order_cycles_visibility",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_order_cycles_visibility]",
ng: { value: "'hidden'", if: "rule.is_default" } }
%span.text-normal{ ng: { if: "rule.is_default" } }
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_order_cycles_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_order_cycles_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_order_cycles_visibility", "ng-if": "!rule.is_default" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_order_cycles_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_order_cycles_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
%span.text-normal{ "ng-if": "rule.is_default" }
=t(:not_visible)

View File

@@ -1,11 +1,5 @@
%div
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_payment_methods_visibility",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_payment_methods_visibility]",
ng: { model: "rule.preferred_matched_payment_methods_visibility", if: "!rule.is_default" },
data: 'visibilityOptions', "min-search" => 5 }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_payment_methods_visibility",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_payment_methods_visibility]",
ng: { value: "'hidden'", if: "rule.is_default" } }
%span.text-normal{ ng: { if: "rule.is_default" } }
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_payment_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_payment_methods_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_payment_methods_visibility", "ng-if": "!rule.is_default" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_payment_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_payment_methods_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
%span.text-normal{ "ng-if": "rule.is_default" }
= t(:not_visible)

View File

@@ -1,11 +1,5 @@
%div
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_variants_visibility",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_variants_visibility]",
ng: { model: "rule.preferred_matched_variants_visibility", if: "!rule.is_default" },
data: 'visibilityOptions', "min-search" => 5 }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_variants_visibility",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_variants_visibility]",
ng: { value: "'hidden'", if: "rule.is_default" } }
%span.text-normal{ ng: { if: "rule.is_default" } }
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_variants_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_variants_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_variants_visibility", "ng-if": "!rule.is_default" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_variants_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_variants_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
%span.text-normal{ "ng-if": "rule.is_default" }
= t(:not_visible)

View File

@@ -1,12 +1,6 @@
%div
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_shipping_methods_visibility",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_shipping_methods_visibility]",
ng: { model: "rule.preferred_matched_shipping_methods_visibility", if: "!rule.is_default" },
data: 'visibilityOptions', "min-search" => 5 }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_shipping_methods_visibility",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_shipping_methods_visibility]",
ng: { value: "'hidden'", if: "rule.is_default" } }
%span.text-normal{ ng: { if: "rule.is_default" } }
%input.fullwidth.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_shipping_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_shipping_methods_visibility]", data: 'visibilityOptions', "min-search": 5, "ng-model": "rule.preferred_matched_shipping_methods_visibility", "ng-if": "!rule.is_default" }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_shipping_methods_visibility", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_shipping_methods_visibility]", "ng-value": "'hidden'", "ng-if": "rule.is_default" }
%span.text-normal{ "ng-if": "rule.is_default" }
= t(:not_visible)

View File

@@ -6,45 +6,27 @@
%col.actions{ width: "10%" }
%tr
%td
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_id",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][id]",
ng: { value: "rule.id" } }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_id", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][id]", "ng-value": "rule.id" }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_type",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][type]",
ng: { value: "rule.type" } }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_type", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][type]", "ng-value": "rule.type" }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_priority",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][priority]",
ng: { value: "tagGroup.startIndex + $index" } }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_priority", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][priority]", "ng-value": "tagGroup.startIndex + $index" }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_is_default",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][is_default]",
ng: { value: "rule.is_default" } }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_is_default", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][is_default]", "ng-value": "rule.is_default" }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_customer_tags",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_customer_tags]",
ng: { value: "rule.preferred_customer_tags" } }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_customer_tags", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_customer_tags]", "ng-value": "rule.preferred_customer_tags" }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_{{opt[rule.type].taggable}}_tags",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_{{opt[rule.type].taggable}}_tags]",
ng: { value: "opt[rule.type].tagListFor(rule)" } }
%input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_{{opt[rule.type].taggable}}_tags", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_{{opt[rule.type].taggable}}_tags]", "ng-value": "opt[rule.type].tagListFor(rule)" }
%span.text-normal {{ opt[rule.type].textTop }}
%td
%tags-with-translation{ object: "rule", max: 1, "tags-attr" => "{{opt[rule.type].tagsAttr}}", "tag-list-attr" => "{{opt[rule.type].tagListAttr}}" }
%td.actions{ rowspan: 2 }
%a{ ng: { click: "deleteTagRule(tagGroup || defaultTagGroup, rule)" }, :class => "delete-tag-rule icon-trash no-text" }
%a{ class: "delete-tag-rule icon-trash no-text", "ng-click": "deleteTagRule(tagGroup || defaultTagGroup, rule)" }
%tr
%td
%span.text-normal {{ opt[rule.type].textBottom }}
%td
%div{ ng: { include: "opt[rule.type].inputTemplate"} }
%div{ "ng-include": "opt[rule.type].inputTemplate" }
%hr

View File

@@ -1,10 +1,2 @@
%tags-input{ template: 'admin/tag.html',
"placeholder" => t('admin.order_cycles.form.add_a_tag'),
ng: { model: 'object[tagsAttr]', class: "{'limit-reached': limitReached}"},
on: { tag: { added: 'tagAdded($tag)', removed:'tagRemoved()' } } }
%auto-complete{ ng: { if: "findTags" }, source: "findTags({query: $query})",
template: "admin/tag_autocomplete.html",
"min-length" => "0",
"load-on-focus" => "true",
"load-on-empty" => "true",
"max-results-to-show" => "32"}
%tags-input{ template: 'admin/tag.html', placeholder: t('admin.order_cycles.form.add_a_tag'), "ng-model": 'object[tagsAttr]', "ng-class": "{'limit-reached': limitReached}", "on-tag-added": 'tagAdded($tag)', "on-tag-removed": 'tagRemoved()' }
%auto-complete{ source: "findTags({query: $query})", template: "admin/tag_autocomplete.html", "min-length": "0", "load-on-focus": "true", "load-on-empty": "true", "max-results-to-show": "32", "ng-if": "findTags" }

View File

@@ -22,24 +22,22 @@
.variant-bulk-buy-quantity-label
{{ "js.shopfront.bulk_buy_modal.min_quantity" | t }}
%div
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "add(-1)", disabled: "!canAdd(-1)"}}>
%button.bulk-buy-add.variant-quantity{ type: "button", "ng-click": "add(-1)", "ng-disabled": "!canAdd(-1)" }>
-# U+FF0D Fullwidth Hyphen-Minus
%input.bulk-buy.variant-quantity{type: "number", min: "0", max: "{{ available() }}",
ng: {model: "variant.line_item.quantity", max: "Infinity"}}>
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "add(1)", disabled: "!canAdd(1)"}}
%input.bulk-buy.variant-quantity{ type: "number", min: "0", max: "{{ available() }}", "ng-model": "variant.line_item.quantity", "ng-max": "Infinity" }>
%button.bulk-buy-add.variant-quantity{ type: "button", "ng-click": "add(1)", "ng-disabled": "!canAdd(1)" }
-# U+FF0B Fullwidth Plus Sign
.columns.small-12.medium-6
.variant-bulk-buy-quantity-label
{{ "js.shopfront.bulk_buy_modal.max_quantity" | t }}
%div
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "addMax(-1)", disabled: "!canAddMax(-1)"}}>
%button.bulk-buy-add.variant-quantity{ type: "button", "ng-click": "addMax(-1)", "ng-disabled": "!canAddMax(-1)" }>
-# U+FF0D Fullwidth Hyphen-Minus
%input.bulk-buy.variant-quantity{type: "number", min: "0", max: "{{ available() }}",
ng: {model: "variant.line_item.max_quantity", max: "Infinity"}}>
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "addMax(1)", disabled: "!canAddMax(1)"}}
%input.bulk-buy.variant-quantity{ type: "number", min: "0", max: "{{ available() }}", "ng-model": "variant.line_item.max_quantity", "ng-max": "Infinity" }>
%button.bulk-buy-add.variant-quantity{ type: "button", "ng-click": "addMax(1)", "ng-disabled": "!canAddMax(1)" }
-# U+FF0B Fullwidth Plus Sign

View File

@@ -1,3 +1,3 @@
%ul
%active-selector{ ng: { repeat: "selector in allSelectors", show: "ifDefined(selector.fits, true)" } }
%active-selector{ "ng-repeat": "selector in allSelectors", "ng-show": "ifDefined(selector.fits, true)" }
%span{"ng-bind" => "::selector.object.name"}

View File

@@ -5,5 +5,5 @@
.small-12.columns.text-center
{{ helpText }}
.row.text-center
%button.primary.small{ ng: { click: '$close()' } }
%button.primary.small{ "ng-click": '$close()' }
= t(:ok)

View File

@@ -1,4 +1,4 @@
.row.pad-top{ng: { if: 'enterprise.is_distributor' } }
.row.pad-top{ "ng-if": 'enterprise.is_distributor' }
.cta-container.small-12.columns
.row
.small-4.columns

View File

@@ -1,6 +1,6 @@
.joyride-tip-guide.price_breakdown{ng: {class: "{ in: tt_isOpen, fade: tt_animation }", show: "tt_isOpen"}}
.joyride-tip-guide.price_breakdown{ "ng-class": "{ in: tt_isOpen, fade: tt_animation }", "ng-show": "tt_isOpen" }
%span.joyride-nub.top
.background{ng: {click: "tt_isOpen = false"}}
.background{ "ng-click": "tt_isOpen = false" }
.joyride-content-wrapper
%h6 {{ "js.shopfront.price_breakdown" | t }}
%ul

View File

@@ -1,5 +1,5 @@
.joyride-tip-guide.question-mark-tooltip{class: "{{ context }}", ng: {class: "{ in: tt_isOpen, fade: tt_animation }", show: "tt_isOpen"}}
.background{ng: {click: "tt_isOpen = false"}}
.joyride-tip-guide.question-mark-tooltip{ class: "{{ context }}", "ng-class": "{ in: tt_isOpen, fade: tt_animation }", "ng-show": "tt_isOpen" }
.background{ "ng-click": "tt_isOpen = false" }
.joyride-content-wrapper
{{ key | t }}
%span.joyride-nub.bottom

View File

@@ -1,22 +0,0 @@
.modal-actions {
display: flex;
&.justify-space-around {
justify-content: space-around;
}
&.justify-end {
justify-content: flex-end;
input[type="button"] {
margin: 0 5px;
}
@media only screen and (max-width: 1024px) {
flex-direction: column;
justify-content: space-around;
input[type="button"] {
margin: 5px 0;
}
}
}
}

View File

@@ -1,10 +1,11 @@
# frozen_string_literal: true
class ModalComponent < ViewComponent::Base
def initialize(id:, close_button: true, instant: false)
def initialize(id:, close_button: true, instant: false, modal_class: :small)
@id = id
@close_button = close_button
@instant = instant
@modal_class = modal_class
end
private

View File

@@ -1,6 +1,6 @@
%div{ id: @id, "data-controller": "modal", "data-action": "keyup@document->modal#closeIfEscapeKey", "data-modal-instant-value": @instant }
.reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" }
.reveal-modal.fade.small.modal-component{ "data-modal-target": "modal" }
.reveal-modal.fade.modal-component{ "data-modal-target": "modal", class: @modal_class }
= content
- if close_button?

View File

@@ -3,6 +3,8 @@
visibility: visible;
position: fixed;
top: 3em;
min-height: auto; // reset from reveal-modal
&.in {
padding: 1.2rem;
}
@@ -16,9 +18,39 @@
p {
margin-bottom: 0.5em;
}
img {
// Ensure image fits in container
max-width: 100%;
height: auto;
}
}
/* prevent arrow on selected admin menu item appearing above modal */
body.modal-open #admin-menu li.selected a::after {
z-index: 0;
}
.modal-actions {
display: flex;
text-align: center; // Ensure text inside fullwidth buttons are centred on small screens
&.justify-space-around {
justify-content: space-around;
}
&.justify-end {
justify-content: flex-end;
input[type="button"] {
margin: 0 5px;
}
@media only screen and (max-width: 1024px) {
flex-direction: column;
justify-content: space-around;
input[type="button"] {
margin: 5px 0;
}
}
}
}

View File

@@ -70,7 +70,7 @@ module Admin
def collection
if json_request? && params[:enterprise_id].present?
CustomersWithBalance.new(customers).query.
CustomersWithBalanceQuery.new(customers).call.
includes(
:enterprise,
{ bill_address: [:state, :country] },

View File

@@ -2,6 +2,13 @@
module Admin
class OidcSettingsController < Spree::Admin::BaseController
def index; end
def index
@account = spree_current_user.oidc_account
end
def destroy
spree_current_user.oidc_account&.destroy
redirect_to admin_oidc_settings_path
end
end
end

View File

@@ -23,6 +23,8 @@ module Api
OrderWorkflow.new(@order).advance_to_payment if @order.line_items.any?
@order.recreate_all_fees!
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
end

View File

@@ -59,7 +59,7 @@ module Api
def customer
@customer ||= if action_name == "show"
CustomersWithBalance.new(Customer.where(id: params[:id])).query.first!
CustomersWithBalanceQuery.new(Customer.where(id: params[:id])).call.first!
else
Customer.find(params[:id])
end
@@ -74,7 +74,7 @@ module Api
customers = customers.where(enterprise_id: params[:enterprise_id]) if params[:enterprise_id]
if @extra_customer_fields.include?(:balance)
customers = CustomersWithBalance.new(customers).query
customers = CustomersWithBalanceQuery.new(customers).call
end
customers.ransack(params[:q]).result.order(:id)

View File

@@ -2,7 +2,7 @@
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def openid_connect
spree_current_user.link_from_omniauth(request.env["omniauth.auth"])
OidcAccount.link(spree_current_user, request.env["omniauth.auth"])
redirect_to admin_oidc_settings_path
end

View File

@@ -59,6 +59,8 @@ module Spree
flash[:error] = t(:cannot_perform_operation)
end
rescue StandardError => e
logger.error e.message
Bugsnag.notify(e)
flash[:error] = e.message
ensure
redirect_to request.referer

View File

@@ -16,7 +16,7 @@ module Spree
before_action :set_locale
def show
@payments_requiring_action = PaymentsRequiringAction.new(spree_current_user).query
@payments_requiring_action = PaymentsRequiringActionQuery.new(spree_current_user).call
@orders = orders_collection.includes(:line_items)
customers = spree_current_user.customers
@@ -79,7 +79,7 @@ module Spree
private
def orders_collection
CompleteOrdersWithBalance.new(@user).query
CompleteOrdersWithBalanceQuery.new(@user).call
end
def load_object

View File

@@ -22,7 +22,7 @@ module ShopHelper
{ name: 'home', title: t(:shopping_tabs_home), show: show_home_tab?,
default: show_home_tab? },
{ name: 'shop', title: t(:shopping_tabs_shop), show: !require_customer?,
default: !show_home_tab? },
default: !show_home_tab?, shop: true },
{ name: 'about', title: t(:shopping_tabs_about), show: true },
{ name: 'producers', title: t(:shopping_tabs_producers), show: true },
{ name: 'contact', title: t(:shopping_tabs_contact), show: true },

View File

@@ -12,7 +12,7 @@ module Spree
id: "#{model}_#{method}_field")
end
def error_message_on(object, method, _options = {})
def error_message_on(object, method, options = {})
object = convert_to_model(object)
obj = object.respond_to?(:errors) ? object : instance_variable_get("@#{object}")
@@ -20,7 +20,7 @@ module Spree
# rubocop:disable Rails/OutputSafety
errors = obj.errors[method].map { |err| h(err) }.join('<br />').html_safe
# rubocop:enable Rails/OutputSafety
content_tag(:span, errors, class: 'formError')
content_tag(:span, errors, class: 'formError', **options)
else
''
end

View File

@@ -4,7 +4,7 @@ class Invoice < ApplicationRecord
self.belongs_to_required_by_default = false
belongs_to :order, class_name: 'Spree::Order'
serialize :data, Hash
serialize :data, Hash, coder: YAML
before_validation :serialize_order
after_create :cancel_previous_invoices
default_scope { order(created_at: :desc) }

View File

@@ -91,6 +91,14 @@ class Invoice
Spree::Money.new(shipment.amount + shipment.additional_tax_total, currency:)
end
def display_line_item_tax_rate(item)
all_tax_adjustments.select { |a|
a.adjustable.type == 'Spree::LineItem' && a.adjustable.id == item.id
}.map(&:originator).map { |tr|
number_to_percentage(tr.amount * 100, precision: 1)
}.join(", ")
end
def display_shipment_tax_rates
all_eligible_adjustments.select { |a|
a.originator.type == 'Spree::TaxRate' && a.adjustable_type == 'Spree::Shipment'

View File

@@ -3,11 +3,10 @@
class Invoice
class DataPresenter
class LineItem < Invoice::DataPresenter::Base
attributes :added_tax, :currency, :included_tax, :price_with_adjustments, :quantity,
attributes :id, :added_tax, :currency, :included_tax, :price_with_adjustments, :quantity,
:variant_id, :unit_price_price_and_unit, :unit_presentation,
:enterprise_fee_additional_tax, :enterprise_fee_included_tax
attributes_with_presenter :variant
array_attribute :tax_rates, class_name: 'TaxRate'
invoice_generation_attributes :added_tax, :included_tax, :price_with_adjustments,
:quantity, :variant_id
@@ -35,10 +34,6 @@ class Invoice
fee_tax = enterprise_fee_included_tax || 0.0
Spree::Money.new(price_with_adjustments - ((included_tax + fee_tax) / quantity), currency:)
end
def display_line_item_tax_rates
tax_rates.map { |tr| number_to_percentage(tr.amount * 100, precision: 1) }.join(", ")
end
end
end
end

View File

@@ -0,0 +1,22 @@
# frozen_string_literal: true
class OidcAccount < ApplicationRecord
belongs_to :user, class_name: "Spree::User"
# When a user authenticates via token, the `uid` should be mapped to only one
# OFN user and therefore it needs to be unique.
validates :uid, presence: true, uniqueness: true
def self.link(user, auth)
attributes = {
user_id: user.id,
provider: auth.provider,
uid: auth.uid,
token: auth.dig(:credentials, :token),
refresh_token: auth.dig(:credentials, :refresh_token),
}
# This skips validations but we have database constraints in place.
# We may replace this at some point.
upsert_all([attributes], unique_by: [:user_id]) # rubocop:disable Rails/SkipsModelValidations
end
end

View File

@@ -4,5 +4,5 @@ class ReportRenderingOptions < ApplicationRecord
self.belongs_to_required_by_default = false
belongs_to :user, class_name: "Spree::User"
serialize :options, Hash
serialize :options, Hash, coder: YAML
end

View File

@@ -177,7 +177,7 @@ module Spree
can [:admin, :create], :manager_invitation
can [:admin, :index], :oidc_setting
can [:admin, :index, :destroy], :oidc_setting
can [:admin, :create], Voucher
end

View File

@@ -4,7 +4,6 @@ require 'stripe/profile_storer'
require 'stripe/credit_card_cloner'
require 'stripe/authorize_response_patcher'
require 'stripe/payment_intent_validator'
require 'active_merchant/billing/gateways/stripe_payment_intents_decorator'
require 'active_merchant/billing/gateways/stripe'
module Spree
@@ -44,7 +43,7 @@ module Spree
StripeAccount.find_by(enterprise_id: preferred_enterprise_id)&.stripe_user_id
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
# NOTE: this method is required by Spree::Payment::Processing
def purchase(money, creditcard, gateway_options)
begin
payment_intent_id = fetch_payment_intent(creditcard, gateway_options)
@@ -64,7 +63,7 @@ module Spree
provider.capture(money, payment_intent_id, options)
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
# NOTE: this method is required by Spree::Payment::Processing
def charge_offline(money, creditcard, gateway_options)
customer, payment_method =
Stripe::CreditCardCloner.new(creditcard, stripe_account_id).find_or_clone
@@ -75,7 +74,7 @@ module Spree
failed_activemerchant_billing_response(e.message)
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
# NOTE: this method is required by Spree::Payment::Processing
def authorize(money, creditcard, gateway_options)
authorize_response =
provider.authorize(*options_for_authorize(money, creditcard, gateway_options))
@@ -84,26 +83,27 @@ module Spree
failed_activemerchant_billing_response(e.message)
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
def void(response_code, _creditcard, gateway_options)
payment_intent_id = response_code
payment_intent_response = Stripe::PaymentIntent.retrieve(payment_intent_id,
stripe_account: stripe_account_id)
# NOTE: this method is required by Spree::Payment::Processing
def void(payment_intent_id, _creditcard, gateway_options)
payment_intent_response = Stripe::PaymentIntent.retrieve(
payment_intent_id, stripe_account: stripe_account_id
)
gateway_options[:stripe_account] = stripe_account_id
# If a payment has been confirmed it can't be voided by Stripe, and must be refunded instead
if voidable?(payment_intent_response)
provider.void(response_code, gateway_options)
provider.void(payment_intent_id, gateway_options)
else
provider.refund(refundable_amount(payment_intent_response), response_code,
gateway_options)
provider.refund(
payment_intent_response.amount_received, payment_intent_id, gateway_options
)
end
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
def credit(money, _creditcard, response_code, gateway_options)
# NOTE: this method is required by Spree::Payment::Processing
def credit(money, _creditcard, payment_intent_id, gateway_options)
gateway_options[:stripe_account] = stripe_account_id
provider.refund(money, response_code, gateway_options)
provider.refund(money, payment_intent_id, gateway_options)
end
def create_profile(payment)
@@ -119,11 +119,6 @@ module Spree
VOIDABLE_STATES.include? payment_intent_response.status
end
def refundable_amount(payment_intent_response)
payment_intent_response.amount_received -
payment_intent_response.charges.data.map(&:amount_refunded).sum
end
# In this gateway, what we call 'secret_key' is the 'login'
def options
options = super

View File

@@ -193,6 +193,7 @@ module Spree
adjustments.tax.additional.sum(:amount)
end
# Some of the tax rates may not be applicable depending to the order's tax zone
def tax_rates
variant&.tax_category&.tax_rates || []
end

View File

@@ -21,7 +21,8 @@ module Spree
belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
has_many :offsets, -> { where("source_type = 'Spree::Payment' AND amount < 0").completed },
class_name: "Spree::Payment", foreign_key: :source_id, dependent: :restrict_with_exception
class_name: "Spree::Payment", foreign_key: :source_id,
dependent: :restrict_with_exception
has_many :log_entries, as: :source, dependent: :destroy
has_one :adjustment, as: :adjustable, dependent: :destroy

View File

@@ -2,8 +2,7 @@
module Spree
class Preference < ApplicationRecord
serialize :value
serialize :value, coder: YAML
validates :key, presence: true
validates :value_type, presence: true

View File

@@ -287,6 +287,22 @@ module Spree
variants << variant
end
# Format as per WeightsAndMeasures (todo: re-orgnaise maybe after product/variant refactor)
def variant_unit_with_scale
scale_clean = ActiveSupport::NumberHelper.number_to_rounded(variant_unit_scale,
precision: nil,
strip_insignificant_zeros: true)
[variant_unit, scale_clean].compact_blank.join("_")
end
def variant_unit_with_scale=(variant_unit_with_scale)
values = variant_unit_with_scale.split("_")
assign_attributes(
variant_unit: values[0],
variant_unit_scale: values[1] || nil
)
end
private
def update_units

View File

@@ -42,6 +42,7 @@ module Spree
has_many :credit_cards, dependent: :destroy
has_many :report_rendering_options, class_name: "::ReportRenderingOptions", dependent: :destroy
has_many :webhook_endpoints, dependent: :destroy
has_one :oidc_account, dependent: :destroy
accepts_nested_attributes_for :enterprise_roles, allow_destroy: true
accepts_nested_attributes_for :webhook_endpoints
@@ -51,11 +52,6 @@ module Spree
validates :email, 'valid_email_2/email': { mx: true }, if: :email_changed?
validate :limit_owned_enterprises
validates :uid, uniqueness: true, if: lambda { uid.present? }
# Same validation as in the openid_connect gem.
# This validator is totally outdated but we indirectly depend on it.
validates :uid, email: true, if: lambda { uid.present? }
class DestroyWithOrdersError < StandardError; end
@@ -63,10 +59,6 @@ module Spree
User.admin.count > 0
end
def link_from_omniauth(auth)
update!(provider: auth.provider, uid: auth.uid)
end
# Whether a user has a role or not.
def has_spree_role?(role_in_question)
spree_roles.where(name: role_in_question.to_s).any?

View File

@@ -69,7 +69,7 @@ module Spree
%w(weight volume).include?(variant.product&.variant_unit)
}
validates :unit_value, numericality: { greater_than: 0 }
validates :unit_value, numericality: { greater_than: 0 }, allow_blank: true
validates :price, numericality: { greater_than_or_equal_to: 0 }
validates :unit_description, presence: true, if: ->(variant) {

View File

@@ -1,13 +1,13 @@
# frozen_string_literal: true
# Fetches complete orders of the specified user including their balance as a computed column
class CompleteOrdersWithBalance
class CompleteOrdersWithBalanceQuery
def initialize(user)
@user = user
end
def query
OutstandingBalance.new(sorted_finalized_orders).query
def call
OutstandingBalanceQuery.new(sorted_finalized_orders).call
end
private

View File

@@ -1,11 +1,11 @@
# frozen_string_literal: true
class CompleteVisibleOrders
class CompleteVisibleOrdersQuery
def initialize(order_permissions)
@order_permissions = order_permissions
end
def query
def call
order_permissions.visible_orders.complete
end

View File

@@ -2,12 +2,12 @@
# Adds an aggregated 'balance_value' to each customer based on their order history
#
class CustomersWithBalance
class CustomersWithBalanceQuery
def initialize(customers)
@customers = customers
end
def query
def call
@customers.
joins(left_join_complete_orders).
group("customers.id").
@@ -20,7 +20,7 @@ class CustomersWithBalance
# The resulting orders are in states that belong after the checkout. Only these can be considered
# for a customer's balance.
def left_join_complete_orders
<<~SQL
<<~SQL.squish
LEFT JOIN spree_orders ON spree_orders.customer_id = customers.id
AND #{finalized_states.to_sql}
SQL
@@ -32,6 +32,6 @@ class CustomersWithBalance
end
def outstanding_balance_sum
"SUM(#{OutstandingBalance.new.statement})::float"
"SUM(#{OutstandingBalanceQuery.new.statement})::float"
end
end

View File

@@ -7,11 +7,11 @@
# Alternatively, you can get the SQL by calling #statement, which is suitable for more complex
# cases.
#
# See CompleteOrdersWithBalance or CustomersWithBalance as examples.
# See CompleteOrdersWithBalanceQuery or CustomersWithBalanceQuery as examples.
#
# Note this query object and `app/models/concerns/balance.rb` should implement the same behavior
# until we find a better way. If you change one, please, change the other too.
class OutstandingBalance
class OutstandingBalanceQuery
# All the states of a finished order but that shouldn't count towards the balance (the customer
# didn't get the order for whatever reason). Note it does not include complete
FINALIZED_NON_SUCCESSFUL_STATES = %w(canceled returned).freeze
@@ -22,14 +22,14 @@ class OutstandingBalance
@relation = relation
end
def query
def call
relation.select("#{statement} AS balance_value")
end
# Arel doesn't support CASE statements until v7.1.0 so we'll have to wait with SQL literals
# a little longer. See https://github.com/rails/arel/pull/400 for details.
def statement
<<~SQL
<<~SQL.squish
CASE WHEN "spree_orders"."state" IN #{non_fulfilled_states_group.to_sql} THEN "spree_orders"."payment_total"
WHEN "spree_orders"."state" IS NOT NULL THEN "spree_orders"."payment_total" - "spree_orders"."total"
ELSE 0 END

View File

@@ -1,12 +1,12 @@
# frozen_string_literal: true
class PaymentsRequiringAction
class PaymentsRequiringActionQuery
def initialize(user)
@user = user
end
def query
Spree::Payment.joins(:order).where("spree_orders.user_id = ?", user.id).
def call
Spree::Payment.joins(:order).where(spree_orders: { user_id: user.id }).
requires_authorization
end

View File

@@ -3,8 +3,8 @@
module Api
module Admin
# This serializer relies on `object` to respond to `#balance_value`. That's done in
# `CustomersWithBalance` due to the fact that ActiveRecord maps the DB result set's columns to
# instance methods. This way, the `balance_value` alias on that class ends up being
# `CustomersWithBalanceQuery` due to the fact that ActiveRecord maps the DB result set's
# columns to instance methods. This way, the `balance_value` alias on that class ends up being
# `object.balance_value` here.
class CustomerWithBalanceSerializer < CustomerSerializer
attributes :balance, :balance_status

View File

@@ -9,8 +9,8 @@ module Api
has_many :payments, serializer: Api::PaymentSerializer
# This method relies on `balance_value` as a computed DB column. See `CompleteOrdersWithBalance`
# for reference.
# This method relies on `balance_value` as a computed DB column.
# See `CompleteOrdersWithBalanceQuery` for reference.
def outstanding_balance
-object.balance_value
end

View File

@@ -6,7 +6,6 @@ class Invoice
:variant_id, :unit_price_price_and_unit, :unit_presentation,
:enterprise_fee_additional_tax, :enterprise_fee_included_tax
has_one :variant, serializer: Invoice::VariantSerializer
has_many :tax_rates, serializer: Invoice::TaxRateSerializer
def enterprise_fee_additional_tax
EnterpriseFeeAdjustments.new(object.enterprise_fee_adjustments).total_additional_tax

View File

@@ -5,7 +5,8 @@ module PermittedAttributes
def self.attributes
[
:id, :name, :description, :supplier_id, :price,
:variant_unit, :variant_unit_scale, :unit_value, :unit_description, :variant_unit_name,
:variant_unit, :variant_unit_scale, :variant_unit_with_scale, :unit_value,
:unit_description, :variant_unit_name,
:display_as, :sku, :group_buy, :group_buy_unit_size,
:taxon_ids, :primary_taxon_id, :tax_category_id,
:meta_keywords, :notes, :inherits_properties,

View File

@@ -20,6 +20,44 @@ class WeightsAndMeasures
scales[product_scale.to_f]['system']
end
# @returns enumerable with label and value for select
def self.variant_unit_options
available_units_sorted.flat_map do |measurement, measurement_info|
measurement_info.filter_map do |scale, unit_info|
scale_clean =
ActiveSupport::NumberHelper.number_to_rounded(scale, precision: nil,
strip_insignificant_zeros: true)
[
"#{I18n.t(measurement)} (#{unit_info['name']})", # Label (eg "Weight (g)")
"#{measurement}_#{scale_clean}", # Scale ID (eg "weight_1")
]
end
end <<
[
I18n.t('items'),
'items'
]
end
def self.available_units
Spree::Config.available_units.split(",")
end
def self.available_units_sorted
self::UNITS.transform_values do |measurement_info|
# Filter to only include available units
measurement_info.filter do |_scale, unit_info|
available_units.include?(unit_info['name'])
end.
# Remove duplicates by name
uniq do |_scale, unit_info|
unit_info['name']
end.
# Sort by unit number
sort.to_h
end
end
private
UNITS = {
@@ -29,10 +67,10 @@ class WeightsAndMeasures
1000.0 => { 'name' => 'kg', 'system' => 'metric' },
1_000_000.0 => { 'name' => 'T', 'system' => 'metric' },
28.349523125 => { 'name' => 'oz', 'system' => 'imperial' },
28.35 => { 'name' => 'oz', 'system' => 'imperial' },
453.59237 => { 'name' => 'lb', 'system' => 'imperial' },
28.349523125 => { 'name' => 'oz', 'system' => 'imperial' },
453.6 => { 'name' => 'lb', 'system' => 'imperial' },
453.59237 => { 'name' => 'lb', 'system' => 'imperial' },
},
'volume' => {
0.001 => { 'name' => 'mL', 'system' => 'metric' },
@@ -49,7 +87,7 @@ class WeightsAndMeasures
return @units[@variant.product.variant_unit] if ignore_available_units
@units[@variant.product.variant_unit]&.reject { |_scale, unit_info|
available_units.exclude?(unit_info['name'])
self.class.available_units.exclude?(unit_info['name'])
}
end
@@ -67,8 +105,4 @@ class WeightsAndMeasures
largest_unit
end
def available_units
Spree::Config.available_units.split(",")
end
end

View File

@@ -14,22 +14,22 @@
= admin_inject_shops(@shops, module: 'admin.customers')
= admin_inject_available_countries(module: 'admin.customers')
%div{ ng: { controller: 'customersCtrl' } }
%div{ "ng-controller": 'customersCtrl' }
.row.filters
.sixteen.columns.alpha.omega
.filter_select.five.columns.alpha
%label{ :for => 'quick_search', ng: {class: '{disabled: !shop_id}'} }=t('admin.quick_search')
%label{ for: 'quick_search', "ng-class": '{disabled: !shop_id}' }=t('admin.quick_search')
%br
%input.fullwidth{ :type => "text", :id => 'quick_search', ng: { model: 'quickSearch', disabled: '!shop_id' }, :placeholder => t('.search_by_email') }
%input.fullwidth{ type: "text", id: 'quick_search', placeholder: t('.search_by_email'), "ng-model": 'quickSearch', "ng-disabled": '!shop_id' }
.filter_select.four.columns
%label{ :for => 'hub_id', ng: { bind: "shop_id ? '#{t('admin.shop')}' : '#{t('admin.variant_overrides.index.select_a_shop')}'" } }
%label{ for: 'hub_id', "ng-bind": "shop_id ? '#{t('admin.shop')}' : '#{t('admin.variant_overrides.index.select_a_shop')}'" }
%br
%input.ofn-select2.fullwidth#shop_id{ 'ng-model' => 'shop_id', name: 'shop_id', data: 'shops', on: { selecting: 'confirmRefresh' } }
%input.ofn-select2.fullwidth#shop_id{ "ng-model": 'shop_id', name: 'shop_id', data: 'shops', "on-selecting": 'confirmRefresh' }
.seven.columns.omega &nbsp;
%hr.divider{ ng: { show: "!RequestMonitor.loading && filteredCustomers.length > 0" } }
%hr.divider{ "ng-show": "!RequestMonitor.loading && filteredCustomers.length > 0" }
.row.controls{ ng: { show: "!RequestMonitor.loading && filteredCustomers.length > 0" } }
.row.controls{ "ng-show": "!RequestMonitor.loading && filteredCustomers.length > 0" }
.thirteen.columns.alpha &nbsp;
%columns-dropdown{ action: "#{controller_name}_#{action_name}" }
@@ -39,13 +39,13 @@
%h1
= t :loading_customers
.row.margin-bottom-50{ ng: { show: "!RequestMonitor.loading" } }
.row.margin-bottom-50{ "ng-show": "!RequestMonitor.loading" }
%form{ name: "customers_form" }
%h1#no_results{ 'ng-show' => '!RequestMonitor.loading && filteredCustomers.length == 0' }
=t :no_customers_found
%save-bar{ dirty: "customers_form.$dirty", persist: "false" }
%input.red{ type: "button", value: t(:save_changes), ng: { click: "submitAll(customers_form)" } }
%input.red{ type: "button", value: t(:save_changes), "ng-click": "submitAll(customers_form)" }
%table.index#customers{ 'ng-show' => '!RequestMonitor.loading && filteredCustomers.length > 0' }
%col.email{ width: "20%", 'ng-show' => 'columns.email.visible' }
@@ -58,7 +58,7 @@
%col.balance{ width: "10%", 'ng-show' => 'columns.balance.visible' }
%col.actions{ width: "10%"}
%thead
%tr{ ng: { controller: "ColumnsCtrl" } }
%tr{ "ng-controller": "ColumnsCtrl" }
-# %th.bulk
-# %input{ :type => "checkbox", :name => 'toggle_bulk', 'ng-click' => 'toggleAllCheckboxes()', 'ng-checked' => "allBoxesChecked()" }
%th.email{ 'ng-show' => 'columns.email.visible' }
@@ -81,12 +81,12 @@
%span{ 'ng-bind' => '::customer.email' }
%span.guest-label{ 'ng-show' => 'customer.user_id == null' }= t('.guest_label')
%td.first_name{ 'ng-show' => 'columns.first_name.visible'}
%input{ type: 'text', name: 'first_name', ng: { model: 'customer.first_name' }, 'obj-for-update' => 'customer', 'attr-for-update' => 'first_name'}
%input{ type: 'text', name: 'first_name', "obj-for-update": 'customer', "attr-for-update": 'first_name', "ng-model": 'customer.first_name' }
%td.last_name{ 'ng-show' => 'columns.last_name.visible'}
%input{ type: 'text', name: 'last_name', ng: { model: 'customer.last_name' }, 'obj-for-update' => 'customer', 'attr-for-update' => 'last_name'}
%input{ type: 'text', name: 'last_name', "obj-for-update": 'customer', "attr-for-update": 'last_name', "ng-model": 'customer.last_name' }
%td.code{ 'ng-show' => 'columns.code.visible' }
%input{ type: 'text', name: 'code', ng: {model: 'customer.code', change: 'checkForDuplicateCodes()'}, "obj-for-update" => "customer", "attr-for-update" => "code" }
%i.icon-warning-sign{ ng: {if: 'duplicate'} }
%input{ type: 'text', name: 'code', "obj-for-update": "customer", "attr-for-update": "code", "ng-model": 'customer.code', "ng-change": 'checkForDuplicateCodes()' }
%i.icon-warning-sign{ "ng-if": 'duplicate' }
= t('.duplicate_code')
%td.tags{ 'ng-show' => 'columns.tags.visible' }
.tag_watcher{ 'obj-for-update' => "customer", "attr-for-update" => "tag_list"}
@@ -101,6 +101,6 @@
%td.actions
%a{ 'ng-click' => "deleteCustomer(customer)", :class => "delete-customer icon-trash no-text" }
%div.text-center{ ng: { show: "filteredCustomers.length > customerLimit" } }
%input{ type: 'button', value: t(:show_more), ng: { click: 'customerLimit = customerLimit + 20' } }
%input{ type: 'button', value: t(:show_all_with_more, num: '{{ filteredCustomers.length - customerLimit }}'), ng: { click: 'customerLimit = filteredCustomers.length' } }
%div.text-center{ "ng-show": "filteredCustomers.length > customerLimit" }
%input{ type: 'button', value: t(:show_more), "ng-click": 'customerLimit = customerLimit + 20' }
%input{ type: 'button', value: t(:show_all_with_more, num: '{{ filteredCustomers.length - customerLimit }}'), "ng-click": 'customerLimit = filteredCustomers.length' }

View File

@@ -29,20 +29,20 @@
%th.actions
%tbody
= enterprise_fee_set_form.ng_fields_for :collection do |f|
%tr{ ng: { repeat: 'enterprise_fee in enterprise_fees | filter:query' } }
%tr{ "ng-repeat": 'enterprise_fee in enterprise_fees | filter:query' }
%td
= f.ng_hidden_field :id
%ofn-select{ :id => angular_id(:enterprise_id), data: 'enterprises', ng: { model: 'enterprise_fee.enterprise_id' }, style: "width: 90%" }
%input{ type: "hidden", name: angular_name(:enterprise_id), ng: { value: "enterprise_fee.enterprise_id" } }
%ofn-select{ id: angular_id(:enterprise_id), data: 'enterprises', style: "width: 90%", "ng-model": 'enterprise_fee.enterprise_id' }
%input{ type: "hidden", name: angular_name(:enterprise_id), "ng-value": "enterprise_fee.enterprise_id" }
%td= f.ng_select :fee_type, enterprise_fee_type_options, 'enterprise_fee.fee_type'
%td= f.ng_text_field :name, { placeholder: t('.name_placeholder') }
%td
%ofn-select{ :id => angular_id(:tax_category_id), data: 'tax_categories', include_blank: true, ng: { model: 'enterprise_fee.tax_category_id' } }
%ofn-select{ id: angular_id(:tax_category_id), data: 'tax_categories', include_blank: true, "ng-model": 'enterprise_fee.tax_category_id' }
%input{ type: "hidden", name: angular_name(:tax_category_id), 'watch-tax-category' => true }
%input{ type: "hidden", name: angular_name(:inherits_tax_category), ng: { value: "enterprise_fee.inherits_tax_category" } }
%input{ type: "hidden", name: angular_name(:inherits_tax_category), "ng-value": "enterprise_fee.inherits_tax_category" }
%td
%ofn-select.calculator_type{ :id => angular_id(:calculator_type), ng: { model: 'enterprise_fee.calculator_type' }, value_attr: 'name', text_attr: 'description', data: 'calculators', 'spree-ensure-calculator-preferences-match-type' => true }
%input{ type: "hidden", name: angular_name(:calculator_type), ng: { value: "enterprise_fee.calculator_type" } }
%ofn-select.calculator_type{ id: angular_id(:calculator_type), value_attr: 'name', text_attr: 'description', data: 'calculators', "spree-ensure-calculator-preferences-match-type": true, "ng-model": 'enterprise_fee.calculator_type' }
%input{ type: "hidden", name: angular_name(:calculator_type), "ng-value": "enterprise_fee.calculator_type" }
%td{'ng-bind-html-unsafe-compiled' => 'enterprise_fee.calculator_settings'}
%td.actions{'spree-delete-resource' => "1"}

View File

@@ -1,7 +1,7 @@
= render 'spree/shared/error_messages', target: @enterprise
= form_for [main_app, :admin, @enterprise_group] do |f|
.row{ ng: {app: 'admin.enterprise_groups', controller: 'enterpriseGroupCtrl'}, data: { controller: 'tabs-and-panels', "tabs-and-panels-class-name-value": "selected" } }
.row{ data: { controller: 'tabs-and-panels', "tabs-and-panels-class-name-value": "selected" }, "ng-app": 'admin.enterprise_groups', "ng-controller": 'enterpriseGroupCtrl' }
.sixteen.columns.alpha
.four.columns.alpha
= render 'admin/shared/side_menu'

View File

@@ -8,7 +8,7 @@
%select.select2.fullwidth{id: "enterprise_relationship_child_id", "ng-model" => "child_id", "ng-options" => "e.id as e.name for e in Enterprises.all_enterprises"}
%td
%label
%input{type: "checkbox", ng: {checked: "allPermissionsChecked()", click: "checkAllPermissions()"}}
%input{ type: "checkbox", "ng-checked": "allPermissionsChecked()", "ng-click": "checkAllPermissions()" }
= t 'admin_enterprise_relationships_everything'
%div{"ng-repeat" => "permission in EnterpriseRelationships.all_permissions"}
%label

View File

@@ -1,5 +1,5 @@
%input.search{"ng-model" => "query", "placeholder" => t(:admin_enterprise_relationships_seach_placeholder)}
%label{ng: {repeat: "permission in EnterpriseRelationships.all_permissions"}}
%input{type: "checkbox", ng: {click: "$parent.query = toggleKeyword($parent.query, permission)"}}
%label{ "ng-repeat": "permission in EnterpriseRelationships.all_permissions" }
%input{ type: "checkbox", "ng-click": "$parent.query = toggleKeyword($parent.query, permission)" }
{{ EnterpriseRelationships.permission_presentation(permission) }}

View File

@@ -3,13 +3,13 @@
= form_for @enterprise, url: main_app.register_admin_enterprise_path(@enterprise),
html: { name: "change_type", id: "change_type", novalidate: true, "ng-app" => "admin.enterprises", "ng-controller"=> 'changeTypeFormCtrl' } do |change_type_form|
-# Have to use hidden:'true' on this input rather than type:'hidden' as the latter seems to break ngPattern and therefore validation
%input{ hidden: "true", name: "sells", ng: { required: true, pattern: "/^(none|own|any)$/", model: 'sells', value: "sells"} }
%input{ hidden: "true", name: "sells", "ng-required": true, "ng-pattern": "/^(none|own|any)$/", "ng-model": 'sells', "ng-value": "sells" }
.row
.options.container
- if @enterprise.is_primary_producer
.basic_producer.option.six.columns.alpha
%a.full-width.button.selector{ ng: { click: "sells='none'", class: "{selected: sells=='none'}" } }
%a.full-width.button.selector{ "ng-click": "sells='none'", "ng-class": "{selected: sells=='none'}" }
.top
%h3= t('.producer_profile')
%p= t('.connect_ofn')
@@ -18,7 +18,7 @@
= t('.producer_description_text')
.producer_shop.option.six.columns
%a.full-width.button.selector{ ng: { click: "sells='own'", class: "{selected: sells=='own'}" } }
%a.full-width.button.selector{ "ng-click": "sells='own'", "ng-class": "{selected: sells=='own'}" }
.top
%h3= t('.producer_shop')
%p= t('.sell_your_produce')
@@ -29,7 +29,7 @@
= t('.producer_shop_description_text2')
.full_hub.option.six.columns.omega
%a.full-width.button.selector{ ng: { click: "sells='any'", class: "{selected: sells=='any'}" } }
%a.full-width.button.selector{ "ng-click": "sells='any'", "ng-class": "{selected: sells=='any'}" }
.top
%h3= t('.producer_hub')
%p= t('.producer_hub_text')
@@ -40,7 +40,7 @@
.two.columns.alpha
&nbsp;
.shop_profile.option.six.columns
%a.full-width.button.selector{ ng: { click: "sells='none'", class: "{selected: sells=='none'}" } }
%a.full-width.button.selector{ "ng-click": "sells='none'", "ng-class": "{selected: sells=='none'}" }
.top
%h3= t('.profile')
%p= t('.get_listing')
@@ -49,7 +49,7 @@
= t('.profile_description_text')
.full_hub.option.six.columns
%a.full-width.button.selector{ ng: { click: "sells='any'", class: "{selected: sells=='any'}" } }
%a.full-width.button.selector{ "ng-click": "sells='any'", "ng-class": "{selected: sells=='any'}" }
.top
%h3= t('.hub_shop')
%p= t('.hub_shop_text')
@@ -60,11 +60,11 @@
.row
.sixteen.columns.alpha
%span.error{ ng: { show: "(change_type.sells.$error.required || change_type.sells.$error.pattern) && submitted" } }
%span.error{ "ng-show": "(change_type.sells.$error.required || change_type.sells.$error.pattern) && submitted" }
= t('.choose_option')
- if @enterprise.sells == 'unspecified'
%input.button.big{ type: 'submit', value: t(:select_continue), ng: { click: "submit(change_type)" } }
%input.button.big{ type: 'submit', value: t(:select_continue), "ng-click": "submit(change_type)" }
- else
%input.button.big{ type: 'submit', value: t('.change_now'), ng: { click: "submit(change_type)" } }
%input.button.big{ type: 'submit', value: t('.change_now'), "ng-click": "submit(change_type)" }
%br &nbsp;
%hr

View File

@@ -1,4 +1,4 @@
%div{ ng: { controller: 'enterprisesCtrl' } }
%div{ "ng-controller": 'enterprisesCtrl' }
.row{ 'ng-hide' => '!loaded' }
.controls{ :class => "sixteen columns alpha", :style => "margin-bottom: 15px;" }
.four.columns.alpha
@@ -15,32 +15,32 @@
.row{ :class => "sixteen columns alpha", 'ng-show' => 'loaded && filteredEnterprises.length == 0'}
%h1#no_results= t('.no_enterprises_found')
.row{ ng: { show: "loaded && filteredEnterprises.length > 0" } }
.row{ "ng-show": "loaded && filteredEnterprises.length > 0" }
%table.index#enterprises
%col.name{ width: "28%", ng: { show: 'columns.name.visible' } }
%col.producer{ width: "18%", ng: { show: 'columns.producer.visible' }}
%col.package{ width: "18%", ng: { show: 'columns.package.visible' }}
%col.status{ width: "18%", ng: { show: 'columns.status.visible' }}
%col.manage{ width: "18%", ng: { show: 'columns.manage.visible' }}
%col.name{ width: "28%", "ng-show": 'columns.name.visible' }
%col.producer{ width: "18%", "ng-show": 'columns.producer.visible' }
%col.package{ width: "18%", "ng-show": 'columns.package.visible' }
%col.status{ width: "18%", "ng-show": 'columns.status.visible' }
%col.manage{ width: "18%", "ng-show": 'columns.manage.visible' }
%thead
%tr{ ng: { controller: "ColumnsCtrl" } }
%th.name{ ng: { show: 'columns.name.visible' } }=t('admin.name')
%th.producer{ ng: { show: 'columns.producer.visible' } }=t('.producer?')
%th.package{ ng: { show: 'columns.package.visible' } }=t('.package')
%th.status{ ng: { show: 'columns.status.visible' } }=t('.status')
%th.manage{ ng: { show: 'columns.manage.visible' } }=t('.manage')
%tbody.panel-ctrl{ :id => "e_{{enterprise.id}}", object: "enterprise", ng: { repeat: "enterprise in filteredEnterprises = ( allEnterprises | filter:{ name: quickSearch } )" } }
%tr.enterprise{ ng: { class: { even: "'even'", odd: "'odd'"} } }
%td.name{ ng: { show: 'columns.name.visible' } }
%span{ ng: { bind: "::enterprise.name" } }
%td.producer.panel-toggle.text-center{ ng: { show: 'columns.producer.visible', class: "{error: enterprise.producerError}" }, name: "producer" }
%h5{ ng: { bind: "enterprise.producer" } }
%td.package.panel-toggle.text-center{ ng: { show: 'columns.package.visible', class: "{error: enterprise.packageError}" }, name: "package" }
%h5{ ng: { bind: "enterprise.package" } }
%td.status.panel-toggle.text-center{ ng: { show: 'columns.status.visible' }, name: "status" }
%i.icon-status{ ng: { class: "enterprise.status" } }
%td.manage{ ng: { show: 'columns.manage.visible' } }
%a.button.fullwidth{ ng: { href: '{{::enterprise.edit_path}}' } }
%tr{ "ng-controller": "ColumnsCtrl" }
%th.name{ "ng-show": 'columns.name.visible' }=t('admin.name')
%th.producer{ "ng-show": 'columns.producer.visible' }=t('.producer?')
%th.package{ "ng-show": 'columns.package.visible' }=t('.package')
%th.status{ "ng-show": 'columns.status.visible' }=t('.status')
%th.manage{ "ng-show": 'columns.manage.visible' }=t('.manage')
%tbody.panel-ctrl{ id: "e_{{enterprise.id}}", object: "enterprise", "ng-repeat": "enterprise in filteredEnterprises = ( allEnterprises | filter:{ name: quickSearch } )" }
%tr.enterprise{ "ng-class-even": "'even'", "ng-class-odd": "'odd'" }
%td.name{ "ng-show": 'columns.name.visible' }
%span{ "ng-bind": "::enterprise.name" }
%td.producer.panel-toggle.text-center{ name: "producer", "ng-show": 'columns.producer.visible', "ng-class": "{error: enterprise.producerError}" }
%h5{ "ng-bind": "enterprise.producer" }
%td.package.panel-toggle.text-center{ name: "package", "ng-show": 'columns.package.visible', "ng-class": "{error: enterprise.packageError}" }
%h5{ "ng-bind": "enterprise.package" }
%td.status.panel-toggle.text-center{ name: "status", "ng-show": 'columns.status.visible' }
%i.icon-status{ "ng-class": "enterprise.status" }
%td.manage{ "ng-show": 'columns.manage.visible' }
%a.button.fullwidth{ "ng-href": '{{::enterprise.edit_path}}' }
= t('.manage_link')
%i.icon-arrow-right

View File

@@ -8,8 +8,8 @@
"ng-cloak" => true } do |f|
%save-bar{ dirty: "enterprise_form.$dirty", persist: "true" }
%input.red{ type: "button", value: t(:update), ng: { click: "submit()", disabled: "!enterprise_form.$dirty" } }
%input{ type: "button", ng: { value: "enterprise_form.$dirty ? '#{t(:cancel)}' : '#{t(:close)}'", click: "cancel('#{main_app.admin_enterprises_path}')" } }
%input.red{ type: "button", value: t(:update), "ng-click": "submit()", "ng-disabled": "!enterprise_form.$dirty" }
%input{ type: "button", "ng-value": "enterprise_form.$dirty ? '#{t(:cancel)}' : '#{t(:close)}'", "ng-click": "cancel('#{main_app.admin_enterprises_path}')" }
.row{ data: {
controller: "tabs-and-panels", "tabs-and-panels-class-name-value": "selected" }}

View File

@@ -4,10 +4,10 @@
%br
= t('.logo_size')
.omega.eight.columns
%img{ class: 'image-field-group__preview-image', ng: { src: '{{ Enterprise.logo.thumb }}', if: 'Enterprise.logo' } }
%img{ class: 'image-field-group__preview-image', "ng-src": '{{ Enterprise.logo.thumb }}', "ng-if": 'Enterprise.logo' }
%br
= f.file_field :logo
%a.button.red{ href: '', ng: {click: 'removeLogo()', if: 'Enterprise.logo'} }
%a.button.red{ href: '', "ng-click": 'removeLogo()', "ng-if": 'Enterprise.logo' }
= t('.remove_logo')
.row.page-admin-enterprises-form__promo-image-field-group.image-field-group
@@ -21,7 +21,7 @@
= t('.promo_image_note3')
.omega.eight.columns
%img{ class: 'image-field-group__preview-image', ng: { src: '{{ Enterprise.promo_image.large }}', if: 'Enterprise.promo_image' } }
%img{ class: 'image-field-group__preview-image', "ng-src": '{{ Enterprise.promo_image.large }}', "ng-if": 'Enterprise.promo_image' }
= f.file_field :promo_image
%a.button.red{ href: '', ng: {click: 'removePromoImage()', if: 'Enterprise.promo_image'} }
%a.button.red{ href: '', "ng-click": 'removePromoImage()', "ng-if": 'Enterprise.promo_image' }
= t('.remove_promo_image')

View File

@@ -23,17 +23,13 @@
= radio_button :enterprise, :preferred_shopfront_product_sorting_method, :by_category, { 'ng-model' => 'Enterprise.preferred_shopfront_product_sorting_method' }
= label :enterprise, :preferred_shopfront_product_sorting_method_by_category, t('.shopfront_sort_by_category')
.eight.columns.omega
%textarea.fullwidth{ id: 'enterprise_preferred_shopfront_taxon_order', name: 'enterprise[preferred_shopfront_taxon_order]', rows: 6,
'ofn-taxon-autocomplete' => '', 'multiple-selection' => 'true', placeholder: t('.shopfront_sort_by_category_placeholder'),
ng: { model: 'Enterprise.preferred_shopfront_taxon_order', readonly: "Enterprise.preferred_shopfront_product_sorting_method != 'by_category'" }}
%textarea.fullwidth{ id: 'enterprise_preferred_shopfront_taxon_order', name: 'enterprise[preferred_shopfront_taxon_order]', rows: 6, "ofn-taxon-autocomplete": '', "multiple-selection": 'true', placeholder: t('.shopfront_sort_by_category_placeholder'), "ng-model": 'Enterprise.preferred_shopfront_taxon_order', "ng-readonly": "Enterprise.preferred_shopfront_product_sorting_method != 'by_category'" }
.row
.three.columns.alpha
= radio_button :enterprise, :preferred_shopfront_product_sorting_method, :by_producer, { 'ng-model' => 'Enterprise.preferred_shopfront_product_sorting_method' }
= label :enterprise, :preferred_shopfront_product_sorting_method_by_producer, t('.shopfront_sort_by_producer')
.eight.columns.omega
%textarea.fullwidth{ id: 'enterprise_preferred_shopfront_producer_order', name: 'enterprise[preferred_shopfront_producer_order]', rows: 6,
'ofn-producer-autocomplete' => '', 'multiple-selection' => 'true', placeholder: t('.shopfront_sort_by_producer_placeholder'),
ng: { model: 'Enterprise.preferred_shopfront_producer_order', readonly: "Enterprise.preferred_shopfront_product_sorting_method != 'by_producer'" }}
%textarea.fullwidth{ id: 'enterprise_preferred_shopfront_producer_order', name: 'enterprise[preferred_shopfront_producer_order]', rows: 6, "ofn-producer-autocomplete": '', "multiple-selection": 'true', placeholder: t('.shopfront_sort_by_producer_placeholder'), "ng-model": 'Enterprise.preferred_shopfront_producer_order', "ng-readonly": "Enterprise.preferred_shopfront_product_sorting_method != 'by_producer'" }
.row
.three.columns.alpha
@@ -56,7 +52,7 @@
= f.radio_button :require_login, true, "ng-model" => "Enterprise.require_login", "ng-value" => "true"
= f.label :require_login, t('.shopfront_requires_login_true'), value: :true
.row{ng: {if: "!Enterprise.require_login"}}
.row{ "ng-if": "!Enterprise.require_login" }
.three.columns.alpha
%label= t '.allow_guest_orders'
%div{'ofn-with-tip' => t('.allow_guest_orders_tip')}
@@ -67,7 +63,7 @@
.five.columns.omega
= f.radio_button :allow_guest_orders, false, "ng-model" => "Enterprise.allow_guest_orders", "ng-value" => "false"
= f.label :allow_guest_orders, t('.allow_guest_orders_false'), value: :false
.row.warning{ng: {show: 'Enterprise.allow_guest_orders && Enterprise.allow_order_changes'}}
.row.warning{ "ng-show": 'Enterprise.allow_guest_orders && Enterprise.allow_order_changes' }
.eight.columns.alpha.omega
%i.icon-warning-sign
= t '.recommend_require_login'

View File

@@ -1,11 +1,11 @@
.row{ ng: { controller: "TagRulesCtrl" } }
.row{ "ng-controller": "TagRulesCtrl" }
.eleven.columns.alpha.omega
%ofn-sortable{ axis: "y", handle: ".header", items: '.customer_tag', position: "tagGroup.position", after: { sort: "updateRuleCounts()" } }
.no_tags{ ng: { show: "tagGroups.length == 0" } }
%ofn-sortable{ axis: "y", handle: ".header", items: '.customer_tag', position: "tagGroup.position", "after-sort": "updateRuleCounts()" }
.no_tags{ "ng-show": "tagGroups.length == 0" }
= t('.no_tags_yet')
= render 'admin/enterprises/form/tag_rules/default_rules'
-# = render 'customer_tags'
.customer_tag{ id: "tg_{{tagGroup.position}}", ng: { repeat: "tagGroup in tagGroups" } }
.customer_tag{ id: "tg_{{tagGroup.position}}", "ng-repeat": "tagGroup in tagGroups" }
.header
%table
%colgroup
@@ -16,12 +16,12 @@
%h5
= t('.for_customers_tagged')
%td
%tags-with-translation{ object: "tagGroup", max: 1, on: { tag: { added: "updateTagsRulesFor(tagGroup)", removed: "updateTagsRulesFor(tagGroup)" } } }
%tags-with-translation{ object: "tagGroup", max: 1, "on-tag-added": "updateTagsRulesFor(tagGroup)", "on-tag-removed": "updateTagsRulesFor(tagGroup)" }
.no_rules{ ng: { show: "tagGroup.rules.length == 0" } }
.no_rules{ "ng-show": "tagGroup.rules.length == 0" }
= t('.no_rules_yet')
.tag_rule{ ng: { repeat: "rule in tagGroup.rules" } }
.tag_rule{ "ng-repeat": "rule in tagGroup.rules" }
.add_rule.text-center
%input.button.icon-plus{ type: 'button', value: t('.add_new_rule'), "add-new-rule-to" => "addNewRuleTo", "tag-group" => "tagGroup", "new-tag-rule-dialog" => true }
.add_tag
%input.button.red.icon-plus{ type: 'button', value: t('.add_new_tag'), ng: { click: 'addNewTag()' } }
%input.button.red.icon-plus{ type: 'button', value: t('.add_new_tag'), "ng-click": 'addNewTag()' }

View File

@@ -21,8 +21,8 @@
= render partial: 'admin/shared/whats_this_tooltip', locals: {tooltip_text: t('.contact_tip')}
.eight.columns.omega
- if full_permissions
%select.select2.fullwidth{id: 'receives_notifications_dropdown', name: 'receives_notifications', ng: {model: 'receivesNotifications', init: "receivesNotifications = '#{@enterprise.contact.id}'"}}
%option{ng: {repeat: 'user in Enterprise.users', selected: "user.id == #{@enterprise.contact.id}", hide: '!user.confirmed'}, value: '{{user.id}}'}
%select.select2.fullwidth{ id: 'receives_notifications_dropdown', name: 'receives_notifications', "ng-model": 'receivesNotifications', "ng-init": "receivesNotifications = '#{@enterprise.contact.id}'" }
%option{ value: '{{user.id}}', "ng-repeat": 'user in Enterprise.users', "ng-selected": "user.id == #{@enterprise.contact.id}", "ng-hide": '!user.confirmed' }
{{user.email}}
- else
= @enterprise.contact.email
@@ -41,16 +41,16 @@
- # Ignore this input in the submit
= hidden_field_tag :ignored, nil, class: "select2 fullwidth", 'user-select' => 'newManager', 'ng-model' => 'newManager'
%td.actions
%tr.animate-repeat{ id: "manager-{{manager.id}}", ng: { repeat: 'manager in Enterprise.users' }}
%tr.animate-repeat{ id: "manager-{{manager.id}}", "ng-repeat": 'manager in Enterprise.users' }
%td
= hidden_field_tag "enterprise[user_ids][]", nil, multiple: true, 'ng-value' => 'manager.id'
{{ manager.email }}
%i.confirmation.confirmed.fa.fa-check-circle{ 'ofn-with-tip' => t('.email_confirmed'), ng: {show: 'manager.confirmed'} }
%i.confirmation.unconfirmed.fa.fa-exclamation-triangle{ 'ofn-with-tip' => t('.email_not_confirmed'), ng: {show: '!manager.confirmed'} }
%i.role.contact.fa.fa-envelope-o{ 'ofn-with-tip' => t('.contact'), ng: {show: 'manager.id == receivesNotifications'} }
%i.role.owner.fa.fa-star{ 'ofn-with-tip' => t('.owner'), ng: {show: 'manager.id == Enterprise.owner.id'} }
%i.confirmation.confirmed.fa.fa-check-circle{ "ofn-with-tip": t('.email_confirmed'), "ng-show": 'manager.confirmed' }
%i.confirmation.unconfirmed.fa.fa-exclamation-triangle{ "ofn-with-tip": t('.email_not_confirmed'), "ng-show": '!manager.confirmed' }
%i.role.contact.fa.fa-envelope-o{ "ofn-with-tip": t('.contact'), "ng-show": 'manager.id == receivesNotifications' }
%i.role.owner.fa.fa-star{ "ofn-with-tip": t('.owner'), "ng-show": 'manager.id == Enterprise.owner.id' }
%td.actions
%a{ ng: {click: 'removeManager(manager)', class: "{disabled: manager.id == Enterprise.owner.id || manager.id == receivesNotifications}"}, :class => "icon-trash no-text" }
%a{ class: "icon-trash no-text", "ng-click": 'removeManager(manager)', "ng-class": "{disabled: manager.id == Enterprise.owner.id || manager.id == receivesNotifications}" }
- else
- @enterprise.users.each do |manager|

View File

@@ -8,9 +8,9 @@
%h5
= t('.by_default')
%i.text-big.icon-question-sign{ "data-controller": "help-modal-link", "data-action": "click->help-modal-link#open", "data-help-modal-link-target-value": "tag_rule_help_modal" }
.no_rules{ ng: { show: "defaultTagGroup.rules.length == 0" } }
.no_rules{ "ng-show": "defaultTagGroup.rules.length == 0" }
= t('.no_rules_yet')
.tag_rule{ ng: { repeat: "rule in defaultTagGroup.rules" } }
.tag_rule{ "ng-repeat": "rule in defaultTagGroup.rules" }
.add_rule.text-center
%input.button.icon-plus{ type: 'button', value: t('.add_new_button'), "add-new-rule-to" => "addNewRuleTo", "tag-group" => "defaultTagGroup", "new-tag-rule-dialog" => true }

View File

@@ -16,5 +16,5 @@
= form_for [main_app, :admin, @enterprise], html: { "nav-check" => '', "nav-callback" => '' } do |f|
.row
.twelve.columns.fullwidth_inputs{ ng: { controller: "NewEnterpriseController" } }
.twelve.columns.fullwidth_inputs{ "ng-controller": "NewEnterpriseController" }
= render 'new_form', f: f, scope: 'admin.enterprises.form'

View File

@@ -10,10 +10,11 @@
= check_box_tag 'preferences[enable_invoices?]', '1', Spree::Config[:enable_invoices?]
= label_tag nil, t('.enable_invoices?')
.field.align-center
= hidden_field_tag 'preferences[invoice_style2?]', '0'
= check_box_tag 'preferences[invoice_style2?]', '1', Spree::Config[:invoice_style2?]
= label_tag nil, t('.invoice_style2?')
- if ! OpenFoodNetwork::FeatureToggle.enabled?(:invoices, spree_current_user)
.field.align-center
= hidden_field_tag 'preferences[invoice_style2?]', '0'
= check_box_tag 'preferences[invoice_style2?]', '1', Spree::Config[:invoice_style2?]
= label_tag nil, t('.invoice_style2?')
.field.align-center
= hidden_field_tag 'preferences[enterprise_number_required_on_invoices?]', '0'

View File

@@ -7,14 +7,26 @@
%h2= t(".connect")
%br
- if spree_current_user.provider == 'openid_connect' && spree_current_user.uid.present?
= t(".already_connected")
= spree_current_user.uid
- if @account
= t(".connected", uid: @account.uid)
%br
%br
= t(".view_account")
= link_to t(".les_communs_link"), "#{ Devise.omniauth_configs[:openid_connect].options[:issuer] }/account"
%br
%br
= button_to t(".disconnect"), admin_oidc_setting_path(@account), method: :delete
- if @account.refresh_token.blank?
%br
%br
%p= t(".note_expiry")
%br
%br
= button_to t(".refresh"),
Spree::Core::Engine.routes.url_helpers.spree_user_openid_connect_omniauth_authorize_path(auth_type: "login"),
data: { method: :post, "ujs-navigate": "false" }
- else
= t(".link_your_account")

View File

@@ -22,7 +22,7 @@
.omega.eight.columns
= f.check_box :automatic_notifications
.row{ "data-controller": "remote-toggle", "data-remote-toggle-selector-value": "#advanced_settings" }
.row{ "data-controller": "toggle-control", "data-toggle-control-selector-value": "#advanced_settings" }
.sixteen.columns.alpha.omega.text-center
%input{ type: 'submit', value: t('.save_reload') }
%a{ href: "#", "data-action": "click->remote-toggle#toggle" }= t(:close)
%a{ href: "#", "data-action": "click->toggle-control#toggleAdvancedSettings" }= t(:close)

View File

@@ -1,4 +1,4 @@
%tr{ ng: { class: "'#{type} #{type}-{{ exchange.enterprise_id }}'" } }
%tr{ "ng-class": "'#{type} #{type}-{{ exchange.enterprise_id }}'" }
%td{:class => "#{type}_name"} {{ enterprises[exchange.enterprise_id].name }}
%td.products.panel-toggle.text-center{ name: "products" }
{{ exchangeSelectedVariants(exchange) }} / {{ exchangeTotalVariants(exchange) }}
@@ -7,7 +7,7 @@
%td.receival-details
= text_field_tag 'order_cycle_incoming_exchange_{{ $index }}_receival_instructions', '', 'id' => 'order_cycle_incoming_exchange_{{ $index }}_receival_instructions', 'placeholder' => t('.receival_instructions_placeholder'), 'ng-model' => 'exchange.receival_instructions'
- if type == 'distributor'
%td.tags.panel-toggle.text-center{ name: "tags", ng: { if: 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' } }
%td.tags.panel-toggle.text-center{ name: "tags", "ng-if": 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' }
{{ exchange.tags.length }}
%td.collection-details
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', '', 'ng-init' => 'setPickupTimeFieldDirty($index, exchange.pickup_time)', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', 'required' => 'required', 'placeholder' => t('.pickup_time_placeholder'), 'ng-model' => 'exchange.pickup_time', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator', 'maxlength' => 35
@@ -16,7 +16,7 @@
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', 'placeholder' => t('.pickup_instructions_placeholder'), 'ng-model' => 'exchange.pickup_instructions', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator'
%span.icon-question-sign{'ofn-with-tip' => t('.pickup_instructions_tip')}
%td.fees
%ol{ ng: { show: 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' } }
%ol{ "ng-show": 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' }
%li{'ng-repeat' => 'enterprise_fee in exchange.enterprise_fees'}
= select_tag 'order_cycle_{{ exchangeDirection(exchange) }}_exchange_{{ $parent.$index }}_enterprise_fees_{{ $index }}_enterprise_id', nil, {'id' => 'order_cycle_{{ exchangeDirection(exchange) }}_exchange_{{ $parent.$index }}_enterprise_fees_{{ $index }}_enterprise_id', 'ng-model' => 'enterprise_fee.enterprise_id', 'ng-options' => 'enterprise.id as enterprise.name for enterprise in enterprisesWithFees()'}

View File

@@ -2,20 +2,20 @@
.filter.four.columns.alpha
%label{ :for => 'query' }=t('admin.quick_search')
%br
%input.fullwidth{ :type => "text", :id => 'query', ng: { model: 'query' }, placeholder: t(".search_by_order_cycle_name") }
%input.fullwidth{ type: "text", id: 'query', placeholder: t(".search_by_order_cycle_name"), "ng-model": 'query' }
.filter_select.four.columns
%label{ :for => 'involving_filter' }=t('.involving')
%br
%input.ofn-select2.fullwidth{ id: 'involving_filter', type: 'number', blank: "{id: 0, name: '#{j t(".any_enterprise")}'}", data: 'enterprises', ng: { model: 'involvingFilter' } }
%input.ofn-select2.fullwidth{ id: 'involving_filter', type: 'number', blank: "{id: 0, name: '#{j t(".any_enterprise")}'}", data: 'enterprises', "ng-model": 'involvingFilter' }
- if subscriptions_enabled?
.filter_select.four.columns
%label{ :for => 'schedule_filter' }=t('admin.order_cycles.index.schedule')
%br
%input.ofn-select2.fullwidth{ id: 'schedule_filter', type: 'number', blank: "{id: 0, name: '#{j t(".any_schedule")}'}", data: 'schedules', ng: { model: 'scheduleFilter' } }
%input.ofn-select2.fullwidth{ id: 'schedule_filter', type: 'number', blank: "{id: 0, name: '#{j t(".any_schedule")}'}", data: 'schedules', "ng-model": 'scheduleFilter' }
.one.columns &nbsp;
- else
.five.columns &nbsp;
.filter_clear.three.columns.omega
%label{ :for => 'clear_all_filters' }
%br
%input.red.fullwidth{ :type => 'button', :id => 'clear_all_filters', :value => "#{t('admin.clear_all')}", ng: { click: "resetSelectFilters()" } }
%input.red.fullwidth{ type: 'button', id: 'clear_all_filters', value: "#{t('admin.clear_all')}", "ng-click": "resetSelectFilters()" }

View File

@@ -1,35 +1,35 @@
%colgroup
%col{ ng: { show: 'columns.name.visible' } }
%col{ ng: { show: 'columns.schedules.visible' } }
%col{ ng: { show: 'columns.open.visible' }, style: 'width: 20%;' }
%col{ ng: { show: 'columns.close.visible' }, style: 'width: 20%;' }
%col{ "ng-show": 'columns.name.visible' }
%col{ "ng-show": 'columns.schedules.visible' }
%col{ style: 'width: 20%;', "ng-show": 'columns.open.visible' }
%col{ style: 'width: 20%;', "ng-show": 'columns.close.visible' }
- unless simple_index
%col{ ng: { show: 'columns.producers.visible' } }
%col{ ng: { show: 'columns.coordinator.visible' } }
%col{ ng: { show: 'columns.shops.visible' } }
%col{ ng: { show: 'columns.products.visible' } }
%col{ "ng-show": 'columns.producers.visible' }
%col{ "ng-show": 'columns.coordinator.visible' }
%col{ "ng-show": 'columns.shops.visible' }
%col{ "ng-show": 'columns.products.visible' }
%col{ style: 'width: 5%;' }
%col{ style: 'width: 5%;' }
%col{ style: 'width: 5%;' }
%thead
%tr
%th{ ng: { show: 'columns.name.visible' } }
%th{ "ng-show": 'columns.name.visible' }
=t :name
%th{ ng: { show: 'columns.schedules.visible' } }
%th{ "ng-show": 'columns.schedules.visible' }
=t('admin.order_cycles.index.schedules')
%th{ ng: { show: 'columns.open.visible' } }
%th{ "ng-show": 'columns.open.visible' }
=t :open
%th{ ng: { show: 'columns.close.visible' } }
%th{ "ng-show": 'columns.close.visible' }
=t :close
- unless simple_index
%th{ ng: { show: 'columns.producers.visible' } }
%th{ "ng-show": 'columns.producers.visible' }
=t :label_producers
%th{ ng: { show: 'columns.coordinator.visible' } }
%th{ "ng-show": 'columns.coordinator.visible' }
=t :coordinator
%th{ ng: { show: 'columns.shops.visible' } }
%th{ "ng-show": 'columns.shops.visible' }
=t :label_shops
%th{ ng: { show: 'columns.products.visible' } }
%th{ "ng-show": 'columns.products.visible' }
=t :products
%th.actions
%th.actions

View File

@@ -1,6 +1,6 @@
%div.sixteen.columns.alpha.omega#loading{ ng: { cloak: true, if: 'RequestMonitor.loading' } }
%div.sixteen.columns.alpha.omega#loading{ "ng-cloak": true, "ng-if": 'RequestMonitor.loading' }
= render partial: "components/admin_spinner"
%h1{ ng: { hide: 'orderCycles.length > 0' } }
%h1{ "ng-hide": 'orderCycles.length > 0' }
= t('.loading_order_cycles')
%h1{ ng: { show: 'orderCycles.length > 0' } }
%h1{ "ng-show": 'orderCycles.length > 0' }
= t('.loading')

View File

@@ -35,11 +35,6 @@
= f.label :schedule_ids, t('admin.order_cycles.index.schedules')
.six.columns
- if viewing_as_coordinator_of?(@order_cycle)
%input.fullwidth.ofn-select2#schedule_ids{ name: 'order_cycle[schedule_ids]',
data: 'schedules',
multiple: 'true',
placeholder: t('admin.please_select'),
filter: '{viewing_as_coordinator: true}',
ng: { model: 'order_cycle.schedule_ids' } }
%input.fullwidth.ofn-select2#schedule_ids{ name: 'order_cycle[schedule_ids]', data: 'schedules', multiple: 'true', placeholder: t('admin.please_select'), filter: '{viewing_as_coordinator: true}', "ng-model": 'order_cycle.schedule_ids' }
- else
%schedule-list{ 'order-cycle' => 'order_cycle' }

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