mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-12 18:36:49 +00:00
Compare commits
205 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0634735288 | ||
|
|
719c45b408 | ||
|
|
b70edd5424 | ||
|
|
a6498c2f96 | ||
|
|
56be7b1d46 | ||
|
|
b2f3477261 | ||
|
|
14b73149be | ||
|
|
0ab7d95607 | ||
|
|
ee08dcfeb4 | ||
|
|
b893dea810 | ||
|
|
ec5ce45850 | ||
|
|
9afb97fa0f | ||
|
|
676abe0ced | ||
|
|
73d38cb91b | ||
|
|
fffae46a63 | ||
|
|
6ed91cab1f | ||
|
|
cc5d0c35dd | ||
|
|
c34570154c | ||
|
|
a5940e1641 | ||
|
|
39f0c5b5b0 | ||
|
|
abb5adec43 | ||
|
|
525cb4826f | ||
|
|
fde0aba96c | ||
|
|
ff18fd25f1 | ||
|
|
9248ac05ac | ||
|
|
a066c6391d | ||
|
|
4d11485283 | ||
|
|
9e270690ef | ||
|
|
15b781b271 | ||
|
|
5dc8f21b7b | ||
|
|
9ccb3ee80b | ||
|
|
27de66b055 | ||
|
|
ba98c7e2c5 | ||
|
|
22eae753fe | ||
|
|
d832d850fe | ||
|
|
aead867ea0 | ||
|
|
97f5022bdd | ||
|
|
0cb7a555d3 | ||
|
|
52b7872a55 | ||
|
|
522aaee1a3 | ||
|
|
179cf6e484 | ||
|
|
28ded1f0c2 | ||
|
|
7d971fc39d | ||
|
|
4f0b20e8ad | ||
|
|
a6f2ee1367 | ||
|
|
eb1c598a6c | ||
|
|
4706bf0528 | ||
|
|
969b6caa96 | ||
|
|
69ea1e6d26 | ||
|
|
91704d9df7 | ||
|
|
dbbc2ddb1c | ||
|
|
99729457cc | ||
|
|
5a58294bc6 | ||
|
|
398b3bbd8b | ||
|
|
6cb038c362 | ||
|
|
cc40948783 | ||
|
|
00bdcd3948 | ||
|
|
c860ffc176 | ||
|
|
8664411880 | ||
|
|
f17f1008e3 | ||
|
|
a2828f3b9a | ||
|
|
cbfdfb43e3 | ||
|
|
23e672aef9 | ||
|
|
6d9cc7e29d | ||
|
|
8a47788a09 | ||
|
|
afed5ab666 | ||
|
|
357eda8c19 | ||
|
|
f18401d183 | ||
|
|
4ea91d14f9 | ||
|
|
f57661b13f | ||
|
|
ad25c1d1b2 | ||
|
|
87af5dcee5 | ||
|
|
106871b956 | ||
|
|
4d25abcfce | ||
|
|
2ccdf3c97a | ||
|
|
89bd9c8038 | ||
|
|
88627dc837 | ||
|
|
8ca57b0705 | ||
|
|
c7db283e8c | ||
|
|
83ca3b7b8b | ||
|
|
830699d2b8 | ||
|
|
f822e658c4 | ||
|
|
8817a1afb7 | ||
|
|
693adf181e | ||
|
|
f269f13b09 | ||
|
|
9845258a25 | ||
|
|
edbed2c8d3 | ||
|
|
8e0f2d2500 | ||
|
|
e022504c26 | ||
|
|
62e4cbd052 | ||
|
|
70ae59550d | ||
|
|
f74af8fa2d | ||
|
|
82d1b57005 | ||
|
|
c32aacc1b3 | ||
|
|
523b4045bf | ||
|
|
8e4e273b7c | ||
|
|
816297e22f | ||
|
|
72889b5c36 | ||
|
|
0f0216fe79 | ||
|
|
42433d1ad4 | ||
|
|
52533fc04c | ||
|
|
bb0223877c | ||
|
|
5eb1fcddbb | ||
|
|
c646eb3939 | ||
|
|
a313c99370 | ||
|
|
0f84d9f02e | ||
|
|
900a9c6145 | ||
|
|
5b33cbe9aa | ||
|
|
114ce3b764 | ||
|
|
660d3f326f | ||
|
|
b8d51ae0de | ||
|
|
0bdda6387a | ||
|
|
4fbdbb1aa2 | ||
|
|
72ddcb4fff | ||
|
|
50ef2de5f9 | ||
|
|
55d3ee1af0 | ||
|
|
422166441e | ||
|
|
9d3f85628c | ||
|
|
669d9c3c66 | ||
|
|
dcb406d246 | ||
|
|
cadad28b0c | ||
|
|
01b0a033fd | ||
|
|
0fb66ab258 | ||
|
|
a49c21cfd1 | ||
|
|
f67a8c1f2d | ||
|
|
f4624ead42 | ||
|
|
2cd570383f | ||
|
|
920900b619 | ||
|
|
e98d934a67 | ||
|
|
31a846b9c3 | ||
|
|
5eaea28401 | ||
|
|
50ef902adb | ||
|
|
75b6a078c6 | ||
|
|
c0c93c172e | ||
|
|
ed18244070 | ||
|
|
e13063e0c6 | ||
|
|
6c38997010 | ||
|
|
0e01c0d69b | ||
|
|
caab3ea74d | ||
|
|
c543dff2e1 | ||
|
|
92badfd88c | ||
|
|
dca64e6939 | ||
|
|
a9c4d27d5e | ||
|
|
610c2f9519 | ||
|
|
05d757e7c4 | ||
|
|
31a2453882 | ||
|
|
5febd0a0d6 | ||
|
|
694f1e9b25 | ||
|
|
131bf842a9 | ||
|
|
8ec1c2e04a | ||
|
|
e94dc257a1 | ||
|
|
3bd4fc59d4 | ||
|
|
7b8463b03a | ||
|
|
00e7fc1c0d | ||
|
|
2ca20ad701 | ||
|
|
775da82072 | ||
|
|
162b392004 | ||
|
|
26bedf0523 | ||
|
|
ff3ee62509 | ||
|
|
9c2a78adf2 | ||
|
|
5a767ba3ef | ||
|
|
691d642721 | ||
|
|
7dbfc3740d | ||
|
|
b2897d7feb | ||
|
|
b18177c215 | ||
|
|
cec0a8c2e7 | ||
|
|
412de318ed | ||
|
|
92cc7a4648 | ||
|
|
96c0481e17 | ||
|
|
5dd7ddc288 | ||
|
|
ea91a82f30 | ||
|
|
8e10269b50 | ||
|
|
dae74666c5 | ||
|
|
94e31e35ba | ||
|
|
c835b4eb1a | ||
|
|
ef9e43fbd3 | ||
|
|
f083433854 | ||
|
|
9052b1c3db | ||
|
|
59578a73af | ||
|
|
c691e260cf | ||
|
|
82072c8970 | ||
|
|
d0c52ac176 | ||
|
|
6811a62568 | ||
|
|
8653d03969 | ||
|
|
90d5a04368 | ||
|
|
84e4ebef08 | ||
|
|
98603c4042 | ||
|
|
26a4ee0171 | ||
|
|
4f03a2d25c | ||
|
|
6a830a3843 | ||
|
|
3ffd049135 | ||
|
|
e6d1b38b82 | ||
|
|
f8a892faf2 | ||
|
|
54e141489a | ||
|
|
e64fd1d308 | ||
|
|
01647c3df9 | ||
|
|
cd6d7c76f6 | ||
|
|
efa71c4ac8 | ||
|
|
d4eb27a4ed | ||
|
|
eca18ba6ee | ||
|
|
31fa49feed | ||
|
|
b68aafdb72 | ||
|
|
fd09a63e48 | ||
|
|
afc50863cd | ||
|
|
fea2240c39 |
@@ -1,14 +1,36 @@
|
||||
engines:
|
||||
version: "2"
|
||||
plugins:
|
||||
rubocop:
|
||||
enabled: true
|
||||
channel: rubocop-0-48
|
||||
channel: "rubocop-0-48"
|
||||
scss-lint:
|
||||
enabled: false
|
||||
ratings:
|
||||
paths:
|
||||
- app/**
|
||||
- lib/**
|
||||
- "**.rb"
|
||||
exclude_paths:
|
||||
- spec/**/*
|
||||
- vendor/**/*
|
||||
duplication:
|
||||
enabled: true
|
||||
exclude_patterns:
|
||||
- "db/**"
|
||||
- "config/initializers/active_record_postgresql_referential_integrity_patch.rb"
|
||||
checks:
|
||||
argument-count:
|
||||
enabled: false
|
||||
complex-logic:
|
||||
enabled: true
|
||||
file-lines:
|
||||
enabled: false
|
||||
method-complexity:
|
||||
enabled: false
|
||||
method-count:
|
||||
enabled: false
|
||||
method-lines:
|
||||
enabled: false
|
||||
nested-control-flow:
|
||||
enabled: true
|
||||
return-statements:
|
||||
enabled: true
|
||||
similar-code:
|
||||
enabled: true
|
||||
identical-code:
|
||||
enabled: true
|
||||
exclude_patterns:
|
||||
- "spec/**/*"
|
||||
- "vendor/**/*"
|
||||
|
||||
42
.github/ISSUE_TEMPLATE.md
vendored
Normal file
42
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<!--- If what you want to file is not a bug, please use the [Feature
|
||||
template](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Feature-template)
|
||||
instead -->
|
||||
|
||||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
|
||||
## Description
|
||||
<!--- Provide a more detailed introduction to the issue itself, and why you consider it to be a bug -->
|
||||
|
||||
## Expected Behavior
|
||||
<!--- Tell us what should happen -->
|
||||
|
||||
## Actual Behavior
|
||||
<!--- Tell us what happens instead -->
|
||||
|
||||
## Steps to Reproduce
|
||||
<!--- Provide an unambiguous set of steps to reproduce this bug -->
|
||||
<!--- Include code to reproduce, if relevant -->
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
4.
|
||||
|
||||
## Animated Gif/Screenshot
|
||||
<!-- Provide a screenshot or brief animated gif reproducing the bug. Linux users can use
|
||||
[Peek](https://github.com/phw/peek#ubuntu) while Mac users can use [Recordit](http://recordit.co/) -->
|
||||
|
||||
## Context
|
||||
<!--- How has this bug affected you? What were you trying to accomplish? -->
|
||||
|
||||
## Severity
|
||||
<!--- Use the [Bug severity
|
||||
guideline](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Bug-severity) to assign one to this bug -->
|
||||
|
||||
## Your Environment
|
||||
<!--- Include as many relevant details about the environment you experienced the bug in -->
|
||||
* Version used:
|
||||
* Browser name and version:
|
||||
* Operating System and version (desktop or mobile):
|
||||
|
||||
## Possible Fix
|
||||
<!--- Not obligatory, but suggest a fix or reason for the bug -->
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,5 +1,7 @@
|
||||
#### What? Why?
|
||||
|
||||
Closes #[the issue number this PR is related to]
|
||||
|
||||
[Explain why is this change needed and the solution you propose. Provide
|
||||
context for others to understand it]
|
||||
|
||||
|
||||
@@ -27,6 +27,10 @@ Style/Documentation:
|
||||
Style/StringLiterals:
|
||||
Enabled: false
|
||||
|
||||
Style/HashSyntax:
|
||||
Enabled: true
|
||||
EnforcedStyle: ruby19_no_mixed_keys
|
||||
|
||||
Layout/MultilineMethodCallIndentation:
|
||||
Enabled: true
|
||||
EnforcedStyle: indented
|
||||
@@ -53,6 +57,10 @@ Lint/UselessAssignment:
|
||||
Rails/DynamicFindBy:
|
||||
Enabled: false
|
||||
|
||||
# Same as above, #find_by is not available until Rails 4
|
||||
Rails/FindBy:
|
||||
Enabled: false
|
||||
|
||||
# This should be the programmer's discretion, perhaps we should review all of
|
||||
# the uses of it an make specific exceptions though.
|
||||
Rails/SkipsModelValidations:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,9 +22,6 @@ env:
|
||||
- CI_NODE_INDEX=3
|
||||
- CI_NODE_INDEX=4 KARMA="true" GITHUB_DEPLOY="true"
|
||||
|
||||
before_install:
|
||||
- ./script/upgrade_bundler.sh
|
||||
|
||||
before_script:
|
||||
- cp config/database.travis.yml config/database.yml
|
||||
- cp config/application.yml.example config/application.yml
|
||||
@@ -43,7 +40,6 @@ before_script:
|
||||
|
||||
script:
|
||||
- 'if [ "$KARMA" = "true" ]; then bundle exec rake karma:run; else echo "Skipping karma run"; fi'
|
||||
#- "KNAPSACK_GENERATE_REPORT=true bundle exec rspec spec"
|
||||
- "bundle exec rake 'knapsack:rspec[--tag ~performance]'"
|
||||
|
||||
after_success:
|
||||
|
||||
@@ -1,36 +1,68 @@
|
||||
See this here post on raising a github issue:
|
||||
https://community.openfoodnetwork.org/t/how-to-raise-a-github-issue/912
|
||||
|
||||
# Contributing
|
||||
We love pull requests from everyone. Any contribution is valuable, but there are two issue streams that we especially love people to work on:
|
||||
|
||||
We love pull requests from everyone. Here are some instructions for
|
||||
contributing code to Open Food Network. See the [developer wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki) for more information.
|
||||
1) Our delivery backlog, is managed via a ZenHub board (ZenHub extensions are available for most major browsers). We use a Kanban-style approach, whereby devs pick issues from the top of the backlog which has been organised according to current priorities. If you have some time and are interested in working on some issues from the backlog, please make yourself known on the [#dev](https://openfoodnetwork.slack.com/messages/C2GQ45KNU) channel on Slack and we can direct you to the most appropriate issue to pick up.
|
||||
|
||||
Fork, then clone the repo:
|
||||
2) Our list of bugs and other self-contained issues that we consider to be a good starting point for new contributors, or devs who aren’t able to commit to seeing a whole feature through. These issues are marked with the `# good first issue` label.
|
||||
|
||||
git clone git@github.com:your-username/openfoodnetwork.git
|
||||
## Set up
|
||||
|
||||
Follow the instructions in README.markdown to set up your machine.
|
||||
Set up your local development environment by following the appropriate guide from the `Development environment setup` section in the [developer wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki).
|
||||
|
||||
Make sure the tests pass:
|
||||
Add an `upstream` remote that points to the main repo:
|
||||
|
||||
rspec spec
|
||||
cd ~/location-of-your-local-ofn-repo
|
||||
git remote add upstream https://github.com/openfoodfoundation/openfoodnetwork
|
||||
|
||||
Make your change. Add tests for your change. Make the tests pass:
|
||||
If you haven't already done so, fork this repo using the `Fork` button in the top-right corner of this screen. Then ensure that your fork is listed as the `origin` remote on your local machine.
|
||||
|
||||
rspec spec
|
||||
git remote set-url origin https://github.com/your-username/openfoodnetwork
|
||||
|
||||
Push to your fork and [submit a pull request][pr].
|
||||
Fetch the latest version of `master` from `upstream` (ie. the main repo):
|
||||
|
||||
[pr]: https://github.com/openfoodfoundation/openfoodnetwork/compare/
|
||||
git fetch upstream master
|
||||
|
||||
At this point you're waiting on us. We may suggest some changes or
|
||||
improvements or alternatives.
|
||||
Create a new branch on your local machine for (based on `upstream/master`):
|
||||
|
||||
To increase the chance that your pull request is swiftly accepted:
|
||||
git checkout -b branch-name-here --no-track upstream/master
|
||||
|
||||
If you want to run the whole test suite, we recommend using a free CI service to run your tests in parallel. Running the whole suite locally in series is likely to take > 40 minutes. [TravisCI][travis] and [SemaphoreCI][semaphore] both work great in our experience. Either way, make sure the tests pass on your new branch:
|
||||
|
||||
bundle exec rspec spec
|
||||
|
||||
## Making a change
|
||||
|
||||
Make your changes to the codebase. We recommend using TDD. Add a test, make changes and get the test suite back to green.
|
||||
|
||||
bundle exec rspec spec
|
||||
|
||||
Once the tests are passing you can commit your changes. See [Making a great commit][great-commit] for more tips.
|
||||
|
||||
git add .
|
||||
git commit -m "Add a concise commit message describing your change here"
|
||||
|
||||
Push your changes to a branch on your fork:
|
||||
|
||||
git push origin branch-name-here
|
||||
|
||||
## Submitting a Pull Request
|
||||
|
||||
Use the GitHub UI to submit a [new pull request][pr] against upstream/master. To increase the chances that your pull request is swiftly accepted please have a look at our guide to [[making a great pull request]].
|
||||
|
||||
TL;DR:
|
||||
* Write tests
|
||||
* Make sure the whole test suite is passing
|
||||
* Keep your PR small, with a single focus
|
||||
* Maintain a clean commit history
|
||||
* Use a style consistent with the rest of the codebase
|
||||
* Before submitting, [rebase your work][rebase] on the current master branch
|
||||
|
||||
From here, your pull request will progress through the [Review, Test, Merge & Deploy process][process].
|
||||
|
||||
[pr]: https://github.com/openfoodfoundation/openfoodnetwork/compare/
|
||||
[great-pr]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Making-a-great-pull-request
|
||||
[great-commit]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Making-a-great-commit
|
||||
[process]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/The-process-of-review%2C-test%2C-merge-and-deploy
|
||||
[rebase]: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/workflow-walkthrough
|
||||
[travis]: https://travis-ci.org/
|
||||
[semaphore]: https://semaphoreci.com/
|
||||
|
||||
34
Gemfile
34
Gemfile
@@ -1,5 +1,6 @@
|
||||
source 'https://rubygems.org'
|
||||
ruby "2.1.5"
|
||||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
|
||||
|
||||
gem 'rails', '3.2.21'
|
||||
gem 'rails-i18n', '~> 3.0.0'
|
||||
@@ -10,15 +11,15 @@ gem 'i18n-js', '~> 3.0.0'
|
||||
gem 'nokogiri', '>= 1.6.7.1'
|
||||
|
||||
gem 'pg'
|
||||
gem 'spree', github: 'openfoodfoundation/spree', branch: 'step-6a', ref: '5a76d45'
|
||||
gem 'spree', github: 'openfoodfoundation/spree', branch: 'step-6a', ref: '86bf87f1b1e1b299edc8cd10a2486e44ba0a3987'
|
||||
gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable'
|
||||
gem 'spree_auth_devise', github: 'openfoodfoundation/spree_auth_devise', branch: 'spree-upgrade-intermediate'
|
||||
|
||||
# Our branch contains two changes
|
||||
# - Pass customer email and phone number to PayPal (merged to upstream master)
|
||||
# - Change type of password from string to password to hide it in the form
|
||||
gem 'spree_paypal_express', :github => "openfoodfoundation/better_spree_paypal_express", :branch => "spree-upgrade-intermediate"
|
||||
#gem 'spree_paypal_express', :github => "spree-contrib/better_spree_paypal_express", :branch => "1-3-stable"
|
||||
gem 'spree_paypal_express', github: "openfoodfoundation/better_spree_paypal_express", branch: "spree-upgrade-intermediate"
|
||||
#gem 'spree_paypal_express', github: "spree-contrib/better_spree_paypal_express", branch: "1-3-stable"
|
||||
gem 'stripe', '~> 3.3.1'
|
||||
gem 'activemerchant', '~> 1.71.0'
|
||||
|
||||
@@ -30,7 +31,7 @@ gem 'daemons'
|
||||
|
||||
# Fix bug in simple_form preventing collection_check_boxes usage within form_for block
|
||||
# When merged, revert to upstream gem
|
||||
gem 'simple_form', :github => 'RohanM/simple_form'
|
||||
gem 'simple_form', github: 'RohanM/simple_form'
|
||||
|
||||
gem 'unicorn'
|
||||
gem 'angularjs-rails', '1.5.5'
|
||||
@@ -48,14 +49,14 @@ gem 'representative_view'
|
||||
gem 'rabl'
|
||||
gem "active_model_serializers"
|
||||
gem 'oj'
|
||||
gem 'deface', :github => 'spree/deface', :ref => '1110a13'
|
||||
gem 'deface', github: 'spree/deface', ref: '1110a13'
|
||||
gem 'paperclip'
|
||||
gem 'dalli'
|
||||
gem 'geocoder'
|
||||
gem 'gmaps4rails'
|
||||
gem 'spinjs-rails'
|
||||
gem 'rack-ssl', :require => 'rack/ssl'
|
||||
gem 'custom_error_message', :github => 'jeremydurham/custom-err-msg'
|
||||
gem 'rack-ssl', require: 'rack/ssl'
|
||||
gem 'custom_error_message', github: 'jeremydurham/custom-err-msg'
|
||||
gem 'angularjs-file-upload-rails', '~> 1.1.6'
|
||||
gem 'roadie-rails', '~> 1.0.3'
|
||||
gem 'figaro'
|
||||
@@ -101,19 +102,19 @@ gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz'
|
||||
|
||||
group :test, :development do
|
||||
# Pretty printed test output
|
||||
gem 'turn', '~> 0.8.3', :require => false
|
||||
gem 'fuubar'
|
||||
gem 'rspec-rails'
|
||||
gem 'turn', '~> 0.8.3', require: false
|
||||
gem 'fuubar', '~> 2.2.0'
|
||||
gem 'rspec-rails', ">= 3.5.2"
|
||||
gem 'shoulda-matchers'
|
||||
gem 'factory_girl_rails', :require => false
|
||||
gem 'capybara'
|
||||
gem 'database_cleaner', '0.7.1', :require => false
|
||||
gem 'factory_girl_rails', require: false
|
||||
gem 'capybara', '>= 2.15.4'
|
||||
gem 'database_cleaner', '0.7.1', require: false
|
||||
gem 'awesome_print'
|
||||
gem 'letter_opener'
|
||||
gem 'timecop'
|
||||
gem 'poltergeist'
|
||||
gem 'poltergeist', '>= 1.16.0'
|
||||
gem 'rspec-retry'
|
||||
gem 'json_spec'
|
||||
gem 'json_spec', '~> 1.1.4'
|
||||
gem 'unicorn-rails'
|
||||
gem 'atomic'
|
||||
gem 'knapsack'
|
||||
@@ -130,10 +131,11 @@ group :development do
|
||||
gem 'pry-byebug', '>= 3.4.3'
|
||||
gem 'debugger-linecache'
|
||||
gem 'guard'
|
||||
gem 'listen', '3.0.8' # 3.1.0 requires ruby 2.2
|
||||
gem 'guard-livereload'
|
||||
gem 'rack-livereload'
|
||||
gem 'guard-rails'
|
||||
gem 'guard-rspec'
|
||||
gem 'guard-rspec', '~> 4.7.3'
|
||||
gem 'parallel_tests'
|
||||
gem 'rubocop', '>= 0.49.1'
|
||||
|
||||
|
||||
158
Gemfile.lock
158
Gemfile.lock
@@ -1,5 +1,5 @@
|
||||
GIT
|
||||
remote: git://github.com/RohanM/simple_form.git
|
||||
remote: https://github.com/RohanM/simple_form.git
|
||||
revision: 45f08a213b40f3d4bda5f5398db841137587160a
|
||||
specs:
|
||||
simple_form (2.0.2)
|
||||
@@ -7,13 +7,13 @@ GIT
|
||||
activemodel (~> 3.0)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/jeremydurham/custom-err-msg.git
|
||||
remote: https://github.com/jeremydurham/custom-err-msg.git
|
||||
revision: 3a8ec9dddc7a5b0aab7c69a6060596de300c68f4
|
||||
specs:
|
||||
custom_error_message (1.1.1)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/openfoodfoundation/better_spree_paypal_express.git
|
||||
remote: https://github.com/openfoodfoundation/better_spree_paypal_express.git
|
||||
revision: 8d95f4544c682634812becaf50999fba0cd04df0
|
||||
branch: spree-upgrade-intermediate
|
||||
specs:
|
||||
@@ -22,16 +22,16 @@ GIT
|
||||
spree_core (~> 1.3.99)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/openfoodfoundation/ofn-qz.git
|
||||
remote: https://github.com/openfoodfoundation/ofn-qz.git
|
||||
revision: 024680ccea429b2e5428d7b964fa67c52add34ec
|
||||
specs:
|
||||
ofn-qz (0.1.0)
|
||||
railties (~> 3.1)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/openfoodfoundation/spree.git
|
||||
revision: 5a76d456ff70aea7aae3d25156558d71eb7febf2
|
||||
ref: 5a76d45
|
||||
remote: https://github.com/openfoodfoundation/spree.git
|
||||
revision: 86bf87f1b1e1b299edc8cd10a2486e44ba0a3987
|
||||
ref: 86bf87f1b1e1b299edc8cd10a2486e44ba0a3987
|
||||
branch: step-6a
|
||||
specs:
|
||||
spree (1.3.99)
|
||||
@@ -91,7 +91,7 @@ GIT
|
||||
spree_core (= 1.3.99)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/openfoodfoundation/spree_auth_devise.git
|
||||
remote: https://github.com/openfoodfoundation/spree_auth_devise.git
|
||||
revision: da9eecefc6fe13dedf4c6f3febec79caad839ec3
|
||||
branch: spree-upgrade-intermediate
|
||||
specs:
|
||||
@@ -103,7 +103,7 @@ GIT
|
||||
spree_frontend (~> 1.3.6)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/spree/deface.git
|
||||
remote: https://github.com/spree/deface.git
|
||||
revision: 1110a1336252109bce7f98f9182042e0bc2930ae
|
||||
ref: 1110a13
|
||||
specs:
|
||||
@@ -113,7 +113,7 @@ GIT
|
||||
rails (>= 3.1)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/spree/spree_i18n.git
|
||||
remote: https://github.com/spree/spree_i18n.git
|
||||
revision: 752eb67204e9c5a4e22b62591a8fd55fe2285e43
|
||||
branch: 1-3-stable
|
||||
specs:
|
||||
@@ -123,7 +123,7 @@ GIT
|
||||
spree_core (>= 1.1)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/willrjmarshall/foundation_rails_helper.git
|
||||
remote: https://github.com/willrjmarshall/foundation_rails_helper.git
|
||||
revision: 4d5d53fdc4b1fb71e66524d298c5c635de82cfbb
|
||||
branch: rails3
|
||||
specs:
|
||||
@@ -173,7 +173,8 @@ GEM
|
||||
acts-as-taggable-on (3.5.0)
|
||||
activerecord (>= 3.2, < 5)
|
||||
acts_as_list (0.1.9)
|
||||
addressable (2.4.0)
|
||||
addressable (2.5.2)
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
andand (1.3.3)
|
||||
angular-rails-templates (0.2.0)
|
||||
railties (>= 3.1)
|
||||
@@ -200,15 +201,13 @@ GEM
|
||||
builder (3.0.4)
|
||||
byebug (9.0.6)
|
||||
cancan (1.6.8)
|
||||
capybara (2.7.1)
|
||||
capybara (2.15.4)
|
||||
addressable
|
||||
mime-types (>= 1.16)
|
||||
mini_mime (>= 0.1.3)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
celluloid (0.15.2)
|
||||
timers (~> 1.1.0)
|
||||
chronic (0.10.2)
|
||||
chunky_png (1.3.4)
|
||||
climate_control (0.1.0)
|
||||
@@ -266,11 +265,11 @@ GEM
|
||||
warden (~> 1.2.1)
|
||||
devise-encryptable (0.1.2)
|
||||
devise (>= 2.1.0)
|
||||
diff-lcs (1.2.4)
|
||||
diff-lcs (1.3)
|
||||
diffy (3.1.0)
|
||||
em-websocket (0.5.0)
|
||||
em-websocket (0.5.1)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0.5.3)
|
||||
http_parser.rb (~> 0.6.0)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.2.3)
|
||||
excon (0.45.4)
|
||||
@@ -283,7 +282,7 @@ GEM
|
||||
faraday (0.9.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffaker (1.15.0)
|
||||
ffi (1.9.3)
|
||||
ffi (1.9.18)
|
||||
figaro (0.7.0)
|
||||
bundler (~> 1.0)
|
||||
rails (>= 3, < 5)
|
||||
@@ -404,31 +403,38 @@ GEM
|
||||
foundation-rails (5.5.0.0)
|
||||
railties (>= 3.1.0)
|
||||
sass (>= 3.2.0, < 3.4)
|
||||
fuubar (1.3.3)
|
||||
rspec (>= 2.14.0, < 3.1.0)
|
||||
fuubar (2.2.0)
|
||||
rspec-core (~> 3.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
geocoder (1.1.8)
|
||||
gmaps4rails (1.5.6)
|
||||
guard (2.2.4)
|
||||
guard (2.14.1)
|
||||
formatador (>= 0.2.4)
|
||||
listen (~> 2.1)
|
||||
listen (>= 2.7, < 4.0)
|
||||
lumberjack (~> 1.0)
|
||||
nenv (~> 0.1)
|
||||
notiffany (~> 0.0)
|
||||
pry (>= 0.9.12)
|
||||
shellany (~> 0.0)
|
||||
thor (>= 0.18.1)
|
||||
guard-livereload (2.0.1)
|
||||
guard-compat (1.2.1)
|
||||
guard-livereload (2.5.2)
|
||||
em-websocket (~> 0.5)
|
||||
guard (~> 2.0)
|
||||
guard (~> 2.8)
|
||||
guard-compat (~> 1.0)
|
||||
multi_json (~> 1.8)
|
||||
guard-rails (0.4.7)
|
||||
guard (>= 0.2.2)
|
||||
guard-rspec (4.0.4)
|
||||
guard (>= 2.1.1)
|
||||
rspec (~> 2.14)
|
||||
guard-rails (0.7.2)
|
||||
guard (~> 2.11)
|
||||
guard-compat (~> 1.0)
|
||||
guard-rspec (4.7.3)
|
||||
guard (~> 2.1)
|
||||
guard-compat (~> 1.1)
|
||||
rspec (>= 2.99.0, < 4.0)
|
||||
haml (4.0.4)
|
||||
tilt
|
||||
highline (1.6.15)
|
||||
hike (1.2.3)
|
||||
http_parser.rb (0.5.3)
|
||||
http_parser.rb (0.6.0)
|
||||
httparty (0.9.0)
|
||||
multi_json (~> 1.0)
|
||||
multi_xml
|
||||
@@ -446,9 +452,9 @@ GEM
|
||||
railties (>= 3.0, < 5.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
json (1.8.6)
|
||||
json_spec (1.1.1)
|
||||
json_spec (1.1.5)
|
||||
multi_json (~> 1.0)
|
||||
rspec (~> 2.0)
|
||||
rspec (>= 2.0, < 4.0)
|
||||
jwt (1.5.4)
|
||||
kaminari (0.13.0)
|
||||
actionpack (>= 3.0.0)
|
||||
@@ -463,16 +469,16 @@ GEM
|
||||
letter_opener (1.0.0)
|
||||
launchy (>= 2.0.4)
|
||||
libv8 (3.16.14.11)
|
||||
listen (2.2.0)
|
||||
celluloid (>= 0.15.2)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
rb-inotify (>= 0.9)
|
||||
lumberjack (1.0.4)
|
||||
listen (3.0.8)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
lumberjack (1.0.12)
|
||||
mail (2.5.4)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
method_source (0.9.0)
|
||||
mime-types (1.25.1)
|
||||
mini_mime (0.1.4)
|
||||
mini_portile2 (2.1.0)
|
||||
momentjs-rails (2.5.1)
|
||||
railties (>= 3.1)
|
||||
@@ -481,9 +487,13 @@ GEM
|
||||
multi_json (1.12.1)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
nenv (0.3.0)
|
||||
newrelic_rpm (3.12.0.288)
|
||||
nokogiri (1.6.8.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
notiffany (0.1.1)
|
||||
nenv (~> 0.1)
|
||||
shellany (~> 0.0)
|
||||
oauth2 (1.2.0)
|
||||
faraday (>= 0.8, < 0.10)
|
||||
jwt (~> 1.0)
|
||||
@@ -511,28 +521,28 @@ GEM
|
||||
paypal-sdk-merchant (1.106.1)
|
||||
paypal-sdk-core (~> 0.2.3)
|
||||
pg (0.13.2)
|
||||
poltergeist (1.9.0)
|
||||
poltergeist (1.16.0)
|
||||
capybara (~> 2.1)
|
||||
cliver (~> 0.3.1)
|
||||
multi_json (~> 1.0)
|
||||
websocket-driver (>= 0.2.0)
|
||||
polyamorous (0.5.0)
|
||||
activerecord (~> 3.0)
|
||||
polyglot (0.3.5)
|
||||
powerpack (0.1.1)
|
||||
pry (0.11.1)
|
||||
pry (0.11.2)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
pry-byebug (3.4.3)
|
||||
byebug (>= 9.0, < 9.1)
|
||||
pry (~> 0.10)
|
||||
public_suffix (3.0.0)
|
||||
rabl (0.7.2)
|
||||
activesupport (>= 2.3.14)
|
||||
multi_json (~> 1.0)
|
||||
rack (1.4.7)
|
||||
rack-cache (1.7.0)
|
||||
rack (>= 0.4)
|
||||
rack-livereload (0.3.15)
|
||||
rack-livereload (0.3.16)
|
||||
rack
|
||||
rack-ssl (1.3.4)
|
||||
rack
|
||||
@@ -564,9 +574,9 @@ GEM
|
||||
actionpack (~> 3.0)
|
||||
activerecord (~> 3.0)
|
||||
polyamorous (~> 0.5.0)
|
||||
rb-fsevent (0.9.3)
|
||||
rb-inotify (0.9.2)
|
||||
ffi (>= 0.5.0)
|
||||
rb-fsevent (0.10.2)
|
||||
rb-inotify (0.9.10)
|
||||
ffi (>= 0.5.0, < 2)
|
||||
rdoc (3.12.2)
|
||||
json (~> 1.4)
|
||||
redcarpet (3.2.3)
|
||||
@@ -588,24 +598,29 @@ GEM
|
||||
roo (2.7.1)
|
||||
nokogiri (~> 1)
|
||||
rubyzip (~> 1.1, < 2.0.0)
|
||||
rspec (2.14.1)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rspec-core (2.14.4)
|
||||
rspec-expectations (2.14.0)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.14.2)
|
||||
rspec-rails (2.14.2)
|
||||
rspec (3.7.0)
|
||||
rspec-core (~> 3.7.0)
|
||||
rspec-expectations (~> 3.7.0)
|
||||
rspec-mocks (~> 3.7.0)
|
||||
rspec-core (3.7.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-expectations (3.7.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-mocks (3.7.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-rails (3.7.1)
|
||||
actionpack (>= 3.0)
|
||||
activemodel (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rspec-core (~> 3.7.0)
|
||||
rspec-expectations (~> 3.7.0)
|
||||
rspec-mocks (~> 3.7.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-retry (0.4.2)
|
||||
rspec-core
|
||||
rspec-support (3.7.0)
|
||||
rubocop (0.49.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.3.3.1, < 3.0)
|
||||
@@ -623,6 +638,7 @@ GEM
|
||||
tilt (~> 1.3)
|
||||
select2-rails (3.5.10)
|
||||
thor (~> 0.14)
|
||||
shellany (0.0.1)
|
||||
shoulda-matchers (1.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
spinjs-rails (1.3)
|
||||
@@ -639,10 +655,9 @@ GEM
|
||||
therubyracer (0.12.0)
|
||||
libv8 (~> 3.16.14.0)
|
||||
ref
|
||||
thor (0.19.4)
|
||||
thor (0.20.0)
|
||||
tilt (1.4.1)
|
||||
timecop (0.8.1)
|
||||
timers (1.1.0)
|
||||
treetop (1.4.15)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
@@ -669,12 +684,12 @@ GEM
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
warden (1.2.6)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
webmock (1.8.11)
|
||||
addressable (>= 2.2.7)
|
||||
crack (>= 0.1.7)
|
||||
websocket-driver (0.6.3)
|
||||
websocket-driver (0.7.0)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.2)
|
||||
whenever (0.9.2)
|
||||
@@ -683,7 +698,7 @@ GEM
|
||||
wicked_pdf (1.1.0)
|
||||
wkhtmltopdf-binary (0.12.3.1)
|
||||
xml-simple (1.1.5)
|
||||
xpath (2.0.0)
|
||||
xpath (2.1.0)
|
||||
nokogiri (~> 1.3)
|
||||
|
||||
PLATFORMS
|
||||
@@ -703,7 +718,7 @@ DEPENDENCIES
|
||||
blockenspiel
|
||||
bugsnag
|
||||
byebug (~> 9.0.0)
|
||||
capybara
|
||||
capybara (>= 2.15.4)
|
||||
coffee-rails (~> 3.2.1)
|
||||
compass-rails
|
||||
css_splitter
|
||||
@@ -723,23 +738,24 @@ DEPENDENCIES
|
||||
foundation-icons-sass-rails
|
||||
foundation-rails
|
||||
foundation_rails_helper!
|
||||
fuubar
|
||||
fuubar (~> 2.2.0)
|
||||
geocoder
|
||||
gmaps4rails
|
||||
guard
|
||||
guard-livereload
|
||||
guard-rails
|
||||
guard-rspec
|
||||
guard-rspec (~> 4.7.3)
|
||||
haml
|
||||
i18n (~> 0.6.11)
|
||||
i18n-js (~> 3.0.0)
|
||||
immigrant
|
||||
jquery-migrate-rails
|
||||
jquery-rails
|
||||
json_spec
|
||||
json_spec (~> 1.1.4)
|
||||
jwt (~> 1.5)
|
||||
knapsack
|
||||
letter_opener
|
||||
listen (= 3.0.8)
|
||||
momentjs-rails
|
||||
newrelic_rpm
|
||||
nokogiri (>= 1.6.7.1)
|
||||
@@ -750,7 +766,7 @@ DEPENDENCIES
|
||||
paperclip
|
||||
parallel_tests
|
||||
pg
|
||||
poltergeist
|
||||
poltergeist (>= 1.16.0)
|
||||
pry-byebug (>= 3.4.3)
|
||||
rabl
|
||||
rack-livereload
|
||||
@@ -761,7 +777,7 @@ DEPENDENCIES
|
||||
representative_view
|
||||
roadie-rails (~> 1.0.3)
|
||||
roo (~> 2.7.0)
|
||||
rspec-rails
|
||||
rspec-rails (>= 3.5.2)
|
||||
rspec-retry
|
||||
rubocop (>= 0.49.1)
|
||||
sass (~> 3.3)
|
||||
@@ -791,4 +807,4 @@ RUBY VERSION
|
||||
ruby 2.1.5p273
|
||||
|
||||
BUNDLED WITH
|
||||
1.15.4
|
||||
1.16.0
|
||||
|
||||
36
README.md
36
README.md
@@ -45,41 +45,15 @@ You can download the source with the command:
|
||||
|
||||
### Get it running
|
||||
|
||||
For those new to Rails, the following tutorial will help get you up to speed with configuring a Rails environment: http://guides.rubyonrails.org/getting_started.html .
|
||||
For those new to Rails, the following tutorial will help get you up to speed with configuring a [Rails environment](http://guides.rubyonrails.org/getting_started.html).
|
||||
|
||||
First, check your dependencies: Ensure that you have Ruby 2.1.5 installed:
|
||||
When ready, run `script/setup`. If the script succeeds you're ready to start developing. If not, take a look at the output as it should be informative enough to help you troubleshoot.
|
||||
|
||||
ruby --version
|
||||
If you run into any other issues getting your local environment up and running please consult [the wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki).
|
||||
|
||||
Install the project's gem dependencies:
|
||||
If still you get stuck do not hesitate to open an issue reporting the full output of the script.
|
||||
|
||||
cd openfoodnetwork
|
||||
./script/upgrade_bundler.sh
|
||||
bundle install
|
||||
|
||||
Configure the site:
|
||||
|
||||
cp config/application.yml.example config/application.yml
|
||||
edit config/application.yml
|
||||
|
||||
Create a PostgreSQL user:
|
||||
|
||||
* Login as your system postrgresql priviledged user: `sudo -i -u postgres` (this may vary on your OS). Now your prompt looks like: `[postgres@your_host ~]$`
|
||||
* Create the `ofn` database superuser and give it the password `f00d`:
|
||||
|
||||
```
|
||||
createuser -s -P ofn
|
||||
```
|
||||
|
||||
Create the development and test databases, using the settings specified in `config/database.yml`, and populate them with a schema and seed data:
|
||||
```
|
||||
bundle exec rake db:setup
|
||||
```
|
||||
Load some default data for your environment:
|
||||
```
|
||||
bundle exec rake openfoodnetwork:dev:load_sample_data
|
||||
```
|
||||
At long last, your dreams of spinning up a development server can be realised:
|
||||
Now, your dreams of spinning up a development server can be realised:
|
||||
```
|
||||
bundle exec rails server
|
||||
```
|
||||
|
||||
@@ -49,6 +49,14 @@
|
||||
//= require textAngular.min.js
|
||||
//= require i18n/translations
|
||||
//= require darkswarm/i18n.translate.js
|
||||
|
||||
//
|
||||
//= require moment
|
||||
//= require moment/en-gb.js
|
||||
//= require moment/es.js
|
||||
//= require moment/fr.js
|
||||
//= require moment/it.js
|
||||
//= require moment/nb.js
|
||||
//= require moment/pt-br.js
|
||||
//= require moment/sv.js
|
||||
|
||||
//= require_tree .
|
||||
|
||||
@@ -32,7 +32,6 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
$scope.filteredProducts = []
|
||||
$scope.currentFilters = []
|
||||
$scope.limit = 15
|
||||
$scope.productsWithUnsavedVariants = []
|
||||
$scope.query = ""
|
||||
$scope.DisplayProperties = DisplayProperties
|
||||
|
||||
@@ -114,7 +113,6 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
display_name: null
|
||||
on_hand: null
|
||||
price: null
|
||||
$scope.productsWithUnsavedVariants.push product
|
||||
DisplayProperties.setShowVariants product.id, true
|
||||
|
||||
|
||||
@@ -196,7 +194,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
filters: $scope.currentFilters
|
||||
).success((data) ->
|
||||
DirtyProducts.clear()
|
||||
BulkProducts.updateVariantLists(data.products, $scope.productsWithUnsavedVariants)
|
||||
BulkProducts.updateVariantLists(data.products || [])
|
||||
$timeout -> $scope.displaySuccess()
|
||||
).error (data, status) ->
|
||||
if status == 400 && data.errors? && data.errors.length > 0
|
||||
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.dropdown", ['templates'])
|
||||
angular.module("admin.dropdown", ['admin.utils'])
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
angular.module("admin.enterpriseRoles", [])
|
||||
@@ -4,10 +4,8 @@ angular.module("admin.enterprises")
|
||||
$scope.PaymentMethods = EnterprisePaymentMethods.paymentMethods
|
||||
$scope.ShippingMethods = EnterpriseShippingMethods.shippingMethods
|
||||
$scope.navClear = NavigationCheck.clear
|
||||
$scope.pristineEmail = $scope.Enterprise.email
|
||||
$scope.menu = SideMenu
|
||||
$scope.newManager = { id: '', email: (t('add_manager')) }
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.$watch 'enterprise_form.$dirty', (newValue) ->
|
||||
@@ -36,6 +34,8 @@ angular.module("admin.enterprises")
|
||||
|
||||
$scope.removeManager = (manager) ->
|
||||
if manager.id?
|
||||
if manager.id == $scope.Enterprise.owner.id or manager.id == parseInt($scope.receivesNotifications)
|
||||
return
|
||||
for i, user of $scope.Enterprise.users when user.id == manager.id
|
||||
$scope.Enterprise.users.splice i, 1
|
||||
if $scope.enterprise_form?
|
||||
@@ -46,6 +46,7 @@ angular.module("admin.enterprises")
|
||||
manager =
|
||||
id: manager.id
|
||||
email: manager.email
|
||||
confirmed: manager.confirmed
|
||||
if (user for user in $scope.Enterprise.users when user.id == manager.id).length == 0
|
||||
$scope.Enterprise.users.push manager
|
||||
else
|
||||
|
||||
@@ -16,9 +16,9 @@ angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher,
|
||||
@unpackProduct newProduct
|
||||
@insertProductAfter(product, newProduct)
|
||||
|
||||
updateVariantLists: (serverProducts, productsWithUnsavedVariants) ->
|
||||
for product in productsWithUnsavedVariants
|
||||
server_product = @findProductInList(product.id, serverProducts)
|
||||
updateVariantLists: (serverProducts) ->
|
||||
for server_product in serverProducts
|
||||
product = @findProductInList(server_product.id, @products)
|
||||
product.variants = server_product.variants
|
||||
@loadVariantUnitValues product
|
||||
|
||||
|
||||
@@ -23,7 +23,16 @@
|
||||
#
|
||||
#= require angular-backstretch.js
|
||||
#= require angular-flash.min.js
|
||||
#
|
||||
#= require moment
|
||||
#= require moment/en-gb.js
|
||||
#= require moment/es.js
|
||||
#= require moment/fr.js
|
||||
#= require moment/it.js
|
||||
#= require moment/nb.js
|
||||
#= require moment/pt-br.js
|
||||
#= require moment/sv.js
|
||||
#
|
||||
#= require modernizr
|
||||
#
|
||||
#= require foundation
|
||||
|
||||
@@ -10,4 +10,11 @@ Darkswarm.controller "LoginCtrl", ($scope, $http, $window, AuthenticationService
|
||||
$window.location.href = $window.location.origin + $window.location.pathname # Strips out hash fragments
|
||||
.error (data) ->
|
||||
Loading.clear()
|
||||
$scope.errors = data.message
|
||||
$scope.errors = data.message || data.error
|
||||
$scope.user_unconfirmed = (data.error == t('devise.failure.unconfirmed'))
|
||||
|
||||
$scope.resend_confirmation = ->
|
||||
$http.post("/user/spree_user/confirmation", {spree_user: $scope.spree_user}).success (data)->
|
||||
$scope.messages = t('devise.confirmations.send_instructions')
|
||||
.error (data) ->
|
||||
$scope.errors = t('devise.confirmations.failed_to_send')
|
||||
@@ -9,9 +9,7 @@ Darkswarm.controller "SignupCtrl", ($scope, $http, $window, $location, Redirecti
|
||||
|
||||
$scope.submit = ->
|
||||
$http.post("/user/spree_user", {spree_user: $scope.spree_user}).success (data)->
|
||||
if Redirections.after_login
|
||||
$window.location.href = $window.location.origin + Redirections.after_login
|
||||
else
|
||||
$window.location.href = $window.location.origin + $window.location.pathname # Strips out hash fragments
|
||||
$scope.errors = {email: null, password: null}
|
||||
$scope.messages = t('devise.user_registrations.spree_user.signed_up_but_unconfirmed')
|
||||
.error (data) ->
|
||||
$scope.errors = data
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# Old aliases before i18n-js was introduced.
|
||||
# TODO - delete it after everything is moved to i18n-js
|
||||
|
||||
# Declares the translation function t.
|
||||
# You can use translate('login') or t('login') in Javascript.
|
||||
window.translate = (key, options = {}) ->
|
||||
|
||||
@@ -2,7 +2,6 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
new class EnterpriseRegistrationService
|
||||
enterprise:
|
||||
user_ids: [CurrentUser.id]
|
||||
email: CurrentUser.email
|
||||
email_address: CurrentUser.email
|
||||
address: {}
|
||||
country: availableCountries[0]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%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()'}}
|
||||
.row
|
||||
= t('admin.customers.index.required_fileds')
|
||||
{{ 'admin.customers.index.required_fileds' | t }}
|
||||
(
|
||||
%span.required *
|
||||
)
|
||||
@@ -11,62 +11,62 @@
|
||||
%table.no-borders
|
||||
%tr
|
||||
%td{style: 'width: 30%'}
|
||||
= t('spree.firstname')
|
||||
{{ 'spree.firstname' | t }}
|
||||
%span.required *
|
||||
%td
|
||||
%input{ type: 'text', name: 'firstname', required: true, ng: { model: 'address.firstname'} }
|
||||
%tr
|
||||
%td
|
||||
= t('spree.lastname')
|
||||
{{ 'spree.lastname' | t }}
|
||||
%span.required *
|
||||
%td
|
||||
%input{ type: 'text', name: 'lastname', required: true, ng: { model: 'address.lastname'} }
|
||||
%tr
|
||||
%td
|
||||
= t('spree.street_address')
|
||||
{{ 'spree.street_address' | t }}
|
||||
%span.required *
|
||||
%td
|
||||
%input{ type: 'text', name: 'address1', required: true, ng: { model: 'address.address1'} }
|
||||
%tr
|
||||
%td
|
||||
= t('spree.street_address_1')
|
||||
{{ 'spree.street_address_1' | t }}
|
||||
%td
|
||||
%input{ type: 'text', name: 'address2', ng: { model: 'address.address2'} }
|
||||
%tr
|
||||
%td
|
||||
= t('spree.city')
|
||||
{{ 'spree.city' | t }}
|
||||
%span.required *
|
||||
%td
|
||||
%input{ type: 'text', name: 'city', required: true, ng: { model: 'address.city'} }
|
||||
%tr
|
||||
%td
|
||||
= t('spree.zipcode')
|
||||
{{ 'spree.zipcode' | t }}
|
||||
%span.required *
|
||||
%td
|
||||
%input{ type: 'text', name: 'zipcode', required: true, ng: { model: 'address.zipcode'} }
|
||||
%tr
|
||||
%td
|
||||
= t('spree.country')
|
||||
{{ 'spree.country' | t }}
|
||||
%span.required *
|
||||
%td
|
||||
%select{ name: 'country', required: true, ng: { model: 'address.country_id' } }
|
||||
%option{value: ''}
|
||||
= t('admin.customers.index.select_country')
|
||||
{{ 'admin.customers.index.select_country' | t }}
|
||||
%option{ ng: { repeat: 'country in availableCountries' }, value: '{{country.id}}' }
|
||||
{{country.name}}
|
||||
%tr
|
||||
%td
|
||||
= t('spree.state')
|
||||
{{ 'spree.state' | t }}
|
||||
%span.required *
|
||||
%td
|
||||
%select{ name: 'state', required: true, ng: { model: 'address.state_id' } }
|
||||
%option{value: ''}
|
||||
= t('admin.customers.index.select_state')
|
||||
{{ 'admin.customers.index.select_state' | t }}
|
||||
%option{ ng: { repeat: 'state in states' }, value: '{{state.id}}' }
|
||||
{{state.name}}
|
||||
%tr
|
||||
%td
|
||||
= t('spree.phone')
|
||||
{{ 'spree.phone' | t }}
|
||||
%span.required *
|
||||
%td
|
||||
%input{ type: 'text', name: 'phone', required: true, ng: { model: 'address.phone'} }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.ofn-drop-down
|
||||
%span
|
||||
%i.icon-check
|
||||
= t('admin.actions')
|
||||
{{ 'admin.actions' | t }}
|
||||
%i{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
%div.menu{ 'ng-show' => "expanded" }
|
||||
%a.menu_item{ 'ng-repeat' => "link in links", href: '{{link.url}}', target: "{{link.target || '_self'}}", data: { method: "{{ link.method || 'get' }}", confirm: "{{link.confirm}}" } }
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
#tag-rule-help
|
||||
.margin-bottom-30.text-center
|
||||
.text-big
|
||||
= t('js.admin.modals.tag_rule_help.title')
|
||||
{{ 'js.admin.modals.tag_rule_help.title' | t }}
|
||||
|
||||
.margin-bottom-30
|
||||
.text-normal= t('js.admin.modals.tag_rule_help.overview')
|
||||
%p= t('js.admin.modals.tag_rule_help.overview_text')
|
||||
.text-normal
|
||||
{{ 'js.admin.modals.tag_rule_help.overview' | t }}
|
||||
%p
|
||||
{{ 'js.admin.modals.tag_rule_help.overview_text' | t }}
|
||||
|
||||
.margin-bottom-30
|
||||
.text-normal= t('js.admin.modals.tag_rule_help.by_default_rules')
|
||||
%p= t('js.admin.modals.tag_rule_help.by_default_rules_text')
|
||||
.text-normal
|
||||
{{ 'js.admin.modals.tag_rule_help.by_default_rules' | t }}
|
||||
%p
|
||||
{{ 'js.admin.modals.tag_rule_help.by_default_rules_text' | t }}
|
||||
|
||||
.margin-bottom-30
|
||||
.text-normal= t('js.admin.modals.tag_rule_help.customer_tagged_rules')
|
||||
%p= t('js.admin.modals.tag_rule_help.customer_tagged_rules_text')
|
||||
.text-normal
|
||||
{{ 'js.admin.modals.tag_rule_help.customer_tagged_rules' | t }}
|
||||
%p
|
||||
{{ 'js.admin.modals.tag_rule_help.customer_tagged_rules_text' | t }}
|
||||
|
||||
.text-center
|
||||
%input.button.red.icon-plus{ type: 'button', value: t('js.admin.modals.got_it'), ng: { click: 'close()' } }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#new-customer-dialog
|
||||
.text-normal.margin-bottom-30.text-center
|
||||
= t('admin.customers.index.add_a_new_customer_for', shop_name: "{{ CurrentShop.shop.name }}:")
|
||||
{{ 'admin.customers.index.add_a_new_customer_for' | t:{ shop_name: CurrentShop.shop.name } }}
|
||||
|
||||
%form{ name: 'new_customer_form', novalidate: true, ng: { submit: "addCustomer()" }}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
%input.fullwidth{ type: 'email', name: 'email', required: true, placeholder: t('admin.customers.index.customer_placeholder'), 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)" } }
|
||||
= t('admin.customers.index.valid_email_error')
|
||||
{{ 'admin.customers.index.valid_email_error' | t }}
|
||||
.error{ ng: { repeat: "error in errors", bind: "error" } }
|
||||
|
||||
.text-center
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#new-tag-rule-dialog
|
||||
.text-normal.margin-bottom-30.text-center
|
||||
= t('js.admin.new_tag_rule_dialog.select_rule_type')
|
||||
{{ 'js.admin.new_tag_rule_dialog.select_rule_type' | t }}
|
||||
|
||||
.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' }
|
||||
|
||||
@@ -2,128 +2,162 @@
|
||||
.alpha.eight.columns
|
||||
%div{ ng: { if: "!enterprise.is_primary_producer", switch: "enterprise.sells" } }
|
||||
.info{ ng: { switch: { when: "none" } } }
|
||||
%h3= t('js.admin.panels.enterprise_package.hub_profile')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.hub_profile' | t }}
|
||||
|
||||
%p
|
||||
%strong= t('js.admin.panels.enterprise_package.hub_profile_cost')
|
||||
%strong
|
||||
{{ 'js.admin.panels.enterprise_package.hub_profile_cost' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.hub_profile_text1')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.hub_profile_text1' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.hub_profile_text2')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.hub_profile_text2' | t }}
|
||||
|
||||
.info{ ng: { switch: { when: "any" } } }
|
||||
%h3= t('js.admin.panels.enterprise_package.hub_shop')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.hub_shop' | t }}
|
||||
|
||||
%p
|
||||
%strong
|
||||
%monthly-pricing-description{ joiner: "comma" }
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.hub_shop_text1')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.hub_shop_text1' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.hub_shop_text2')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.hub_shop_text2' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.hub_shop_text3')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.hub_shop_text3' | t }}
|
||||
|
||||
.info{ ng: { switch: { default: true } } }
|
||||
%h3
|
||||
= t('js.admin.panels.enterprise_package.choose_package')
|
||||
{{ 'js.admin.panels.enterprise_package.choose_package' | t }}
|
||||
%i.icon-arrow-right
|
||||
|
||||
%p
|
||||
%strong= t('js.admin.panels.enterprise_package.choose_package_text1')
|
||||
%strong
|
||||
{{ 'js.admin.panels.enterprise_package.choose_package_text1' | t }}
|
||||
|
||||
%p
|
||||
= t('js.admin.panels.enterprise_package.choose_package_text2')
|
||||
{{ 'js.admin.panels.enterprise_package.choose_package_text2' | t }}
|
||||
|
||||
%div{ ng: { if: "enterprise.is_primary_producer", switch: "enterprise.sells" } }
|
||||
.info{ ng: { switch: { when: "none" } } }
|
||||
%h3= t('js.admin.panels.enterprise_package.profile_only')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.profile_only' | t }}
|
||||
|
||||
%p
|
||||
%strong= t('js.admin.panels.enterprise_package.profile_only_cost')
|
||||
%strong
|
||||
{{ 'js.admin.panels.enterprise_package.profile_only_cost' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.profile_only_text1')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.profile_only_text1' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.profile_only_text2')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.profile_only_text2' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.profile_only_text3')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.profile_only_text3' | t }}
|
||||
|
||||
.info{ ng: { switch: { when: "own" } } }
|
||||
%h3= t('js.admin.panels.enterprise_package.producer_shop')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.producer_shop' | t }}
|
||||
|
||||
%p
|
||||
%strong
|
||||
%monthly-pricing-description{ joiner: "comma" }
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.producer_shop_text1')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.producer_shop_text1' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.producer_shop_text2')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.producer_shop_text2' | t }}
|
||||
|
||||
.info{ ng: { switch: { when: "any" } } }
|
||||
%h3= t('js.admin.panels.enterprise_package.producer_hub')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.producer_hub' | t }}
|
||||
|
||||
%p
|
||||
%strong
|
||||
%monthly-pricing-description{ joiner: "comma" }
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.producer_hub_text1')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.producer_hub_text1' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.producer_hub_text2')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.producer_hub_text2' | t }}
|
||||
|
||||
%p= t('js.admin.panels.enterprise_package.producer_hub_text3')
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.producer_hub_text3' | t }}
|
||||
|
||||
.info{ ng: { switch: { default: true } } }
|
||||
%h3
|
||||
= t('js.admin.panels.enterprise_package.choose_package')
|
||||
{{ 'js.admin.panels.enterprise_package.choose_package' | t }}
|
||||
%i.icon-arrow-right
|
||||
|
||||
%p
|
||||
%strong= t('js.admin.panels.enterprise_package.choose_package_text1')
|
||||
%strong
|
||||
{{ 'js.admin.panels.enterprise_package.choose_package_text1' | t }}
|
||||
|
||||
%p
|
||||
= t('js.admin.panels.enterprise_package.choose_package_text2')
|
||||
{{ '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}" } }
|
||||
.top
|
||||
%h3= t('js.admin.panels.enterprise_package.profile_only')
|
||||
%p= t('js.admin.panels.enterprise_package.get_listing')
|
||||
.bottom= t('js.admin.panels.enterprise_package.always_free')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.profile_only' | t }}
|
||||
%p
|
||||
{{ '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}" } }
|
||||
.top
|
||||
%h3= t('js.admin.panels.enterprise_package.hub_shop')
|
||||
%p= t('js.admin.panels.enterprise_package.sell_produce_others')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.hub_shop' | t }}
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.sell_produce_others' | t }}
|
||||
.bottom
|
||||
%monthly-pricing-description{ joiner: "newline" }
|
||||
|
||||
%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}" } }
|
||||
.top
|
||||
%h3= t('js.admin.panels.enterprise_package.profile_only')
|
||||
%p= t('js.admin.panels.enterprise_package.get_listing')
|
||||
.bottom= t('js.admin.panels.enterprise_package.always_free')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.profile_only' | t }}
|
||||
%p
|
||||
{{ '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}" } }
|
||||
.top
|
||||
%h3= t('js.admin.panels.enterprise_package.producer_shop')
|
||||
%p= t('js.admin.panels.enterprise_package.sell_own_produce')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.producer_shop' | t }}
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.sell_own_produce' | t }}
|
||||
.bottom
|
||||
%monthly-pricing-description{ joiner: "newline" }
|
||||
|
||||
%a.button.selector.producer-hub{ ng: { click: "enterprise.owned && (enterprise.sells='any')", class: "{selected: enterprise.sells=='any', disabled: !enterprise.owned}" } }
|
||||
.top
|
||||
%h3= t('js.admin.panels.enterprise_package.producer_hub')
|
||||
%p= t('js.admin.panels.enterprise_package.sell_both')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_package.producer_hub' | t }}
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_package.sell_both' | t }}
|
||||
.bottom
|
||||
%monthly-pricing-description{ joiner: "newline" }
|
||||
|
||||
%a.button.update.fullwidth{ ng: { show: "enterprise.owned", class: "{disabled: saved() && !saving, saving: saving}", click: "save()" } }
|
||||
%span{ ng: {hide: "saved() || saving" } }
|
||||
= t('js.admin.panels.save')
|
||||
{{ 'js.admin.panels.save' | t }}
|
||||
%i.icon-save
|
||||
%span{ ng: {show: "saved() && !saving" } }
|
||||
= t('js.admin.panels.saved')
|
||||
{{ 'js.admin.panels.saved' | t }}
|
||||
%i.icon-ok-sign
|
||||
%span{ ng: {show: "saving" } }
|
||||
= t('js.admin.panels.saving')
|
||||
{{ 'js.admin.panels.saving' | t }}
|
||||
%i.icon-refresh
|
||||
|
||||
@@ -1,37 +1,47 @@
|
||||
.row.enterprise_producer_panel{ ng: { controller: 'indexProducerPanelCtrl' } }
|
||||
.alpha.eight.columns
|
||||
.info{ ng: { show: "enterprise.is_primary_producer==true" } }
|
||||
%h3= t('js.admin.panels.enterprise_producer.producer')
|
||||
%p= t('js.admin.panels.enterprise_producer.producer_text1')
|
||||
|
||||
%p= t('js.admin.panels.enterprise_producer.producer_text2')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_producer.producer' | t }}
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_producer.producer_text1' | t }}
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_producer.producer_text2' | t }}
|
||||
|
||||
.info{ ng: { show: "enterprise.is_primary_producer==false" } }
|
||||
%h3= t('js.admin.panels.enterprise_producer.non_producer')
|
||||
%p= t('js.admin.panels.enterprise_producer.non_producer_text1')
|
||||
|
||||
%p= t('js.admin.panels.enterprise_producer.non_producer_text2')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_producer.non_producer' | t }}
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_producer.non_producer_text1' | t }}
|
||||
%p
|
||||
{{ '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}" } }
|
||||
.top
|
||||
%h3= t('js.admin.panels.enterprise_producer.producer')
|
||||
%p= t('js.admin.panels.enterprise_producer.producer_desc')
|
||||
.bottom= t('js.admin.panels.enterprise_producer.producer_example')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_producer.producer' | t }}
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_producer.producer_desc' | t }}
|
||||
.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}" } }
|
||||
.top
|
||||
%h3= t('js.admin.panels.enterprise_producer.non_producer')
|
||||
%p= t('js.admin.panels.enterprise_producer.non_producer_desc')
|
||||
.bottom= t('js.admin.panels.enterprise_producer.non_producer_example')
|
||||
%h3
|
||||
{{ 'js.admin.panels.enterprise_producer.non_producer' | t }}
|
||||
%p
|
||||
{{ 'js.admin.panels.enterprise_producer.non_producer_desc' | t }}
|
||||
.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" } }
|
||||
= t('js.admin.panels.save')
|
||||
{{ 'js.admin.panels.save' | t }}
|
||||
%i.icon-save
|
||||
%span{ ng: {show: "saved() && !saving" } }
|
||||
= t('js.admin.panels.saved')
|
||||
{{ 'js.admin.panels.saved' | t }}
|
||||
%i.icon-ok-sign
|
||||
%span{ ng: {show: "saving" } }
|
||||
= t('js.admin.panels.saving')
|
||||
{{ 'js.admin.panels.saving' | t }}
|
||||
%i.icon-refresh
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
.alpha.omega.sixteen.columns
|
||||
%h4.status-ok.text-center{ ng: { show: "issues.length == 0 && warnings.length == 0" } }
|
||||
%i.icon-ok-sign
|
||||
= t('js.admin.panels.enterprise_status.status_title', name: '{{ object.name }}')
|
||||
{{ 'js.admin.panels.enterprise_status.status_title' | t:{ name: object.name } }}
|
||||
|
||||
%table{ ng: { show: "issues.length > 0 || warnings.length > 0" } }
|
||||
%thead
|
||||
%th.severity
|
||||
= t('js.admin.panels.enterprise_status.severity')
|
||||
{{ 'js.admin.panels.enterprise_status.severity' | t }}
|
||||
%th.description
|
||||
= t('js.admin.panels.enterprise_status.description')
|
||||
{{ 'js.admin.panels.enterprise_status.description' | t }}
|
||||
%th.resolve
|
||||
= t('js.admin.panels.enterprise_status.resolve')
|
||||
{{ 'js.admin.panels.enterprise_status.resolve' | t }}
|
||||
%tr{ ng: { repeat: "issue in issues"} }
|
||||
%td.severity
|
||||
%i.icon-warning-sign.issue
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
'ng-model' => 'exchange.select_all_variants',
|
||||
'ng-change' => 'setExchangeVariants(exchange, incomingExchangeVariantsFor(exchange.enterprise_id), exchange.select_all_variants)',
|
||||
'id' => 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants' }
|
||||
= t('admin.select_all')
|
||||
{{ 'admin.select_all' | t }}
|
||||
|
||||
.exchange-products
|
||||
-# Scope product list based on permissions the current user has to view variants in this exchange
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
'ng-model' => 'exchange.select_all_variants',
|
||||
'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)',
|
||||
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
|
||||
= t('admin.select_all')
|
||||
{{ 'admin.select_all' | t }}
|
||||
|
||||
.exchange-products
|
||||
-# No need to scope product list based on permissions, because if an incoming exchange is visible,
|
||||
@@ -36,7 +36,7 @@
|
||||
'ofn-sync-distributions' => '{{ product.master_id }}',
|
||||
'id' => 'order_cycle_incoming_exchange_{{ $parent.$index }}_variants_{{ product.master_id }}',
|
||||
'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(product.master_id) < 0' }
|
||||
= t('admin.obsolete_master')
|
||||
{{ 'admin.obsolete_master' | t }}
|
||||
|
||||
.exchange-product-variant{'ng-repeat' => 'variant in product.variants'}
|
||||
%label
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.row.exchange-tags
|
||||
.sixteen.columns.alpha.omega
|
||||
%span.text-normal
|
||||
= t('admin.tags')
|
||||
{{ 'admin.tags' | t }}
|
||||
%br
|
||||
%tags-with-translation.fullwidth{ object: 'object' }
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
{{$getDisplayText()}}
|
||||
%span.tag-with-rules{ ng: { if: "data.rules == 1" } }
|
||||
—
|
||||
= t('admin.has_one_rule')
|
||||
{{ 'admin.has_one_rule' | t }}
|
||||
%span.tag-with-rules{ ng: { if: "data.rules > 1" } }
|
||||
—
|
||||
= t('admin.has_n_rules', { num: '{{data.rules}}' })
|
||||
{{ 'admin.has_n_rules' | t:{ num: data.rules } }}
|
||||
%span{ ng: { if: "!data.rules" } }
|
||||
{{$getDisplayText()}}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
%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()', removed:'tagRemoved()' } } }
|
||||
%auto-complete{ ng: { if: "findTags" }, source: "findTags({query: $query})",
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
.large-12.columns
|
||||
.alert-box.alert{"ng-show" => "errors != null"}
|
||||
{{ errors }}
|
||||
%a{ng: {show: 'user_unconfirmed', click: 'resend_confirmation()'}}
|
||||
= t('devise.confirmations.resend_confirmation_email')
|
||||
.alert-box.success{ng: {show: 'messages != null'}}
|
||||
{{ messages }}
|
||||
.row
|
||||
.large-12.columns
|
||||
%label{for: "email"} {{'email' | t}}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
%a.close-reveal-modal{"ng-click" => "$close()"}
|
||||
%i.ofn-i_009-close
|
||||
|
||||
%h3= t('js.out_of_stock.reduced_stock_available')
|
||||
%h3
|
||||
{{ 'js.out_of_stock.reduced_stock_available' | t }}
|
||||
|
||||
%p= t('js.out_of_stock.out_of_stock_text')
|
||||
%p
|
||||
{{ 'js.out_of_stock.out_of_stock_text' | t }}
|
||||
|
||||
%p{'ng-repeat' => "v in variants"}
|
||||
%em {{ v.name_to_display }} - {{ v.unit_to_display }}
|
||||
%span{'ng-if' => "v.count_on_hand == 0"}
|
||||
= t('js.out_of_stock.now_out_of_stock')
|
||||
{{ 'js.out_of_stock.now_out_of_stock' | t }}
|
||||
%span{'ng-if' => "v.count_on_hand > 0"}
|
||||
= t('js.out_of_stock.only_n_remainging', num: '{{ v.count_on_hand }}')
|
||||
{{ 'js.out_of_stock.only_n_remainging' | t:{ num: v.count_on_hand } }}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
%a.cta-hub{"ng-href" => "{{::enterprise.path}}",
|
||||
"ng-class" => "{primary: enterprise.active, secondary: !enterprise.active}",
|
||||
"ofn-change-hub" => "enterprise"}
|
||||
%i.ofn-i_033-open-sign{"ng-if" => "::enterprise.active"}
|
||||
%i.ofn-i_032-closed-sign{"ng-if" => "::!enterprise.active"}
|
||||
.hub-name{"ng-bind" => "::enterprise.name"}
|
||||
%span{"ng-if" => "::enterprise.active"} ({{'maps_open' | t}})
|
||||
%span{"ng-if" => "::!enterprise.active"} ({{'maps_closed' | t}})
|
||||
.button-address{"ng-bind" => "::[enterprise.address.city, enterprise.address.state_name] | printArray"}
|
||||
/ %i.ofn-i_007-caret-right
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
%a.cta-hub{"ng-repeat" => "hub in enterprise.hubs | filter:{id: '!'+enterprise.id} | orderBy:'-active'",
|
||||
"ng-href" => "{{::hub.path}}", "ofn-empties-cart" => "hub",
|
||||
"ng-class" => "::{primary: hub.active, secondary: !hub.active}"}
|
||||
%i.ofn-i_033-open-sign{"ng-if" => "::hub.active"}
|
||||
%i.ofn-i_032-closed-sign{"ng-if" => "::!hub.active"}
|
||||
.hub-name{"ng-bind" => "::hub.name"}
|
||||
%span{"ng-if" => "::hub.active"} ({{'maps_open' | t}})
|
||||
%span{"ng-if" => "::!hub.active"} ({{'maps_closed' | t}})
|
||||
.button-address{"ng-bind" => "::[hub.address.city, hub.address.state_name] | printArray"}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
%tab#sign-up-content{ heading: "{{'label_signup' | t}}", active: 'tabs.signup.active', select: "select(path)"}
|
||||
%form{ ng: { controller: "SignupCtrl", submit: "submit()" } }
|
||||
.row
|
||||
.large-12.columns
|
||||
.alert-box.success{ng: {show: 'messages != null'}}
|
||||
{{ messages }}
|
||||
.row
|
||||
.large-12.columns
|
||||
%label{for: "email"} {{'signup_email' | t}}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%li.more
|
||||
%a.dropdown{ data: { dropdown: "{{ 'show-more-' + selectorName }}" }, ng: { class: "{active: selectedOverFlowSelectors().length > 0}" } }
|
||||
%span
|
||||
= t('js.more_items', count: "{{ overFlowSelectors().length }}")
|
||||
{{ 'js.more_items' | t:{ count: overFlowSelectors().length } }}
|
||||
%i.ofn-i_052-point-down
|
||||
.f-dropdown.text-right.content{ ng: { attr: { id: "{{ 'show-more-' + selectorName }}" } } }
|
||||
%ul
|
||||
|
||||
@@ -1,3 +1,29 @@
|
||||
form[name="enterprise_form"] div.row.warning {
|
||||
color: #DA7F52;
|
||||
form[name="enterprise_form"] {
|
||||
div.row.warning {
|
||||
color: #DA7F52;
|
||||
}
|
||||
|
||||
table.managers {
|
||||
i.role {
|
||||
float: right;
|
||||
margin-left: 0.5em;
|
||||
font-size: 1.5em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
i.confirmation {
|
||||
margin-left: 0.2em;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
vertical-align: bottom;
|
||||
|
||||
&.confirmed {
|
||||
color: #1ece1e;
|
||||
}
|
||||
|
||||
&.unconfirmed {
|
||||
color: #ed9524;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
text-align: right
|
||||
p
|
||||
max-width: 400px
|
||||
h4 i
|
||||
margin-right: 0.3rem
|
||||
@media all and (max-width: 640px)
|
||||
float: left
|
||||
clear: left
|
||||
|
||||
@@ -88,6 +88,10 @@ footer {
|
||||
|
||||
@include panepadding;
|
||||
|
||||
div.row a img {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.row {
|
||||
&, p, h1, h2, h3, h4, h5, h6 {
|
||||
color: $disabled-med;
|
||||
|
||||
@@ -8,6 +8,14 @@
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
overflow-y: visible;
|
||||
|
||||
i {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.active_table_row {
|
||||
line-height: 1rem;
|
||||
}
|
||||
|
||||
//Generic text link style
|
||||
@@ -30,7 +38,7 @@
|
||||
//Closed & Open column
|
||||
.open_closed {
|
||||
i {
|
||||
font-size: 2rem;
|
||||
font-size: 1.75rem;
|
||||
float: right;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
@@ -36,10 +36,15 @@ nav {
|
||||
.top-bar-section .has-dropdown > a {
|
||||
padding-right: ($topbar-height / 3) !important;
|
||||
|
||||
i.ofn-i_022-cog {
|
||||
i.ofn-i_022-cog, .ofn-i_071-globe {
|
||||
font-size: 24px;
|
||||
line-height: $topbar-height;
|
||||
}
|
||||
|
||||
i.ofn-i_071-globe {
|
||||
color: #666;
|
||||
font-size: 27px
|
||||
}
|
||||
}
|
||||
|
||||
.top-bar-section .has-dropdown > a:after {
|
||||
@@ -95,6 +100,11 @@ nav {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.off-canvas-list li.language-switcher ul li {
|
||||
list-style-type: none;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.off-canvas-wrap.move-right .tab-bar .menu-icon {
|
||||
@include box-shadow(inset 0 0 6px 2px rgba(0, 0, 0, 0.5));
|
||||
}
|
||||
|
||||
@@ -160,13 +160,6 @@
|
||||
color: $clr-brick;
|
||||
}
|
||||
|
||||
i.ofn-i_033-open-sign, i.ofn-i_032-closed-sign {
|
||||
margin-right: 0.1rem;
|
||||
font-size: 2rem;
|
||||
padding: 0.15rem 0.25rem 0.35rem 0.25rem;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.hub-name {
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 0.2rem;
|
||||
|
||||
@@ -10,4 +10,16 @@
|
||||
background: #fff;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.alert-box {
|
||||
a {
|
||||
color: white;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,3 +233,6 @@
|
||||
.ofn-i_070-shop-map-reversed:before {
|
||||
content: "\e645";
|
||||
}
|
||||
.ofn-i_071-globe:before {
|
||||
content: "\e646";
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ module Admin
|
||||
invoke_callbacks(:update, :before)
|
||||
tag_rules_attributes = params[object_name].delete :tag_rules_attributes
|
||||
update_tag_rules(tag_rules_attributes) if tag_rules_attributes.present?
|
||||
update_enterprise_notifications
|
||||
if @object.update_attributes(params[object_name])
|
||||
invoke_callbacks(:update, :after)
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
@@ -198,6 +199,12 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def update_enterprise_notifications
|
||||
if params.key? :receives_notifications
|
||||
@enterprise.update_contact params[:receives_notifications]
|
||||
end
|
||||
end
|
||||
|
||||
def create_calculator_for(rule, attrs)
|
||||
if attrs[:calculator_type].present? && attrs[:calculator_attributes].present?
|
||||
rule.update_attributes(calculator_type: attrs[:calculator_type])
|
||||
|
||||
@@ -135,7 +135,7 @@ module Admin
|
||||
return
|
||||
end
|
||||
|
||||
available_coordinators = permitted_coordinating_enterprises_for(@order_cycle).select(&:confirmed?)
|
||||
available_coordinators = permitted_coordinating_enterprises_for(@order_cycle)
|
||||
case available_coordinators.count
|
||||
when 0
|
||||
flash[:error] = I18n.t(:order_cycles_no_permission_to_coordinate_error)
|
||||
|
||||
@@ -60,7 +60,12 @@ module Api
|
||||
def override_sells
|
||||
has_hub = current_api_user.owned_enterprises.is_hub.any?
|
||||
new_enterprise_is_producer = !!params[:enterprise][:is_primary_producer]
|
||||
params[:enterprise][:sells] = (has_hub && !new_enterprise_is_producer) ? 'any' : 'unspecified'
|
||||
|
||||
params[:enterprise][:sells] = if has_hub && !new_enterprise_is_producer
|
||||
'any'
|
||||
else
|
||||
'unspecified'
|
||||
end
|
||||
end
|
||||
|
||||
def override_visible
|
||||
|
||||
@@ -45,10 +45,6 @@ class DiscourseSsoController < ApplicationController
|
||||
end
|
||||
|
||||
def require_activation?
|
||||
!admin_user? && !email_validated?
|
||||
end
|
||||
|
||||
def email_validated?
|
||||
spree_current_user.enterprises.confirmed.map(&:email).include?(spree_current_user.email)
|
||||
!admin_user? && !spree_current_user.confirmed?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
class EnterpriseConfirmationsController < DeviseController
|
||||
include Spree::Core::ControllerHelpers::Auth # Needed for access to current_ability, so we can authorize! actions
|
||||
|
||||
# GET /resource/confirmation/new
|
||||
def new
|
||||
build_resource({})
|
||||
end
|
||||
|
||||
# POST /resource/confirmation
|
||||
def create
|
||||
self.resource = resource_class.find_by_unconfirmed_email_with_errors(resource_params)
|
||||
authorize! :resend_confirmation, resource
|
||||
|
||||
self.resource = resource_class.send_confirmation_instructions(resource_params)
|
||||
|
||||
if successfully_sent?(resource)
|
||||
set_flash_message(:success, :confirmation_sent) if is_navigational_format?
|
||||
else
|
||||
set_flash_message(:error, :confirmation_not_sent) if is_navigational_format?
|
||||
end
|
||||
|
||||
respond_with_navigational(resource){ redirect_to spree.admin_path }
|
||||
end
|
||||
|
||||
# GET /resource/confirmation?confirmation_token=abcdef
|
||||
def show
|
||||
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
||||
|
||||
if resource.errors.empty?
|
||||
set_flash_message(:success, :confirmed) if is_navigational_format?
|
||||
else
|
||||
set_flash_message(:error, :not_confirmed) if is_navigational_format?
|
||||
end
|
||||
|
||||
respond_with_navigational(resource){ redirect_to redirect_path(resource) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def new_user_reset_path(resource)
|
||||
password = Devise.friendly_token.first(8)
|
||||
user = Spree::User.create(email: resource.email, password: password, password_confirmation: password)
|
||||
user.send_reset_password_instructions_without_delay
|
||||
resource.users << user
|
||||
spree.edit_spree_user_password_path(user, :reset_password_token => user.reset_password_token, return_to: spree.admin_path)
|
||||
end
|
||||
|
||||
def redirect_path(resource)
|
||||
if resource.persisted? && !Spree::User.exists?(email: resource.email)
|
||||
new_user_reset_path(resource)
|
||||
else
|
||||
spree.admin_path
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,7 +7,7 @@ class EnterprisesController < BaseController
|
||||
|
||||
# These prepended filters are in the reverse order of execution
|
||||
prepend_before_filter :set_order_cycles, :require_distributor_chosen, :reset_order, only: :shop
|
||||
before_filter :check_stock_levels, only: :shop
|
||||
before_filter :check_stock_levels, :set_noindex_meta_tag, only: :shop
|
||||
|
||||
before_filter :clean_permalink, only: :check_permalink
|
||||
before_filter :enable_embedded_shopfront
|
||||
@@ -85,4 +85,8 @@ class EnterprisesController < BaseController
|
||||
order_cycle_options = OrderCycle.active.with_distributor(distributor)
|
||||
order.order_cycle = order_cycle_options.first if order_cycle_options.count == 1
|
||||
end
|
||||
|
||||
def set_noindex_meta_tag
|
||||
@noindex_meta_tag = true unless current_distributor.visible?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,8 @@ require 'spree/core/controller_helpers/respond_with_decorator'
|
||||
Spree::Admin::BaseController.class_eval do
|
||||
include I18nHelper
|
||||
|
||||
layout 'spree/layouts/admin'
|
||||
|
||||
before_filter :set_locale
|
||||
before_filter :warn_invalid_order_cycles
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Spree::Admin::OrdersController.class_eval do
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
helper CheckoutHelper
|
||||
before_filter :load_spree_api_key, :only => :bulk_management
|
||||
before_filter :load_order, only: %i[show edit update fire resend invoice print]
|
||||
before_filter :load_order, only: %i[show edit update fire resend invoice print print_ticket]
|
||||
|
||||
before_filter :load_distribution_choices, only: [:new, :edit, :update]
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ Spree::Admin::SearchController.class_eval do
|
||||
}).result.limit(10)
|
||||
end
|
||||
|
||||
render :users
|
||||
render json: @users, each_serializer: Api::Admin::UserSerializer
|
||||
end
|
||||
|
||||
def customers
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
Spree::UsersController.class_eval do
|
||||
layout 'darkswarm'
|
||||
include I18nHelper
|
||||
|
||||
before_filter :set_locale
|
||||
before_filter :enable_embedded_shopfront
|
||||
|
||||
# Override of spree_auth_devise default
|
||||
# Ignores invoice orders, only order where state: 'complete'
|
||||
def show
|
||||
@orders = @user.orders.where(state: 'complete').order('completed_at desc')
|
||||
@unconfirmed_email = spree_current_user.unconfirmed_email
|
||||
|
||||
return unless Spree::Config.accounts_distributor_id
|
||||
|
||||
|
||||
38
app/controllers/user_confirmations_controller.rb
Normal file
38
app/controllers/user_confirmations_controller.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
class UserConfirmationsController < DeviseController
|
||||
include Spree::Core::ControllerHelpers::Auth # Needed for access to current_ability, so we can authorize! actions
|
||||
|
||||
# GET /resource/confirmation/new
|
||||
def new
|
||||
build_resource({})
|
||||
end
|
||||
|
||||
# POST /resource/confirmation
|
||||
def create
|
||||
self.resource = resource_class.send_confirmation_instructions(resource_params)
|
||||
|
||||
if is_navigational_format?
|
||||
if successfully_sent?(resource)
|
||||
set_flash_message(:success, :confirmation_sent)
|
||||
else
|
||||
set_flash_message(:error, :confirmation_not_sent)
|
||||
end
|
||||
end
|
||||
|
||||
respond_with_navigational(resource){ redirect_to login_path }
|
||||
end
|
||||
|
||||
# GET /resource/confirmation?confirmation_token=abcdef
|
||||
def show
|
||||
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
||||
|
||||
if is_navigational_format?
|
||||
if resource.errors.empty?
|
||||
set_flash_message(:success, :confirmed)
|
||||
else
|
||||
set_flash_message(:error, :not_confirmed)
|
||||
end
|
||||
end
|
||||
|
||||
respond_with_navigational(resource){ redirect_to login_path }
|
||||
end
|
||||
end
|
||||
@@ -5,14 +5,13 @@ class UserRegistrationsController < Spree::UserRegistrationsController
|
||||
def create
|
||||
@user = build_resource(params[:spree_user])
|
||||
if resource.save
|
||||
set_flash_message(:success, :signed_up)
|
||||
sign_in(:spree_user, @user)
|
||||
session[:spree_user_signup] = true
|
||||
associate_user
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
sign_in_and_redirect(:spree_user, @user)
|
||||
set_flash_message(:success, :signed_up_but_unconfirmed)
|
||||
redirect_to after_sign_in_path_for(@user)
|
||||
end
|
||||
format.js do
|
||||
render json: { email: @user.email }
|
||||
|
||||
@@ -87,10 +87,12 @@ module InjectionHelper
|
||||
|
||||
def inject_json_ams(name, data, serializer, opts = {})
|
||||
if data.is_a?(Array)
|
||||
json = ActiveModel::ArraySerializer.new(data, {each_serializer: serializer}.merge(opts)).to_json
|
||||
else
|
||||
json = serializer.new(data, opts).to_json
|
||||
opts = { each_serializer: serializer }.merge(opts)
|
||||
serializer = ActiveModel::ArraySerializer
|
||||
end
|
||||
|
||||
serializer_instance = serializer.new(data, opts)
|
||||
json = serializer_instance.to_json
|
||||
render partial: "json/injection_ams", locals: {name: name, json: json}
|
||||
end
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ module OrderCyclesHelper
|
||||
end
|
||||
|
||||
def permitted_producer_enterprise_options_for(order_cycle)
|
||||
validated_enterprise_options permitted_producer_enterprises_for(order_cycle), confirmed: true
|
||||
validated_enterprise_options permitted_producer_enterprises_for(order_cycle)
|
||||
end
|
||||
|
||||
def permitted_coordinating_enterprises_for(order_cycle)
|
||||
@@ -20,7 +20,7 @@ module OrderCyclesHelper
|
||||
end
|
||||
|
||||
def permitted_coordinating_enterprise_options_for(order_cycle)
|
||||
validated_enterprise_options permitted_coordinating_enterprises_for(order_cycle), confirmed: true
|
||||
validated_enterprise_options permitted_coordinating_enterprises_for(order_cycle)
|
||||
end
|
||||
|
||||
def permitted_hub_enterprises_for(order_cycle)
|
||||
@@ -28,7 +28,7 @@ module OrderCyclesHelper
|
||||
end
|
||||
|
||||
def permitted_hub_enterprise_options_for(order_cycle)
|
||||
validated_enterprise_options permitted_hub_enterprises_for(order_cycle), confirmed: true, shipping_and_payment_methods: true
|
||||
validated_enterprise_options permitted_hub_enterprises_for(order_cycle), shipping_and_payment_methods: true
|
||||
end
|
||||
|
||||
def order_cycle_status_class(order_cycle)
|
||||
@@ -91,8 +91,6 @@ module OrderCyclesHelper
|
||||
elsif e.payment_methods.available.empty?
|
||||
disabled_message = I18n.t(:no_payment)
|
||||
end
|
||||
elsif options[:confirmed] && !e.confirmed?
|
||||
disabled_message = I18n.t(:unconfirmed)
|
||||
end
|
||||
|
||||
if disabled_message
|
||||
|
||||
@@ -37,7 +37,7 @@ class UpdateAccountInvoices
|
||||
if billable_periods.any?
|
||||
oldest_enterprise = billable_periods.first.enterprise
|
||||
address = oldest_enterprise.address.dup
|
||||
first, _space, last = (oldest_enterprise.contact || "").partition(' ')
|
||||
first, _space, last = (oldest_enterprise.contact_name || "").partition(' ')
|
||||
address.update_attributes(phone: oldest_enterprise.phone) if oldest_enterprise.phone.present?
|
||||
address.update_attributes(firstname: first, lastname: last) if first.present? && last.present?
|
||||
account_invoice.order.update_attributes(bill_address: address, ship_address: address)
|
||||
|
||||
@@ -7,21 +7,11 @@ class EnterpriseMailer < Spree::BaseMailer
|
||||
subject = t('enterprise_mailer.welcome.subject',
|
||||
enterprise: @enterprise.name,
|
||||
sitename: Spree::Config[:site_name])
|
||||
mail(:to => enterprise.email,
|
||||
mail(:to => enterprise.contact.email,
|
||||
:from => from_address,
|
||||
:subject => subject)
|
||||
end
|
||||
|
||||
def confirmation_instructions(record, token)
|
||||
@token = token
|
||||
find_enterprise(record)
|
||||
subject = t('enterprise_mailer.confirmation_instructions.subject',
|
||||
enterprise: @enterprise.name)
|
||||
mail(to: (@enterprise.unconfirmed_email || @enterprise.email),
|
||||
from: from_address,
|
||||
subject: subject)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_enterprise(enterprise)
|
||||
|
||||
@@ -13,11 +13,11 @@ class ProducerMailer < Spree::BaseMailer
|
||||
subject = "[#{Spree::Config.site_name}] #{I18n.t('producer_mailer.order_cycle.subject', producer: producer.name)}"
|
||||
|
||||
if has_orders? order_cycle, producer
|
||||
mail(to: @producer.email,
|
||||
mail(to: @producer.contact.email,
|
||||
from: from_address,
|
||||
subject: subject,
|
||||
reply_to: @coordinator.email,
|
||||
cc: @coordinator.email)
|
||||
reply_to: @coordinator.contact.email,
|
||||
cc: @coordinator.contact.email)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ Spree::OrderMailer.class_eval do
|
||||
mail(:to => @order.email,
|
||||
:from => from_address,
|
||||
:subject => subject,
|
||||
:reply_to => @order.distributor.email)
|
||||
:reply_to => @order.distributor.contact.email)
|
||||
end
|
||||
|
||||
def confirm_email_for_shop(order, resend = false)
|
||||
find_order(order) # Finds an order instance from an id
|
||||
subject = (resend ? "[#{t(:resend).upcase}] " : '')
|
||||
subject += "#{Spree::Config[:site_name]} #{t('order_mailer.confirm_email.subject')} ##{@order.number}"
|
||||
mail(:to => @order.distributor.email,
|
||||
mail(:to => @order.distributor.contact.email,
|
||||
:from => from_address,
|
||||
:subject => subject)
|
||||
end
|
||||
@@ -36,7 +36,7 @@ Spree::OrderMailer.class_eval do
|
||||
mail(:to => @order.email,
|
||||
:from => from_address,
|
||||
:subject => subject,
|
||||
:reply_to => @order.distributor.email)
|
||||
:reply_to => @order.distributor.contact.email)
|
||||
end
|
||||
|
||||
def find_order(order)
|
||||
|
||||
@@ -4,4 +4,13 @@ Spree::UserMailer.class_eval do
|
||||
mail(:to => user.email, :from => from_address,
|
||||
:subject => t(:welcome_to) + Spree::Config[:site_name])
|
||||
end
|
||||
|
||||
def confirmation_instructions(user, token)
|
||||
@user = user
|
||||
@token = token
|
||||
subject = t('spree.user_mailer.confirmation_instructions.subject')
|
||||
mail(to: user.email,
|
||||
from: from_address,
|
||||
subject: subject)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require_dependency 'spree/calculator'
|
||||
require 'spree/localized_number'
|
||||
|
||||
class Calculator::FlatPercentPerItem < Spree::Calculator
|
||||
# Spree's FlatPercentItemTotal calculator sums all amounts, and then calculates a percentage
|
||||
@@ -6,11 +7,14 @@ class Calculator::FlatPercentPerItem < Spree::Calculator
|
||||
# In the cart, we display line item individual amounts rounded, so to have consistent
|
||||
# calculations we do the same internally. Here, we round adjustments at the individual
|
||||
# item level first, then multiply by the item quantity.
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
preference :flat_percent, :decimal, :default => 0
|
||||
|
||||
attr_accessible :preferred_flat_percent
|
||||
|
||||
localize_number :preferred_flat_percent
|
||||
|
||||
def self.description
|
||||
I18n.t(:flat_percent_per_item)
|
||||
end
|
||||
|
||||
@@ -10,11 +10,9 @@ class Enterprise < ActiveRecord::Base
|
||||
# This is hopefully a temporary measure, pending the arrival of multiple named inventories
|
||||
# for shops. We need this here to allow hubs to restrict visible variants to only those in
|
||||
# their inventory if they so choose
|
||||
# TODO: delegate this to a separate model instead of abusing Preferences.
|
||||
preference :product_selection_from_inventory_only, :boolean, default: false
|
||||
|
||||
devise :confirmable, reconfirmable: true, confirmation_keys: [ :id, :email ]
|
||||
handle_asynchronously :send_confirmation_instructions
|
||||
handle_asynchronously :send_on_create_confirmation_instructions
|
||||
has_paper_trail only: [:owner_id, :sells], on: [:update]
|
||||
|
||||
self.inheritance_column = nil
|
||||
@@ -71,34 +69,27 @@ class Enterprise < ActiveRecord::Base
|
||||
validate :name_is_unique
|
||||
validates :sells, presence: true, inclusion: {in: SELLS}
|
||||
validates :address, presence: true, associated: true
|
||||
validates :email, presence: true
|
||||
validates_presence_of :owner
|
||||
validates :permalink, uniqueness: true, presence: true
|
||||
validate :shopfront_taxons
|
||||
validate :enforce_ownership_limit, if: lambda { owner_id_changed? && !owner_id.nil? }
|
||||
validates_length_of :description, :maximum => 255
|
||||
|
||||
before_save :confirmation_check, if: lambda { email_changed? }
|
||||
|
||||
before_validation :initialize_permalink, if: lambda { permalink.nil? }
|
||||
before_validation :ensure_owner_is_manager, if: lambda { owner_id_changed? && !owner_id.nil? }
|
||||
before_validation :ensure_email_set
|
||||
before_validation :set_unused_address_fields
|
||||
after_validation :geocode_address
|
||||
|
||||
after_touch :touch_distributors
|
||||
after_create :set_default_contact
|
||||
after_create :relate_to_owners_enterprises
|
||||
# TODO: Later versions of devise have a dedicated after_confirmation callback, so use that
|
||||
after_update :welcome_after_confirm, if: lambda { confirmation_token_changed? && confirmation_token.nil? }
|
||||
after_create :send_welcome_email, if: lambda { email_is_known? }
|
||||
after_create :send_welcome_email
|
||||
|
||||
after_rollback :restore_permalink
|
||||
|
||||
scope :by_name, order('name')
|
||||
scope :visible, where(visible: true)
|
||||
scope :confirmed, where('confirmed_at IS NOT NULL')
|
||||
scope :unconfirmed, where('confirmed_at IS NULL')
|
||||
scope :activated, where("confirmed_at IS NOT NULL AND sells != 'unspecified'")
|
||||
scope :activated, where("sells != 'unspecified'")
|
||||
scope :ready_for_checkout, lambda {
|
||||
joins(:shipping_methods).
|
||||
joins(:payment_methods).
|
||||
@@ -119,16 +110,6 @@ class Enterprise < ActiveRecord::Base
|
||||
scope :is_distributor, where('sells != ?', 'none')
|
||||
scope :is_hub, where(sells: 'any')
|
||||
scope :supplying_variant_in, lambda { |variants| joins(:supplied_products => :variants_including_master).where('spree_variants.id IN (?)', variants).select('DISTINCT enterprises.*') }
|
||||
scope :with_supplied_active_products_on_hand, lambda {
|
||||
joins(:supplied_products)
|
||||
.where('spree_products.deleted_at IS NULL AND spree_products.available_on <= ? AND spree_products.count_on_hand > 0', Time.zone.now)
|
||||
.uniq
|
||||
}
|
||||
scope :with_distributed_active_products_on_hand, lambda {
|
||||
joins(:distributed_products)
|
||||
.where('spree_products.deleted_at IS NULL AND spree_products.available_on <= ? AND spree_products.count_on_hand > 0', Time.zone.now)
|
||||
.uniq
|
||||
}
|
||||
|
||||
scope :with_distributed_products_outer,
|
||||
joins('LEFT OUTER JOIN product_distributions ON product_distributions.distributor_id = enterprises.id').
|
||||
@@ -196,8 +177,17 @@ class Enterprise < ActiveRecord::Base
|
||||
count(distinct: true)
|
||||
end
|
||||
|
||||
def contact
|
||||
contact = users.where(enterprise_roles: {receives_notifications: true}).first
|
||||
contact || owner
|
||||
end
|
||||
|
||||
def update_contact(user_id)
|
||||
enterprise_roles.update_all(["receives_notifications=(user_id=?)", user_id])
|
||||
end
|
||||
|
||||
def activated?
|
||||
confirmed_at.present? && sells != 'unspecified'
|
||||
contact.confirmed? && sells != 'unspecified'
|
||||
end
|
||||
|
||||
def set_producer_property(property_name, property_value)
|
||||
@@ -350,11 +340,6 @@ class Enterprise < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
# Based on a devise method, but without adding errors
|
||||
def pending_any_confirmation?
|
||||
!confirmed? || pending_reconfirmation?
|
||||
end
|
||||
|
||||
def shop_trial_expiry
|
||||
shop_trial_start_date.andand + Spree::Config[:shop_trial_length_days].days
|
||||
end
|
||||
@@ -380,25 +365,6 @@ class Enterprise < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def email_is_known?
|
||||
owner.enterprises.confirmed.map(&:email).include?(email)
|
||||
end
|
||||
|
||||
def confirmation_check
|
||||
# Skip confirmation/reconfirmation if the new email has already been confirmed
|
||||
if email_is_known?
|
||||
new_record? ? skip_confirmation! : skip_reconfirmation!
|
||||
end
|
||||
end
|
||||
|
||||
def welcome_after_confirm
|
||||
# Send welcome email if we are confirming a newly created enterprise
|
||||
# Note: this callback only runs on email confirmation
|
||||
if confirmed? && unconfirmed_email.nil? && !unconfirmed_email_changed?
|
||||
send_welcome_email
|
||||
end
|
||||
end
|
||||
|
||||
def send_welcome_email
|
||||
Delayed::Job.enqueue WelcomeEnterpriseJob.new(self.id)
|
||||
end
|
||||
@@ -419,16 +385,16 @@ class Enterprise < ActiveRecord::Base
|
||||
users << owner unless users.include?(owner) || owner.admin?
|
||||
end
|
||||
|
||||
def ensure_email_set
|
||||
self.email = owner.email if email.blank? && owner.present?
|
||||
end
|
||||
|
||||
def enforce_ownership_limit
|
||||
unless owner.can_own_more_enterprises?
|
||||
errors.add(:owner, I18n.t(:enterprise_owner_error, email: owner.email, enterprise_limit: owner.enterprise_limit ))
|
||||
end
|
||||
end
|
||||
|
||||
def set_default_contact
|
||||
update_contact self.owner_id
|
||||
end
|
||||
|
||||
def relate_to_owners_enterprises
|
||||
# When a new producer is created, it grants permissions to all pre-existing hubs
|
||||
# When a new hub is created,
|
||||
|
||||
@@ -38,7 +38,8 @@ class OrderCycle < ActiveRecord::Base
|
||||
joins(:exchanges).
|
||||
merge(Exchange.outgoing).
|
||||
merge(Exchange.with_product(product)).
|
||||
select('DISTINCT order_cycles.*') }
|
||||
select('DISTINCT order_cycles.*')
|
||||
}
|
||||
|
||||
scope :with_distributor, lambda { |distributor|
|
||||
joins(:exchanges).merge(Exchange.outgoing).merge(Exchange.to_enterprise(distributor))
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
require 'spree/localized_number'
|
||||
|
||||
module Spree
|
||||
Adjustment.class_eval do
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
# Deletion of metadata is handled in the database.
|
||||
# So we don't need the option `dependent: :destroy` as long as
|
||||
# AdjustmentMetadata has no destroy logic itself.
|
||||
@@ -17,6 +21,8 @@ module Spree
|
||||
|
||||
attr_accessible :included_tax
|
||||
|
||||
localize_number :amount
|
||||
|
||||
def set_included_tax!(rate)
|
||||
tax = amount - (amount / (1 + rate))
|
||||
set_absolute_included_tax! tax
|
||||
@@ -73,6 +79,5 @@ module Spree
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,4 +42,7 @@ Spree::AppConfiguration.class_eval do
|
||||
|
||||
# Stripe Connect
|
||||
preference :stripe_connect_enabled, :boolean, default: false
|
||||
|
||||
# Number localization
|
||||
preference :enable_localized_number?, :boolean, default: false
|
||||
end
|
||||
|
||||
@@ -20,7 +20,8 @@ Spree::Calculator::DefaultTax.class_eval do
|
||||
per_item_fees_total = order.line_items.sum do |line_item|
|
||||
calculator.send(:per_item_enterprise_fee_applicators_for, line_item.variant)
|
||||
.select { |applicator| (!applicator.enterprise_fee.inherits_tax_category && applicator.enterprise_fee.tax_category == rate.tax_category) ||
|
||||
(applicator.enterprise_fee.inherits_tax_category && line_item.product.tax_category == rate.tax_category) }
|
||||
(applicator.enterprise_fee.inherits_tax_category && line_item.product.tax_category == rate.tax_category)
|
||||
}
|
||||
.sum { |applicator| applicator.enterprise_fee.compute_amount(line_item) }
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
require 'spree/localized_number'
|
||||
|
||||
module Spree
|
||||
Calculator::FlatPercentItemTotal.class_eval do
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
localize_number :preferred_flat_percent
|
||||
|
||||
def compute(object)
|
||||
item_total = line_items_for(object).map(&:amount).sum
|
||||
value = item_total * BigDecimal(self.preferred_flat_percent.to_s) / 100.0
|
||||
|
||||
9
app/models/spree/calculator/flat_rate_decorator.rb
Normal file
9
app/models/spree/calculator/flat_rate_decorator.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
require 'spree/localized_number'
|
||||
|
||||
module Spree
|
||||
Calculator::FlatRate.class_eval do
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
localize_number :preferred_amount
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,12 @@
|
||||
require 'spree/localized_number'
|
||||
|
||||
module Spree
|
||||
Calculator::FlexiRate.class_eval do
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
localize_number :preferred_first_item,
|
||||
:preferred_additional_item
|
||||
|
||||
def compute(object)
|
||||
sum = 0
|
||||
max = self.preferred_max_items.to_i
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
require 'spree/localized_number'
|
||||
|
||||
module Spree
|
||||
Calculator::PerItem.class_eval do
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
localize_number :preferred_amount
|
||||
|
||||
def compute(object=nil)
|
||||
return 0 if object.nil?
|
||||
self.preferred_amount * line_items_for(object).reduce(0) do |sum, value|
|
||||
|
||||
11
app/models/spree/calculator/price_sack_decorator.rb
Normal file
11
app/models/spree/calculator/price_sack_decorator.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
require 'spree/localized_number'
|
||||
|
||||
module Spree
|
||||
Calculator::PriceSack.class_eval do
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
localize_number :preferred_minimal_amount,
|
||||
:preferred_normal_amount,
|
||||
:preferred_discount_amount
|
||||
end
|
||||
end
|
||||
@@ -1,11 +1,17 @@
|
||||
require 'spree/localized_number'
|
||||
|
||||
module Spree
|
||||
Payment.class_eval do
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
has_one :adjustment, as: :source, dependent: :destroy
|
||||
|
||||
after_save :ensure_correct_adjustment, :update_order
|
||||
|
||||
attr_accessible :source
|
||||
|
||||
localize_number :amount
|
||||
|
||||
def ensure_correct_adjustment
|
||||
revoke_adjustment_eligibility if ['failed', 'invalid'].include?(state)
|
||||
return if adjustment.try(:finalized?)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
Spree::PaymentMethod.class_eval do
|
||||
include Spree::Core::CalculatedAdjustments
|
||||
|
||||
Spree::PaymentMethod::DISPLAY = [:both, :front_end, :back_end]
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', :class_name => 'Enterprise', association_foreign_key: 'distributor_id'
|
||||
|
||||
@@ -16,7 +16,7 @@ module Spree
|
||||
private
|
||||
|
||||
def product_selection_from_inventory_only_changed?
|
||||
key =~ product_selection_from_inventory_only_regex
|
||||
!!(key =~ product_selection_from_inventory_only_regex)
|
||||
end
|
||||
|
||||
def enterprise
|
||||
|
||||
@@ -97,12 +97,14 @@ Spree::Product.class_eval do
|
||||
# Find products that are distributed by the given order cycle
|
||||
scope :in_order_cycle, lambda { |order_cycle| with_order_cycles_inner.
|
||||
merge(Exchange.outgoing).
|
||||
where('order_cycles.id = ?', order_cycle) }
|
||||
where('order_cycles.id = ?', order_cycle)
|
||||
}
|
||||
|
||||
scope :in_an_active_order_cycle, lambda { with_order_cycles_inner.
|
||||
merge(OrderCycle.active).
|
||||
merge(Exchange.outgoing).
|
||||
where('order_cycles.id IS NOT NULL') }
|
||||
where('order_cycles.id IS NOT NULL')
|
||||
}
|
||||
|
||||
scope :by_producer, joins(:supplier).order('enterprises.name')
|
||||
scope :by_name, order('name')
|
||||
|
||||
@@ -19,10 +19,16 @@ Spree.user_class.class_eval do
|
||||
accepts_nested_attributes_for :ship_address
|
||||
|
||||
attr_accessible :enterprise_ids, :enterprise_roles_attributes, :enterprise_limit, :locale, :bill_address_attributes, :ship_address_attributes
|
||||
after_create :send_signup_confirmation
|
||||
|
||||
validate :limit_owned_enterprises
|
||||
|
||||
# We use the same options as Spree and add :confirmable
|
||||
devise :confirmable, reconfirmable: true
|
||||
handle_asynchronously :send_confirmation_instructions
|
||||
handle_asynchronously :send_on_create_confirmation_instructions
|
||||
# TODO: Later versions of devise have a dedicated after_confirmation callback, so use that
|
||||
after_update :welcome_after_confirm, if: lambda { confirmation_token_changed? && confirmation_token.nil? }
|
||||
|
||||
def known_users
|
||||
if admin?
|
||||
Spree::User.scoped
|
||||
@@ -46,6 +52,14 @@ Spree.user_class.class_eval do
|
||||
customers.find_by_enterprise_id(enterprise)
|
||||
end
|
||||
|
||||
def welcome_after_confirm
|
||||
# Send welcome email if we are confirming an user's email
|
||||
# Note: this callback only runs on email confirmation
|
||||
if confirmed? && unconfirmed_email.nil? && !unconfirmed_email_changed?
|
||||
send_signup_confirmation
|
||||
end
|
||||
end
|
||||
|
||||
def send_signup_confirmation
|
||||
Delayed::Job.enqueue ConfirmSignupJob.new(id)
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@ require 'open_food_network/variant_and_line_item_naming'
|
||||
require 'open_food_network/products_cache'
|
||||
|
||||
Spree::Variant.class_eval do
|
||||
extend Spree::LocalizedNumber
|
||||
# Remove method From Spree, so method from the naming module is used instead
|
||||
# This file may be double-loaded in delayed job environment, so we check before
|
||||
# removing the Spree method to prevent error.
|
||||
@@ -55,6 +56,8 @@ Spree::Variant.class_eval do
|
||||
.where("o_inventory_items.id IS NULL OR o_inventory_items.visible = (?)", true)
|
||||
}
|
||||
|
||||
localize_number :price, :cost_price, :weight
|
||||
|
||||
# Define sope as class method to allow chaining with other scopes filtering id.
|
||||
# In Rails 3, merging two scopes on the same column will consider only the last scope.
|
||||
def self.in_distributor(distributor)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class VariantOverride < ActiveRecord::Base
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
belongs_to :hub, class_name: 'Enterprise'
|
||||
@@ -17,6 +19,8 @@ class VariantOverride < ActiveRecord::Base
|
||||
where(hub_id: hubs)
|
||||
}
|
||||
|
||||
localize_number :price
|
||||
|
||||
def self.indexed(hub)
|
||||
Hash[
|
||||
for_hubs(hub).preload(:variant).map { |vo| [vo.variant, vo] }
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/ insert_after "fieldset.currency"
|
||||
|
||||
%fieldset.number_localization.no-border-bottom
|
||||
%legend{:align => "center"}= t('admin.number_localization.number_localization_settings')
|
||||
.field
|
||||
= preference_field_tag(:enable_localized_number?, Spree::Config[:enable_localized_number?], type: Spree::Config.preference_type(:enable_localized_number?))
|
||||
= label_tag(:enable_localized_number?, t('admin.number_localization.enable_localized_number')) + tag(:br)
|
||||
@@ -39,7 +39,7 @@
|
||||
.alpha.three.columns
|
||||
-# The 'Category' label here is just a logical descriptor for the data we are trying to collect for 'requires_ship_address'
|
||||
-# and does not relate to shipping categories in any way.
|
||||
= f.label :require_ship_address, "Category"
|
||||
= f.label :require_ship_address, t(:category)
|
||||
.two.columns
|
||||
= f.radio_button :require_ship_address, true
|
||||
|
||||
|
||||
@@ -11,3 +11,8 @@
|
||||
.field{"data-hook" => "unit_description"}
|
||||
= f.label :unit_description, t(:spree_admin_unit_description)
|
||||
= f.text_field :unit_description, class: "fullwidth", placeholder: t('admin.products.unit_name_placeholder')
|
||||
|
||||
:javascript
|
||||
angular.element(document.getElementById("new_variant")).ready(function() {
|
||||
angular.bootstrap(document.getElementById("new_variant"), ['admin.products']);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/ insert_before "#password-credentials"
|
||||
|
||||
- if @unconfirmed_email
|
||||
%p.alert-box
|
||||
= t('spree.users.show.unconfirmed_email', unconfirmed_email: @unconfirmed_email)
|
||||
@@ -1,9 +1,9 @@
|
||||
class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer
|
||||
attributes :name, :id, :is_primary_producer, :is_distributor, :sells, :category, :payment_method_ids, :shipping_method_ids
|
||||
attributes :producer_profile_only, :email, :long_description, :permalink
|
||||
attributes :producer_profile_only, :long_description, :permalink
|
||||
attributes :preferred_shopfront_message, :preferred_shopfront_closed_message, :preferred_shopfront_taxon_order, :preferred_shopfront_order_cycle_order
|
||||
attributes :preferred_product_selection_from_inventory_only
|
||||
attributes :owner, :users, :tag_groups, :default_tag_group
|
||||
attributes :owner, :contact, :users, :tag_groups, :default_tag_group
|
||||
attributes :require_login, :allow_guest_orders, :allow_order_changes
|
||||
|
||||
has_one :owner, serializer: Api::Admin::UserSerializer
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'open_food_network/last_used_address'
|
||||
|
||||
class Api::Admin::UserSerializer < ActiveModel::Serializer
|
||||
attributes :id, :email
|
||||
attributes :id, :email, :confirmed
|
||||
|
||||
has_one :ship_address, serializer: Api::AddressSerializer
|
||||
has_one :bill_address, serializer: Api::AddressSerializer
|
||||
@@ -15,4 +15,8 @@ class Api::Admin::UserSerializer < ActiveModel::Serializer
|
||||
object.bill_address ||
|
||||
OpenFoodNetwork::LastUsedAddress.new(object.email).last_used_bill_address
|
||||
end
|
||||
|
||||
def confirmed
|
||||
object.confirmed?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class Api::VariantSerializer < ActiveModel::Serializer
|
||||
attributes :id, :is_master, :count_on_hand, :name_to_display, :unit_to_display, :unit_value
|
||||
attributes :options_text, :on_demand, :price, :fees, :price_with_fees, :product_name
|
||||
attributes :tag_list
|
||||
|
||||
def price
|
||||
object.price
|
||||
@@ -22,4 +23,10 @@ class Api::VariantSerializer < ActiveModel::Serializer
|
||||
def product_name
|
||||
object.product.name
|
||||
end
|
||||
|
||||
# Used for showing/hiding variants in shopfront based on tag rules
|
||||
def tag_list
|
||||
return [] unless object.respond_to?(:tag_list)
|
||||
object.tag_list
|
||||
end
|
||||
end
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
.row.margin-bottom-50{ ng: { show: "!RequestMonitor.loading && filteredCustomers.length > 0" } }
|
||||
%form{ name: "customers_form" }
|
||||
%save-bar{ dirty: "customers_form.$dirty", persist: "false" }
|
||||
%input.red{ type: "button", value: "Save Changes", ng: { click: "submitAll(customers_form)", disabled: "!customers_form.$dirty" } }
|
||||
%input.red{ type: "button", value: "Save Changes", ng: { click: "submitAll(customers_form)" } }
|
||||
|
||||
%table.index#customers
|
||||
%col.email{ width: "20%", 'ng-show' => 'columns.email.visible' }
|
||||
|
||||
@@ -46,9 +46,9 @@
|
||||
|
||||
.row
|
||||
.alpha.three.columns
|
||||
= f.label :contact, t('.contact_name')
|
||||
= f.label :contact_name, t('.contact_name')
|
||||
.omega.nine.columns
|
||||
= f.text_field :contact, { placeholder: t('admin.enterprises.form.contact.name_placeholder')}
|
||||
= f.text_field :contact_name, { placeholder: t('admin.enterprises.form.contact.name_placeholder')}
|
||||
.row
|
||||
.alpha.three.columns
|
||||
= f.label :email_address, t('admin.enterprises.form.contact.email_address')
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
.row
|
||||
.alpha.three.columns
|
||||
= f.label :contact, t('.name')
|
||||
= f.label :contact_name, t('.name')
|
||||
.omega.eight.columns
|
||||
= f.text_field :contact, { placeholder: t('.name_placeholder') }
|
||||
= f.text_field :contact_name, { placeholder: t('.name_placeholder') }
|
||||
.row
|
||||
.alpha.three.columns
|
||||
= f.label :email_address, t('.email_address')
|
||||
%div{'ofn-with-tip' => t('.email_address_tip')}
|
||||
%a= t('admin.whats_this')
|
||||
.omega.eight.columns
|
||||
= f.text_field :email_address, { placeholder: t('.email_address_placeholder') }
|
||||
.row
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
- owner_email = @enterprise.andand.owner.andand.email || ""
|
||||
- full_permissions = (spree_current_user.admin? || spree_current_user == @enterprise.andand.owner)
|
||||
|
||||
-if @enterprise.pending_any_confirmation?
|
||||
.alert-box
|
||||
- email = @enterprise.confirmed? ? @enterprise.unconfirmed_email : @enterprise.email
|
||||
= t('.email_confirmation_notice_html', {email: "<strong>#{email}</strong>".html_safe})
|
||||
= link_to(t('.resend'), main_app.enterprise_confirmation_path(enterprise: { id: @enterprise.id, email: email } ), method: :post)
|
||||
%a.close{ href: "#" } ×
|
||||
|
||||
.row
|
||||
.three.columns.alpha
|
||||
=f.label :owner_id, t('.owner')
|
||||
@@ -17,27 +10,24 @@
|
||||
%a= t('admin.whats_this')
|
||||
.eight.columns.omega
|
||||
- if full_permissions
|
||||
= f.hidden_field :owner_id, class: "select2 fullwidth", 'user-select' => 'Enterprise.owner'
|
||||
= f.hidden_field :owner_id, class: "select2 fullwidth", 'user-select' => 'Enterprise.owner', 'ng-model' => 'Enterprise.owner'
|
||||
- else
|
||||
= owner_email
|
||||
|
||||
.row
|
||||
.three.columns.alpha
|
||||
= f.label :email, t('.notifications')
|
||||
=f.label :user_ids, t('.notifications')
|
||||
- if full_permissions
|
||||
%span.required *
|
||||
.with-tip{'data-powertip' => t('.notifications_tip')}
|
||||
%div{'ofn-with-tip' => t('.contact_tip')}
|
||||
%a= t('admin.whats_this')
|
||||
.eight.columns.omega
|
||||
- if full_permissions
|
||||
= f.text_field :email, { placeholder: t('.notifications_placeholder'), "ng-model" => "Enterprise.email" }
|
||||
%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}}'}
|
||||
{{user.email}}
|
||||
- else
|
||||
= @enterprise.email
|
||||
.row{ ng: { hide: "pristineEmail == null || pristineEmail == Enterprise.email"} }
|
||||
.alpha.three.columns
|
||||
|
||||
.omega.eight.columns
|
||||
= t('.notifications_note')
|
||||
= @enterprise.contact.email
|
||||
|
||||
.row
|
||||
.three.columns.alpha
|
||||
@@ -48,19 +38,24 @@
|
||||
%a= t('admin.whats_this')
|
||||
.eight.columns.omega
|
||||
- if full_permissions
|
||||
%table
|
||||
%table.managers
|
||||
%tr
|
||||
%td
|
||||
- # Ignore this input in the submit
|
||||
= hidden_field_tag :ignored, :new_manager, class: "select2 fullwidth", 'user-select' => 'newManager', 'ng-model' => 'newManager'
|
||||
%td.actions
|
||||
%a{ 'ng-click' => 'addManager(newManager)', :class => "icon-plus no-text" }
|
||||
%tr.animate-repeat{ 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'} }
|
||||
%td.actions
|
||||
%a{ 'ng-click' => 'removeManager(manager)', :class => "icon-trash no-text" }
|
||||
%a{ ng: {click: 'removeManager(manager)', class: "{disabled: manager.id == Enterprise.owner.id || manager.id == receivesNotifications}"}, :class => "icon-trash no-text" }
|
||||
|
||||
- else
|
||||
- @enterprise.users.each do |manager|
|
||||
= manager.email
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
= render 'checkout/accordion_heading'
|
||||
|
||||
.small-12.columns.medium-12.columns.large-6.columns
|
||||
%label{"ng-repeat" => "method in ShippingMethods.shipping_methods"}
|
||||
%label{"ng-repeat" => "method in ShippingMethods.shipping_methods | orderBy: 'name'"}
|
||||
%input{type: :radio,
|
||||
required: true,
|
||||
name: "order.shipping_method_id",
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
%h3
|
||||
= t :email_confirmation_greeting, contact: @enterprise.contact
|
||||
%p.lead
|
||||
= t :email_confirmation_profile_created, name: @enterprise.name
|
||||
%p
|
||||
|
||||
%p.callout
|
||||
= t :email_confirmation_click_link
|
||||
%br
|
||||
%strong
|
||||
= link_to t(:email_confirmation_link_label), confirmation_url(@enterprise, :confirmation_token => @enterprise.confirmation_token)
|
||||
|
||||
%p
|
||||
%p
|
||||
= t :email_confirmation_help_html, link: link_to(t(:email_confirmation_userguide), 'http://www.openfoodnetwork.org/platform/user-guide/'), sitename: Spree::Config[:site_name]
|
||||
|
||||
= render 'shared/mailers/signoff'
|
||||
|
||||
= render 'shared/mailers/social_and_contact'
|
||||
@@ -1,7 +1,6 @@
|
||||
%h3
|
||||
= "#{t(:email_welcome)}, #{@enterprise.contact}!"
|
||||
= "#{t(:email_welcome)}!"
|
||||
%p.lead
|
||||
= t :email_confirmed
|
||||
%strong
|
||||
= @enterprise.name
|
||||
= "#{t(:email_registered)} #{ Spree::Config.site_name }!"
|
||||
@@ -13,7 +12,7 @@
|
||||
= t :email_admin_html, link: link_to('Admin Panel', spree.admin_url)
|
||||
|
||||
%p
|
||||
= t :email_community_html, link: link_to(t(:join_the_community), ContentConfig.community_forum_url)
|
||||
= t :email_community_html, link: link_to(t(:join_community), ContentConfig.community_forum_url)
|
||||
|
||||
%p
|
||||
= t :email_help
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
%script
|
||||
:javascript
|
||||
I18n.default_locale = "#{I18n.default_locale}";
|
||||
I18n.locale = "#{I18n.locale}";
|
||||
I18n.fallbacks = true;
|
||||
moment.lang([I18n.locale, 'en']);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user