mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-14 18:56:49 +00:00
Compare commits
450 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61a58bca7d | ||
|
|
e67e22ee73 | ||
|
|
7a23f671a2 | ||
|
|
d115eb816e | ||
|
|
4b5e33d5b0 | ||
|
|
c579d302d5 | ||
|
|
2f2ebf419c | ||
|
|
2f13ab6adf | ||
|
|
b121984e76 | ||
|
|
23b9dd5c71 | ||
|
|
bc6110c178 | ||
|
|
72f7e545dc | ||
|
|
e0da49e4df | ||
|
|
b004060679 | ||
|
|
ea68619f0b | ||
|
|
555f639026 | ||
|
|
26a2f1a280 | ||
|
|
83e3fb98f7 | ||
|
|
bac4fcbd8f | ||
|
|
ecd11702c3 | ||
|
|
fe0652e243 | ||
|
|
f49722ba90 | ||
|
|
0370723edd | ||
|
|
d46712de84 | ||
|
|
199a3c38f9 | ||
|
|
0ed8cf973d | ||
|
|
76d4f74f6b | ||
|
|
ca3c464fda | ||
|
|
85f61364f8 | ||
|
|
c1d04af5cc | ||
|
|
5b72f53738 | ||
|
|
da325780b1 | ||
|
|
a40a03905f | ||
|
|
044e423543 | ||
|
|
cb9b61f393 | ||
|
|
58031408f1 | ||
|
|
e20b06bb97 | ||
|
|
cc4f9dd09b | ||
|
|
18ea0c1717 | ||
|
|
2bb85eb8e0 | ||
|
|
5d28a7fdf8 | ||
|
|
befc558224 | ||
|
|
c91f1301f0 | ||
|
|
e6a51bb49d | ||
|
|
ae0ad73b4a | ||
|
|
b7edf5e046 | ||
|
|
81f244025f | ||
|
|
fcc328f00a | ||
|
|
758b1f8e64 | ||
|
|
bb58473b90 | ||
|
|
1d46c2febd | ||
|
|
15ea64b409 | ||
|
|
6787709693 | ||
|
|
a3874d42af | ||
|
|
3f8d470d23 | ||
|
|
ae3061df80 | ||
|
|
5579fa5e0b | ||
|
|
e33ede0ec2 | ||
|
|
76d4fbccf9 | ||
|
|
60e971ad63 | ||
|
|
222b390b31 | ||
|
|
932ac45ea5 | ||
|
|
80ebaece2d | ||
|
|
3419198635 | ||
|
|
1026b81d0c | ||
|
|
c74463404d | ||
|
|
2081744cf6 | ||
|
|
cbaf2a0cb3 | ||
|
|
6e7b6b5dfc | ||
|
|
815694de31 | ||
|
|
2daceb1111 | ||
|
|
eb07680f1f | ||
|
|
47c23c986a | ||
|
|
742e2279ae | ||
|
|
eaae16a486 | ||
|
|
ae945ace9d | ||
|
|
9d5606a4fd | ||
|
|
cd7721a127 | ||
|
|
ee447c9ce6 | ||
|
|
eba2aae353 | ||
|
|
c1a80b1e8f | ||
|
|
6998df25e0 | ||
|
|
921210012a | ||
|
|
8d270e919f | ||
|
|
1e397a41ae | ||
|
|
243ef4ee16 | ||
|
|
ea6974d438 | ||
|
|
ccb23cd186 | ||
|
|
d4ee20455e | ||
|
|
ef603a070e | ||
|
|
1a4448c6d2 | ||
|
|
a78d8fa6af | ||
|
|
8c0a82f26f | ||
|
|
93c42d24c7 | ||
|
|
036ffeb634 | ||
|
|
3dcbdad088 | ||
|
|
7820c31976 | ||
|
|
d314f07887 | ||
|
|
2efaedc225 | ||
|
|
c5e2ed5aa1 | ||
|
|
8f917817b8 | ||
|
|
a2c0088c91 | ||
|
|
9fef0a9909 | ||
|
|
29bfac5f54 | ||
|
|
efa7c215e2 | ||
|
|
1589bd9ac3 | ||
|
|
a810a6e2b7 | ||
|
|
c4fb4a8510 | ||
|
|
d67a5aba0e | ||
|
|
d5c4da3bf0 | ||
|
|
261a464b50 | ||
|
|
0f2ae79e05 | ||
|
|
caffdee047 | ||
|
|
d320b2e7d4 | ||
|
|
e8ccd35363 | ||
|
|
bd854bf2dd | ||
|
|
10edb2b056 | ||
|
|
86f1afae92 | ||
|
|
1cffd35968 | ||
|
|
baeacfb8a9 | ||
|
|
7ecf5df26a | ||
|
|
a5a886c51f | ||
|
|
96aace971f | ||
|
|
6c254c534f | ||
|
|
b341c1ef8a | ||
|
|
7e6b43266f | ||
|
|
3975eef0c4 | ||
|
|
a2a87cc68f | ||
|
|
4bdc1bc418 | ||
|
|
33454a7090 | ||
|
|
6268b7cc7e | ||
|
|
75846a4d1f | ||
|
|
c199e22190 | ||
|
|
3b2bdb8397 | ||
|
|
767671c3b4 | ||
|
|
76414dedff | ||
|
|
ae7fb91a9a | ||
|
|
229070a76b | ||
|
|
8bfe459241 | ||
|
|
bb6fb2f5e8 | ||
|
|
6de44877c8 | ||
|
|
b6f3e6eca6 | ||
|
|
a86cc96452 | ||
|
|
178e5f59e6 | ||
|
|
7fffa03d8d | ||
|
|
888e4d80ef | ||
|
|
d3c7c46800 | ||
|
|
c432ed9e08 | ||
|
|
e175149e76 | ||
|
|
1b5901317d | ||
|
|
2f4b5bad26 | ||
|
|
64e8927ae9 | ||
|
|
c932d20ef5 | ||
|
|
5d5fda3a25 | ||
|
|
a96cdd5ee7 | ||
|
|
4191e2b6f0 | ||
|
|
88fd9f72e6 | ||
|
|
3d36ebe2e6 | ||
|
|
6966fbba7c | ||
|
|
2310bc95bc | ||
|
|
27a5791e26 | ||
|
|
be8038e9d0 | ||
|
|
1556d38b1e | ||
|
|
4e4de65cba | ||
|
|
6e8d807408 | ||
|
|
095466cb43 | ||
|
|
2719c699d7 | ||
|
|
34030276d7 | ||
|
|
330977186e | ||
|
|
fc57255b40 | ||
|
|
266820742d | ||
|
|
722471a111 | ||
|
|
86b5e810e5 | ||
|
|
f8a31e8864 | ||
|
|
639472b917 | ||
|
|
193325f81b | ||
|
|
5a7cac652c | ||
|
|
b5aaf36bd2 | ||
|
|
c5a26249ea | ||
|
|
69ead3c829 | ||
|
|
93caa4a11d | ||
|
|
e20d8d3e95 | ||
|
|
fb3e292e20 | ||
|
|
f499dd627a | ||
|
|
8e1bade355 | ||
|
|
a32321df68 | ||
|
|
5a29311137 | ||
|
|
3e7a12cca1 | ||
|
|
81a6e07d5c | ||
|
|
727ecae62b | ||
|
|
85e45fa558 | ||
|
|
83c0093665 | ||
|
|
46a9304ae1 | ||
|
|
d794981ecf | ||
|
|
6476ce6ba9 | ||
|
|
a06b452e7e | ||
|
|
0b6cbb43d6 | ||
|
|
27903a46e6 | ||
|
|
330882c689 | ||
|
|
b1bac703ed | ||
|
|
bf6bd2dc68 | ||
|
|
eb7b2e7a3b | ||
|
|
73c80cb5e5 | ||
|
|
6769c2c729 | ||
|
|
afef9e3211 | ||
|
|
a9e5f2912f | ||
|
|
66d1e4297e | ||
|
|
5e59048705 | ||
|
|
4d4e2d4abd | ||
|
|
db4e8382e4 | ||
|
|
51762753f4 | ||
|
|
2483eef4be | ||
|
|
38d2616ea0 | ||
|
|
5db64b6f21 | ||
|
|
0505a45de5 | ||
|
|
e96fa967b8 | ||
|
|
8b29612614 | ||
|
|
90d52151b6 | ||
|
|
6666de96b2 | ||
|
|
b7d92786d0 | ||
|
|
d731d4e803 | ||
|
|
2277b9f5a6 | ||
|
|
aef8b9648e | ||
|
|
65589d25c6 | ||
|
|
5ffad4d343 | ||
|
|
50a551a87e | ||
|
|
1494389d34 | ||
|
|
b43049af47 | ||
|
|
f563f04f1c | ||
|
|
ae7e744644 | ||
|
|
625e0888ea | ||
|
|
a3d638df67 | ||
|
|
9227df54b6 | ||
|
|
015f3eb9ac | ||
|
|
fd747f9012 | ||
|
|
7350dbb75e | ||
|
|
94e1264aef | ||
|
|
aec3980a93 | ||
|
|
4eed222f18 | ||
|
|
f63a80300b | ||
|
|
87cf3eda41 | ||
|
|
02423d3a41 | ||
|
|
cb1f79f59a | ||
|
|
18a7317185 | ||
|
|
c5810fc003 | ||
|
|
f60b6994eb | ||
|
|
50b3635e7e | ||
|
|
ab7bfd10c5 | ||
|
|
cdb0c2db33 | ||
|
|
21e5895a8a | ||
|
|
33e1322a44 | ||
|
|
b08556ec7f | ||
|
|
a71999ba84 | ||
|
|
2d468f5022 | ||
|
|
eba13a0dd7 | ||
|
|
1946bac8e4 | ||
|
|
e52f7165c3 | ||
|
|
6dfae1b014 | ||
|
|
40972cc6ec | ||
|
|
795830d94d | ||
|
|
039fcb80eb | ||
|
|
6a70c162bb | ||
|
|
0fd29dd32e | ||
|
|
bbeeb8a493 | ||
|
|
6c1619ba60 | ||
|
|
df34f6ef8e | ||
|
|
dc8166ec84 | ||
|
|
ef08977dbe | ||
|
|
9b2653aa2d | ||
|
|
adf0a84669 | ||
|
|
7163664725 | ||
|
|
2053fbecda | ||
|
|
6781051fe6 | ||
|
|
2357f46a4e | ||
|
|
8bd78eb139 | ||
|
|
f152e4054c | ||
|
|
62d31f79ed | ||
|
|
2ea1a59666 | ||
|
|
a95727b376 | ||
|
|
b35df3c945 | ||
|
|
421774e46c | ||
|
|
5b3e052f78 | ||
|
|
47fb2270bd | ||
|
|
f12fd7b4a3 | ||
|
|
40d627cb34 | ||
|
|
6e7fc6a0f7 | ||
|
|
104b100fe6 | ||
|
|
3a505abfc7 | ||
|
|
ecc3bad8c8 | ||
|
|
13fc36bad6 | ||
|
|
a766f007fc | ||
|
|
4fbeb0c3b1 | ||
|
|
de80e6d5bf | ||
|
|
92f7b72056 | ||
|
|
b22d591775 | ||
|
|
1ad0f95536 | ||
|
|
a71410042f | ||
|
|
815df3d667 | ||
|
|
27741863c5 | ||
|
|
1751a95909 | ||
|
|
c169e4af92 | ||
|
|
7d379dbe4b | ||
|
|
5f80043857 | ||
|
|
e9d1cf6eb5 | ||
|
|
d2470685cd | ||
|
|
a4db4ee782 | ||
|
|
9115e1175e | ||
|
|
56fd91f82b | ||
|
|
d62775a785 | ||
|
|
8b40d094ee | ||
|
|
91fae79be4 | ||
|
|
5aa3ebde9c | ||
|
|
bd737ef727 | ||
|
|
31e7ca9fa2 | ||
|
|
0eed8b4578 | ||
|
|
6b1e66ed26 | ||
|
|
da42032d92 | ||
|
|
143c005f0a | ||
|
|
ae96541112 | ||
|
|
f8725a0174 | ||
|
|
9c6264c4a0 | ||
|
|
10bc3919ca | ||
|
|
b5bc4701fa | ||
|
|
7552776349 | ||
|
|
8f40702369 | ||
|
|
9dc0598870 | ||
|
|
4f05b9c28d | ||
|
|
aa4f1f1dec | ||
|
|
14fbeda29e | ||
|
|
1c6f3f4877 | ||
|
|
2dcbe2b4f2 | ||
|
|
27384439f8 | ||
|
|
13adb61b3a | ||
|
|
77c10dafd6 | ||
|
|
4a8f9d1e36 | ||
|
|
0debdcdd9c | ||
|
|
ae30007fed | ||
|
|
aa183dc9e0 | ||
|
|
b1285cd07f | ||
|
|
79497d28d2 | ||
|
|
5eb20fd8cd | ||
|
|
01c9560a19 | ||
|
|
6cc403cd92 | ||
|
|
11c3cf5f71 | ||
|
|
448bd12e9f | ||
|
|
204a3275ac | ||
|
|
6665f9b4a0 | ||
|
|
ddb0aa4e74 | ||
|
|
aa8e486a45 | ||
|
|
619c4959ff | ||
|
|
1b2a06572b | ||
|
|
cc26321ab2 | ||
|
|
fb01f6d32a | ||
|
|
0fbd26a3c5 | ||
|
|
6f3fad5864 | ||
|
|
5f61952785 | ||
|
|
128b6853f4 | ||
|
|
bed3815df5 | ||
|
|
7c5816af82 | ||
|
|
15df1f7f26 | ||
|
|
065bc087d5 | ||
|
|
c53b5f3edb | ||
|
|
60cd5ce879 | ||
|
|
8bbda5715d | ||
|
|
92eb5ed367 | ||
|
|
70de4fd1fd | ||
|
|
c2c0c3684d | ||
|
|
38e3690f56 | ||
|
|
2048800c43 | ||
|
|
cc0f1ccfa7 | ||
|
|
d3e8966e65 | ||
|
|
e6f6a3ad81 | ||
|
|
160c0d75fe | ||
|
|
f2389ee672 | ||
|
|
0812643136 | ||
|
|
3e9a61a693 | ||
|
|
e3e59d76a9 | ||
|
|
65c26296bd | ||
|
|
9c4ed5f092 | ||
|
|
f0fa696d2f | ||
|
|
4d58faefd8 | ||
|
|
311ffc3dc9 | ||
|
|
d51c69d353 | ||
|
|
ee8a86d495 | ||
|
|
fa8c3d65dc | ||
|
|
b4e58a1a79 | ||
|
|
550434dfe8 | ||
|
|
fc44e57171 | ||
|
|
77f735c722 | ||
|
|
b736e209ca | ||
|
|
af2bc99c71 | ||
|
|
924b3b4cc3 | ||
|
|
b724745acc | ||
|
|
bbe25da117 | ||
|
|
77e361dd52 | ||
|
|
083d7327bc | ||
|
|
2fa217df56 | ||
|
|
6489848eff | ||
|
|
b8e40d799b | ||
|
|
205a7f1673 | ||
|
|
2e591b98e1 | ||
|
|
0b4a43d77a | ||
|
|
ce87ea54cd | ||
|
|
637e5c4fee | ||
|
|
ecca23488d | ||
|
|
2488411b94 | ||
|
|
3f822ed0e3 | ||
|
|
33af6cbfb1 | ||
|
|
326c972f63 | ||
|
|
11892ffe21 | ||
|
|
10cd654ff5 | ||
|
|
3e53decd85 | ||
|
|
4f0e75893e | ||
|
|
e61abb92d2 | ||
|
|
832f47d6b0 | ||
|
|
415dac3ae3 | ||
|
|
8b6f5b4a99 | ||
|
|
06010bd8ad | ||
|
|
85c99102dd | ||
|
|
d908701b59 | ||
|
|
e3085d9224 | ||
|
|
3dbc2e0382 | ||
|
|
baaa192967 | ||
|
|
2f05fc3824 | ||
|
|
955f41633a | ||
|
|
fd37324359 | ||
|
|
63ec0d7dcf | ||
|
|
91ca5f0213 | ||
|
|
f5b45fa0ba | ||
|
|
73376b30e2 | ||
|
|
3565548e91 | ||
|
|
6999bcfd4e | ||
|
|
2fe5d7c73f | ||
|
|
3a3bf19cf8 | ||
|
|
30e04b509d | ||
|
|
4279742de5 | ||
|
|
713c93a570 | ||
|
|
36584f0177 | ||
|
|
6b1c125b03 | ||
|
|
0f1ec17698 | ||
|
|
9103e83ce2 | ||
|
|
99709b53ed | ||
|
|
717b3b6494 | ||
|
|
ca665dc6bc | ||
|
|
67b17de695 | ||
|
|
8d5a0aea9f | ||
|
|
803d790b7a | ||
|
|
375bdc0586 | ||
|
|
9b7fd1c16b | ||
|
|
05437e2a56 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -34,6 +34,7 @@ config/abr.yml
|
||||
config/heroku_env.rb
|
||||
config/newrelic.yml
|
||||
config/initializers/feature_toggle.rb
|
||||
config/initializers/db2fog.rb
|
||||
NERD_tree*
|
||||
coverage
|
||||
libpeerconnection.log
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.9.3-p392
|
||||
2.1.5
|
||||
|
||||
53
.travis.yml
53
.travis.yml
@@ -1,15 +1,56 @@
|
||||
language: ruby
|
||||
sudo: false
|
||||
cache: bundler
|
||||
bundler_args: --without development
|
||||
rvm:
|
||||
- "1.9.3"
|
||||
services: postgresql
|
||||
before_install:
|
||||
- "2.1.5"
|
||||
|
||||
# Set the timezone for phantomjs with TZ
|
||||
# Set the timezone for karma with TIMEZONE
|
||||
#
|
||||
# The test cases are roughly split according to their test times.
|
||||
# It would be better to use https://github.com/ArturT/knapsack.
|
||||
env:
|
||||
global:
|
||||
- TZ="Australia/Melbourne"
|
||||
- TIMEZONE="Australia/Melbourne"
|
||||
matrix:
|
||||
- TEST_CASES="./spec/features/admin" GITHUB_DEPLOY="true"
|
||||
- TEST_CASES="./spec/features/consumer ./spec/serializers ./spec/performance"
|
||||
- TEST_CASES="./spec/models"
|
||||
- TEST_CASES="./spec/controllers ./spec/views ./spec/jobs"
|
||||
- TEST_CASES="./spec/requests ./spec/helpers ./spec/mailers ./spec/lib" KARMA="true"
|
||||
|
||||
before_script:
|
||||
- cp config/database.travis.yml config/database.yml
|
||||
- psql -c 'create database open_food_network_test;' -U postgres
|
||||
- cp config/application.yml.example config/application.yml
|
||||
- RAILS_ENV=test bundle exec rake db:create db:schema:load
|
||||
- >
|
||||
if [ "$KARMA" = "true" ]; then
|
||||
npm install karma@0.12.31
|
||||
npm install karma-jasmine@0.1.5
|
||||
npm install karma-phantomjs-launcher@0.1.4
|
||||
npm install karma-coffee-preprocessor@0.2.1
|
||||
npm install -g karma-cli@0.0.4
|
||||
fi
|
||||
|
||||
script:
|
||||
- RAILS_ENV=test bundle exec rake db:migrate --trace
|
||||
- bundle exec rake spec
|
||||
- '[ "$KARMA" = "true" ] && bundle exec rake karma:run || echo "Skipping karma run"'
|
||||
- "bundle exec rspec $TEST_CASES"
|
||||
|
||||
after_success:
|
||||
- >
|
||||
if [ "$GITHUB_DEPLOY" = "true" -a "$TRAVIS_PULL_REQUEST" = "false" -a -n "$TRAVIS_BRANCH" -a -n "$GITHUB_API_SECRET" ]; then
|
||||
description="`git show "$TRAVIS_BRANCH" -s --oneline --no-color`"
|
||||
data="{
|
||||
\"ref\":\"$TRAVIS_BRANCH\",
|
||||
\"description\":\"$description\",
|
||||
\"environment\":\"staging\",
|
||||
\"required_contexts\":[]}"
|
||||
curl -u "$GITHUB_API_SECRET" -d "$data" "https://api.github.com/repos/$TRAVIS_REPO_SLUG/deployments"
|
||||
else
|
||||
echo "Not deploying on this build."
|
||||
fi
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
33
CONTRIBUTING.md
Normal file
33
CONTRIBUTING.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Contributing
|
||||
|
||||
We love pull requests from everyone. Here are some instructions for
|
||||
contributing code to Open Food Network.
|
||||
|
||||
Fork, then clone the repo:
|
||||
|
||||
git clone git@github.com:your-username/openfoodnetwork.git
|
||||
|
||||
Follow the instructions in README.markdown to set up your machine.
|
||||
|
||||
Make sure the tests pass:
|
||||
|
||||
rspec spec
|
||||
|
||||
Make your change. Add tests for your change. Make the tests pass:
|
||||
|
||||
rspec spec
|
||||
|
||||
Push to your fork and [submit a pull request][pr].
|
||||
|
||||
[pr]: https://github.com/openfoodfoundation/openfoodnetwork/compare/
|
||||
|
||||
At this point you're waiting on us. We may suggest some changes or
|
||||
improvements or alternatives.
|
||||
|
||||
To increase the chance that your pull request is swiftly accepted:
|
||||
|
||||
* Write tests
|
||||
* Use a style consistent with the rest of the codebase
|
||||
* Before submitting, [rebase your work][rebase] on the current master branch
|
||||
|
||||
[rebase]: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/workflow-walkthrough
|
||||
12
Gemfile
12
Gemfile
@@ -1,10 +1,12 @@
|
||||
source 'https://rubygems.org'
|
||||
ruby "1.9.3"
|
||||
ruby "2.1.5"
|
||||
|
||||
gem 'rails', '3.2.21'
|
||||
gem 'rails-i18n', '~> 3.0.0'
|
||||
gem 'i18n', '~> 0.6.11'
|
||||
|
||||
gem 'nokogiri'
|
||||
|
||||
gem 'pg'
|
||||
gem 'spree', :github => 'openfoodfoundation/spree', :branch => '1-3-stable'
|
||||
gem 'spree_i18n', :github => 'spree/spree_i18n', :branch => '1-3-stable'
|
||||
@@ -52,6 +54,10 @@ gem 'roadie-rails', '~> 1.0.3'
|
||||
gem 'figaro'
|
||||
gem 'blockenspiel'
|
||||
gem 'acts-as-taggable-on', '~> 3.4'
|
||||
gem 'paper_trail', '~> 3.0.8'
|
||||
|
||||
gem 'wicked_pdf'
|
||||
gem 'wkhtmltopdf-binary'
|
||||
|
||||
gem 'foreigner'
|
||||
gem 'immigrant'
|
||||
@@ -91,7 +97,6 @@ group :test, :development do
|
||||
gem 'factory_girl_rails', :require => false
|
||||
gem 'capybara'
|
||||
gem 'database_cleaner', '0.7.1', :require => false
|
||||
gem 'simplecov', :require => false
|
||||
gem 'awesome_print'
|
||||
gem 'letter_opener'
|
||||
gem 'timecop'
|
||||
@@ -99,6 +104,7 @@ group :test, :development do
|
||||
gem 'rspec-retry'
|
||||
gem 'json_spec'
|
||||
gem 'unicorn-rails'
|
||||
gem 'atomic'
|
||||
end
|
||||
|
||||
group :test do
|
||||
@@ -109,7 +115,7 @@ group :test do
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'pry-debugger'
|
||||
gem 'pry-byebug'
|
||||
gem 'debugger-linecache'
|
||||
gem 'guard'
|
||||
gem 'guard-livereload'
|
||||
|
||||
186
Gemfile.lock
186
Gemfile.lock
@@ -107,6 +107,7 @@ GIT
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (2.3.2)
|
||||
actionmailer (3.2.21)
|
||||
actionpack (= 3.2.21)
|
||||
mail (~> 2.5.4)
|
||||
@@ -155,6 +156,7 @@ GEM
|
||||
angularjs-rails (1.2.13)
|
||||
ansi (1.4.2)
|
||||
arel (3.0.3)
|
||||
atomic (1.1.99)
|
||||
awesome_nested_set (2.1.5)
|
||||
activerecord (>= 3.0.0)
|
||||
awesome_print (1.0.2)
|
||||
@@ -170,8 +172,11 @@ GEM
|
||||
httparty (>= 0.6, < 1.0)
|
||||
multi_json (~> 1.0)
|
||||
builder (3.0.4)
|
||||
byebug (2.7.0)
|
||||
columnize (~> 0.3)
|
||||
debugger-linecache (~> 1.2)
|
||||
cancan (1.6.8)
|
||||
capybara (2.2.1)
|
||||
capybara (2.5.0)
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
@@ -190,12 +195,12 @@ GEM
|
||||
coffee-rails (3.2.2)
|
||||
coffee-script (>= 2.2.0)
|
||||
railties (~> 3.2.0)
|
||||
coffee-script (2.2.0)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.3.3)
|
||||
coffee-script-source (1.10.0)
|
||||
colorize (0.7.7)
|
||||
columnize (0.3.6)
|
||||
columnize (0.9.0)
|
||||
comfortable_mexican_sofa (1.6.24)
|
||||
active_link_to (~> 1.0.0)
|
||||
paperclip (>= 2.3.0)
|
||||
@@ -229,12 +234,7 @@ GEM
|
||||
activerecord (~> 3.0)
|
||||
fog (~> 1.0)
|
||||
rails (~> 3.0)
|
||||
debugger (1.6.1)
|
||||
columnize (>= 0.3.1)
|
||||
debugger-linecache (~> 1.2.0)
|
||||
debugger-ruby_core_source (~> 1.2.3)
|
||||
debugger-linecache (1.2.0)
|
||||
debugger-ruby_core_source (1.2.3)
|
||||
delayed_job (4.0.4)
|
||||
activesupport (>= 3.0, < 4.2)
|
||||
delayed_job_active_record (4.0.2)
|
||||
@@ -252,9 +252,9 @@ GEM
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0.5.3)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.0.3)
|
||||
excon (0.25.3)
|
||||
execjs (2.5.2)
|
||||
eventmachine (1.0.8)
|
||||
excon (0.45.4)
|
||||
execjs (2.6.0)
|
||||
factory_girl (3.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (3.3.0)
|
||||
@@ -265,19 +265,117 @@ GEM
|
||||
figaro (0.7.0)
|
||||
bundler (~> 1.0)
|
||||
rails (>= 3, < 5)
|
||||
fog (1.14.0)
|
||||
fission (0.5.0)
|
||||
CFPropertyList (~> 2.2)
|
||||
fog (1.36.0)
|
||||
fog-aliyun (>= 0.1.0)
|
||||
fog-atmos
|
||||
fog-aws (>= 0.6.0)
|
||||
fog-brightbox (~> 0.4)
|
||||
fog-core (~> 1.32)
|
||||
fog-dynect (~> 0.0.2)
|
||||
fog-ecloud (~> 0.1)
|
||||
fog-google (<= 0.1.0)
|
||||
fog-json
|
||||
fog-local
|
||||
fog-powerdns (>= 0.1.1)
|
||||
fog-profitbricks
|
||||
fog-radosgw (>= 0.0.2)
|
||||
fog-riakcs
|
||||
fog-sakuracloud (>= 0.0.4)
|
||||
fog-serverlove
|
||||
fog-softlayer
|
||||
fog-storm_on_demand
|
||||
fog-terremark
|
||||
fog-vmfusion
|
||||
fog-voxel
|
||||
fog-xenserver
|
||||
fog-xml (~> 0.1.1)
|
||||
ipaddress (~> 0.5)
|
||||
nokogiri (~> 1.5, >= 1.5.11)
|
||||
fog-aliyun (0.1.0)
|
||||
fog-core (~> 1.27)
|
||||
fog-json (~> 1.0)
|
||||
ipaddress (~> 0.8)
|
||||
xml-simple (~> 1.1)
|
||||
fog-atmos (0.1.0)
|
||||
fog-core
|
||||
fog-xml
|
||||
fog-aws (0.7.6)
|
||||
fog-core (~> 1.27)
|
||||
fog-json (~> 1.0)
|
||||
fog-xml (~> 0.1)
|
||||
ipaddress (~> 0.8)
|
||||
fog-brightbox (0.9.0)
|
||||
fog-core (~> 1.22)
|
||||
fog-json
|
||||
inflecto (~> 0.0.2)
|
||||
fog-core (1.35.0)
|
||||
builder
|
||||
excon (~> 0.25.0)
|
||||
formatador (~> 0.2.0)
|
||||
mime-types
|
||||
multi_json (~> 1.0)
|
||||
net-scp (~> 1.1)
|
||||
net-ssh (>= 2.1.3)
|
||||
nokogiri (~> 1.5)
|
||||
ruby-hmac
|
||||
excon (~> 0.45)
|
||||
formatador (~> 0.2)
|
||||
fog-dynect (0.0.2)
|
||||
fog-core
|
||||
fog-json
|
||||
fog-xml
|
||||
fog-ecloud (0.3.0)
|
||||
fog-core
|
||||
fog-xml
|
||||
fog-google (0.1.0)
|
||||
fog-core
|
||||
fog-json
|
||||
fog-xml
|
||||
fog-json (1.0.2)
|
||||
fog-core (~> 1.0)
|
||||
multi_json (~> 1.10)
|
||||
fog-local (0.2.1)
|
||||
fog-core (~> 1.27)
|
||||
fog-powerdns (0.1.1)
|
||||
fog-core (~> 1.27)
|
||||
fog-json (~> 1.0)
|
||||
fog-xml (~> 0.1)
|
||||
fog-profitbricks (0.0.5)
|
||||
fog-core
|
||||
fog-xml
|
||||
nokogiri
|
||||
fog-radosgw (0.0.4)
|
||||
fog-core (>= 1.21.0)
|
||||
fog-json
|
||||
fog-xml (>= 0.0.1)
|
||||
fog-riakcs (0.1.0)
|
||||
fog-core
|
||||
fog-json
|
||||
fog-xml
|
||||
fog-sakuracloud (1.4.0)
|
||||
fog-core
|
||||
fog-json
|
||||
fog-serverlove (0.1.2)
|
||||
fog-core
|
||||
fog-json
|
||||
fog-softlayer (1.0.2)
|
||||
fog-core
|
||||
fog-json
|
||||
fog-storm_on_demand (0.1.1)
|
||||
fog-core
|
||||
fog-json
|
||||
fog-terremark (0.1.0)
|
||||
fog-core
|
||||
fog-xml
|
||||
fog-vmfusion (0.1.0)
|
||||
fission
|
||||
fog-core
|
||||
fog-voxel (0.1.0)
|
||||
fog-core
|
||||
fog-xml
|
||||
fog-xenserver (0.2.2)
|
||||
fog-core
|
||||
fog-xml
|
||||
fog-xml (0.1.2)
|
||||
fog-core
|
||||
nokogiri (~> 1.5, >= 1.5.11)
|
||||
foreigner (1.6.1)
|
||||
activerecord (>= 3.0.0)
|
||||
formatador (0.2.4)
|
||||
formatador (0.2.5)
|
||||
foundation-icons-sass-rails (3.0.0)
|
||||
railties (>= 3.1.1)
|
||||
sass-rails (>= 3.1.1)
|
||||
@@ -319,6 +417,8 @@ GEM
|
||||
immigrant (0.1.6)
|
||||
activerecord (>= 3.0)
|
||||
foreigner (>= 1.2.1)
|
||||
inflecto (0.0.2)
|
||||
ipaddress (0.8.0)
|
||||
journey (1.0.4)
|
||||
jquery-rails (2.2.2)
|
||||
railties (>= 3.0, < 5.0)
|
||||
@@ -335,7 +435,7 @@ GEM
|
||||
addressable (~> 2.3)
|
||||
letter_opener (1.0.0)
|
||||
launchy (>= 2.0.4)
|
||||
libv8 (3.16.14.3)
|
||||
libv8 (3.16.14.11)
|
||||
listen (2.2.0)
|
||||
celluloid (>= 0.15.2)
|
||||
rb-fsevent (>= 0.9.3)
|
||||
@@ -351,16 +451,16 @@ GEM
|
||||
railties (>= 3.1)
|
||||
money (5.1.1)
|
||||
i18n (~> 0.6.0)
|
||||
multi_json (1.11.0)
|
||||
multi_json (1.11.2)
|
||||
multi_xml (0.5.5)
|
||||
net-scp (1.1.2)
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (2.6.8)
|
||||
newrelic_rpm (3.12.0.288)
|
||||
nokogiri (1.6.6.2)
|
||||
nokogiri (1.6.6.4)
|
||||
mini_portile (~> 0.6.0)
|
||||
oj (2.1.2)
|
||||
orm_adapter (0.5.0)
|
||||
paper_trail (3.0.8)
|
||||
activerecord (>= 3.0, < 5.0)
|
||||
activesupport (>= 3.0, < 5.0)
|
||||
paperclip (3.5.4)
|
||||
activemodel (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
@@ -375,7 +475,7 @@ GEM
|
||||
paypal-sdk-merchant (1.106.1)
|
||||
paypal-sdk-core (~> 0.2.3)
|
||||
pg (0.13.2)
|
||||
poltergeist (1.5.0)
|
||||
poltergeist (1.7.0)
|
||||
capybara (~> 2.1)
|
||||
cliver (~> 0.3.1)
|
||||
multi_json (~> 1.0)
|
||||
@@ -387,13 +487,13 @@ GEM
|
||||
coderay (~> 1.0.5)
|
||||
method_source (~> 0.8)
|
||||
slop (~> 3.4)
|
||||
pry-debugger (0.2.2)
|
||||
debugger (~> 1.3)
|
||||
pry (~> 0.9.10)
|
||||
pry-byebug (1.3.2)
|
||||
byebug (~> 2.7)
|
||||
pry (~> 0.9.12)
|
||||
rabl (0.7.2)
|
||||
activesupport (>= 2.3.14)
|
||||
multi_json (~> 1.0)
|
||||
rack (1.4.5)
|
||||
rack (1.4.7)
|
||||
rack-cache (1.2)
|
||||
rack (>= 0.4)
|
||||
rack-livereload (0.3.15)
|
||||
@@ -464,7 +564,6 @@ GEM
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rspec-retry (0.4.2)
|
||||
rspec-core
|
||||
ruby-hmac (0.4.0)
|
||||
ruby-progressbar (1.7.1)
|
||||
safe_yaml (0.9.5)
|
||||
sass (3.3.14)
|
||||
@@ -476,10 +575,6 @@ GEM
|
||||
thor (~> 0.14)
|
||||
shoulda-matchers (1.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
simplecov (0.7.1)
|
||||
multi_json (~> 1.0)
|
||||
simplecov-html (~> 0.7.1)
|
||||
simplecov-html (0.7.1)
|
||||
slop (3.4.5)
|
||||
spinjs-rails (1.3)
|
||||
rails (>= 3.1)
|
||||
@@ -527,10 +622,15 @@ GEM
|
||||
webmock (1.13.0)
|
||||
addressable (>= 2.2.7)
|
||||
crack (>= 0.3.2)
|
||||
websocket-driver (0.3.2)
|
||||
websocket-driver (0.6.2)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.2)
|
||||
whenever (0.9.2)
|
||||
activesupport (>= 2.3.4)
|
||||
chronic (>= 0.6.3)
|
||||
wicked_pdf (0.11.0)
|
||||
rails
|
||||
wkhtmltopdf-binary (0.9.9.3)
|
||||
xml-simple (1.1.4)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
@@ -547,6 +647,7 @@ DEPENDENCIES
|
||||
angular-rails-templates (~> 0.2.0)
|
||||
angularjs-file-upload-rails (~> 1.1.0)
|
||||
angularjs-rails (= 1.2.13)
|
||||
atomic
|
||||
awesome_print
|
||||
aws-sdk
|
||||
blockenspiel
|
||||
@@ -586,12 +687,14 @@ DEPENDENCIES
|
||||
letter_opener
|
||||
momentjs-rails
|
||||
newrelic_rpm
|
||||
nokogiri
|
||||
oj
|
||||
paper_trail (~> 3.0.8)
|
||||
paperclip
|
||||
parallel_tests
|
||||
pg
|
||||
poltergeist
|
||||
pry-debugger
|
||||
pry-byebug
|
||||
rabl
|
||||
rack-livereload
|
||||
rack-ssl
|
||||
@@ -606,7 +709,6 @@ DEPENDENCIES
|
||||
sass-rails (~> 3.2.3)
|
||||
shoulda-matchers
|
||||
simple_form!
|
||||
simplecov
|
||||
spinjs-rails
|
||||
spree!
|
||||
spree_auth_devise!
|
||||
@@ -622,3 +724,5 @@ DEPENDENCIES
|
||||
unicorn-rails
|
||||
webmock
|
||||
whenever
|
||||
wicked_pdf
|
||||
wkhtmltopdf-binary
|
||||
|
||||
@@ -20,7 +20,7 @@ Below are instructions for setting up a development environment for Open Food Ne
|
||||
## Dependencies
|
||||
|
||||
* Rails 3.2.x
|
||||
* Ruby 1.9.3
|
||||
* Ruby 2.1.5
|
||||
* PostgreSQL database
|
||||
* PhantomJS (for testing)
|
||||
* See Gemfile for a list of gems required
|
||||
@@ -44,7 +44,7 @@ You can download the source with the command:
|
||||
|
||||
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 >= 1.9.3 installed:
|
||||
First, check your dependencies: Ensure that you have Ruby 2.1.5 installed:
|
||||
|
||||
ruby --version
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
angular.module("admin.accounts_and_billing_settings", ["admin.utils"])
|
||||
@@ -0,0 +1,14 @@
|
||||
angular.module("admin.accounts_and_billing_settings").directive "methodSettingsFor", ->
|
||||
template: "<div ng-include='include_html'></div>"
|
||||
restrict: 'A'
|
||||
scope: {
|
||||
enterprise_id: '=methodSettingsFor'
|
||||
}
|
||||
link: (scope, element, attrs) ->
|
||||
scope.include_html = ""
|
||||
|
||||
scope.$watch "enterprise_id", (newVal, oldVal)->
|
||||
if !newVal? || newVal == ""
|
||||
scope.include_html = ""
|
||||
else
|
||||
scope.include_html = "/admin/accounts_and_billing_settings/show_methods?enterprise_id=#{newVal};"
|
||||
@@ -1,3 +1,3 @@
|
||||
angular.module("ofn.admin", ["ngResource", "ngAnimate", "admin.indexUtils", "admin.dropdown", "admin.products", "admin.taxons", "infinite-scroll"]).config ($httpProvider) ->
|
||||
angular.module("ofn.admin", ["ngResource", "ngAnimate", "admin.utils", "admin.indexUtils", "admin.dropdown", "admin.products", "admin.taxons", "infinite-scroll"]).config ($httpProvider) ->
|
||||
$httpProvider.defaults.headers.common["X-CSRF-Token"] = $("meta[name=csrf-token]").attr("content")
|
||||
$httpProvider.defaults.headers.common["Accept"] = "application/json, text/javascript, */*"
|
||||
|
||||
@@ -22,11 +22,16 @@
|
||||
//= require angular-rails-templates
|
||||
//= require_tree ../templates/admin
|
||||
//= require ./admin
|
||||
//= require ./accounts_and_billing_settings/accounts_and_billing_settings
|
||||
//= require ./business_model_configuration/business_model_configuration
|
||||
//= require ./customers/customers
|
||||
//= require ./dropdown/dropdown
|
||||
//= require ./enterprises/enterprises
|
||||
//= require ./enterprise_groups/enterprise_groups
|
||||
//= require ./index_utils/index_utils
|
||||
//= require ./line_items/line_items
|
||||
//= require ./orders/orders
|
||||
//= require ./order_cycles/order_cycles
|
||||
//= require ./payment_methods/payment_methods
|
||||
//= require ./products/products
|
||||
//= require ./shipping_methods/shipping_methods
|
||||
|
||||
@@ -11,7 +11,6 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
|
||||
$scope.confirmDelete = true
|
||||
$scope.startDate = formatDate start
|
||||
$scope.endDate = formatDate end
|
||||
$scope.pendingChanges = pendingChanges
|
||||
$scope.quickSearch = ""
|
||||
$scope.bulkActions = [ { name: "Delete Selected", callback: $scope.deleteLineItems } ]
|
||||
$scope.selectedBulkAction = $scope.bulkActions[0]
|
||||
@@ -77,6 +76,10 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
|
||||
line_item.checked = false
|
||||
line_item.supplier = $scope.matchObject $scope.suppliers, line_item.supplier, null
|
||||
line_item.order = orderWithoutLineItems
|
||||
line_item.original_final_weight_volume = line_item.final_weight_volume
|
||||
line_item.original_quantity = line_item.quantity
|
||||
line_item.original_price = line_item.price
|
||||
|
||||
lineItems.concat order.line_items
|
||||
, []
|
||||
|
||||
@@ -107,6 +110,12 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
|
||||
$scope.deleteLineItem lineItem for lineItem in lineItems when lineItem.checked
|
||||
$scope.confirmDelete = existingState
|
||||
|
||||
$scope.submit = ->
|
||||
if $scope.bulk_order_form.$valid
|
||||
pendingChanges.submitAll()
|
||||
else
|
||||
alert "Some errors must be resolved be before you can update orders.\nAny fields with red borders contain errors."
|
||||
|
||||
$scope.allBoxesChecked = ->
|
||||
checkedCount = $scope.filteredLineItems.reduce (count,lineItem) ->
|
||||
count + (if lineItem.checked then 1 else 0 )
|
||||
@@ -123,17 +132,17 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
|
||||
|
||||
$scope.sumUnitValues = ->
|
||||
sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
|
||||
sum = sum + lineItem.quantity * lineItem.units_variant.unit_value
|
||||
sum = sum + lineItem.final_weight_volume
|
||||
, 0
|
||||
|
||||
$scope.sumMaxUnitValues = ->
|
||||
sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
|
||||
sum = sum + Math.max(lineItem.max_quantity,lineItem.quantity) * lineItem.units_variant.unit_value
|
||||
sum = sum + Math.max(lineItem.max_quantity,lineItem.original_quantity) * lineItem.units_variant.unit_value
|
||||
, 0
|
||||
|
||||
$scope.allUnitValuesPresent = ->
|
||||
$scope.allFinalWeightVolumesPresent = ->
|
||||
for i,lineItem of $scope.filteredLineItems
|
||||
return false if !lineItem.units_variant.hasOwnProperty('unit_value') || !(lineItem.units_variant.unit_value > 0)
|
||||
return false if !lineItem.hasOwnProperty('final_weight_volume') || !(lineItem.final_weight_volume > 0)
|
||||
true
|
||||
|
||||
# How is this different to OptionValueNamer#name?
|
||||
@@ -164,13 +173,11 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
|
||||
$scope.orderCycleFilter = $scope.orderCycles[0].id
|
||||
$scope.quickSearch = ""
|
||||
|
||||
$scope.weightAdjustedPrice = (lineItem, oldValue) ->
|
||||
if oldValue <= 0
|
||||
oldValue = lineItem.units_variant.unit_value * line_item.quantity
|
||||
if lineItem.final_weight_volume <= 0
|
||||
lineItem.final_weight_volume = lineItem.units_variant.unit_value * lineItem.quantity
|
||||
lineItem.price = lineItem.price * lineItem.final_weight_volume / oldValue
|
||||
#$scope.bulk_order_form.line_item.price.$setViewValue($scope.bulk_order_form.line_item.price.$viewValue)
|
||||
$scope.weightAdjustedPrice = (lineItem) ->
|
||||
if lineItem.final_weight_volume > 0
|
||||
unit_value = lineItem.final_weight_volume / lineItem.quantity
|
||||
original_unit_value = lineItem.original_final_weight_volume / lineItem.original_quantity
|
||||
lineItem.price = lineItem.original_price * (unit_value / original_unit_value)
|
||||
|
||||
$scope.unitValueLessThanZero = (lineItem) ->
|
||||
if lineItem.units_variant.unit_value <= 0
|
||||
@@ -178,12 +185,10 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
|
||||
else
|
||||
false
|
||||
|
||||
$scope.updateOnQuantity = (lineItem, oldQuantity) ->
|
||||
if lineItem.quantity <= 0
|
||||
lineItem.quantity = 1
|
||||
# reset price to original unit value
|
||||
lineItem.price = lineItem.price * (oldQuantity * lineItem.units_variant.unit_value) / lineItem.final_weight_volume
|
||||
lineItem.final_weight_volume = lineItem.units_variant.unit_value * lineItem.quantity
|
||||
$scope.updateOnQuantity = (lineItem) ->
|
||||
if lineItem.quantity > 0
|
||||
lineItem.final_weight_volume = lineItem.original_final_weight_volume * lineItem.quantity / lineItem.original_quantity
|
||||
$scope.weightAdjustedPrice(lineItem)
|
||||
|
||||
$scope.$watch "orderCycleFilter", (newVal, oldVal) ->
|
||||
unless $scope.orderCycleFilter == "0" || angular.equals(newVal, oldVal)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
angular.module("admin.businessModelConfiguration", ["admin.utils"])
|
||||
@@ -0,0 +1,21 @@
|
||||
angular.module("admin.businessModelConfiguration").controller "BusinessModelConfigCtrl", ($scope, $filter) ->
|
||||
$scope.turnover = 1000
|
||||
|
||||
$scope.bill = ->
|
||||
return $filter('currency')(0) unless $scope.fixed || $scope.rate
|
||||
Number($scope.fixed) + Number($scope.turnover) * Number($scope.rate)
|
||||
|
||||
$scope.cappedBill = ->
|
||||
return $scope.bill() if !$scope.cap? || Number($scope.cap) == 0
|
||||
Math.min($scope.bill(), Number($scope.cap))
|
||||
|
||||
$scope.capReached = ->
|
||||
return "No" if !$scope.cap? || Number($scope.cap) == 0
|
||||
if $scope.bill() >= Number($scope.cap) then "Yes" else "No"
|
||||
|
||||
$scope.includedTax = ->
|
||||
return 0 if !$scope.taxRate? || Number($scope.taxRate) == 0
|
||||
($scope.cappedBill() * Number($scope.taxRate))
|
||||
|
||||
$scope.total = ->
|
||||
$scope.cappedBill() + $scope.includedTax()
|
||||
@@ -1,7 +0,0 @@
|
||||
angular.module("ofn.admin").directive "ofnConfirmLinkPath", (ofnConfirmHandler) ->
|
||||
restrict: "A"
|
||||
scope:
|
||||
path: "@ofnConfirmLinkPath"
|
||||
link: (scope, element, attrs) ->
|
||||
element.click ofnConfirmHandler scope, ->
|
||||
window.location = scope.path
|
||||
@@ -1,6 +0,0 @@
|
||||
angular.module("ofn.admin").directive "ofnConfirmModelChange", (ofnConfirmHandler,$timeout) ->
|
||||
restrict: "A"
|
||||
link: (scope, element, attrs) ->
|
||||
handler = ofnConfirmHandler scope, -> scope.fetchOrders()
|
||||
scope.$watch attrs.ngModel, (oldValue,newValue) ->
|
||||
handler() unless oldValue == undefined || newValue == oldValue
|
||||
@@ -0,0 +1,5 @@
|
||||
angular.module("admin.dropdown").directive "linksDropdown", ($window)->
|
||||
restrict: "C"
|
||||
scope:
|
||||
links: "="
|
||||
templateUrl: "admin/links_dropdown.html"
|
||||
@@ -1 +1 @@
|
||||
angular.module("admin.dropdown", [])
|
||||
angular.module("admin.dropdown", ['templates'])
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
angular.module("admin.enterprises").controller 'enterprisesCtrl', ($scope, Enterprises, Columns) ->
|
||||
Enterprises.loaded = false
|
||||
$scope.allEnterprises = Enterprises.index()
|
||||
angular.module("admin.enterprises").controller 'enterprisesCtrl', ($scope, $q, Enterprises, Columns) ->
|
||||
requests = []
|
||||
requests.push ($scope.allEnterprises = Enterprises.index(ams_prefix: "index")).$promise
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprises.loaded
|
||||
$q.all(requests).then ->
|
||||
$scope.loaded = true
|
||||
|
||||
$scope.columns = Columns.setColumns
|
||||
name: { name: "Name", visible: true }
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
angular.module("admin.enterprises").directive "monthlyPricingDescription", (monthlyBillDescription) ->
|
||||
restrict: 'E'
|
||||
scope:
|
||||
joiner: "@"
|
||||
template: "<span ng-bind-html='billDescription'></span>"
|
||||
link: (scope, element, attrs) ->
|
||||
joiners = { comma: ", ", newline: "<br>" }
|
||||
scope.billDescription = monthlyBillDescription.replace("{joiner}", joiners[scope.joiner])
|
||||
@@ -1,5 +1,5 @@
|
||||
angular.module("admin.enterprises").factory 'EnterpriseResource', ($resource) ->
|
||||
$resource('/admin/enterprises/:id.json', {}, {
|
||||
$resource('/admin/enterprises/:id/:action.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
angular.module("admin.enterprises").factory 'Enterprises', ($q, EnterpriseResource) ->
|
||||
angular.module("admin.enterprises").factory 'Enterprises', ($q, EnterpriseResource, blankOption) ->
|
||||
new class Enterprises
|
||||
enterprises: []
|
||||
enterprises_by_id: {}
|
||||
pristine_by_id: {}
|
||||
loaded: false
|
||||
enterprisesByID: {}
|
||||
pristineByID: {}
|
||||
|
||||
index: (params={}, callback=null) ->
|
||||
EnterpriseResource.index params, (data) =>
|
||||
includeBlank = !!params['includeBlank']
|
||||
delete params['includeBlank']
|
||||
EnterpriseResource.index(params, (data) =>
|
||||
for enterprise in data
|
||||
@enterprises.push enterprise
|
||||
@pristine_by_id[enterprise.id] = angular.copy(enterprise)
|
||||
@enterprisesByID[enterprise.id] = enterprise
|
||||
@pristineByID[enterprise.id] = angular.copy(enterprise)
|
||||
|
||||
@loaded = true
|
||||
(callback || angular.noop)(@enterprises)
|
||||
(callback || angular.noop)(data)
|
||||
|
||||
@enterprises
|
||||
data.unshift(blankOption()) if includeBlank
|
||||
data
|
||||
)
|
||||
|
||||
save: (enterprise) ->
|
||||
deferred = $q.defer()
|
||||
enterprise.$update({id: enterprise.permalink})
|
||||
.then( (data) =>
|
||||
@pristine_by_id[enterprise.id] = angular.copy(enterprise)
|
||||
@pristineByID[enterprise.id] = angular.copy(enterprise)
|
||||
deferred.resolve(data)
|
||||
).catch (response) ->
|
||||
deferred.reject(response)
|
||||
@@ -31,9 +32,9 @@ angular.module("admin.enterprises").factory 'Enterprises', ($q, EnterpriseResour
|
||||
|
||||
diff: (enterprise) ->
|
||||
changed = []
|
||||
for attr, value of enterprise when not angular.equals(value, @pristine_by_id[enterprise.id][attr])
|
||||
for attr, value of enterprise when not angular.equals(value, @pristineByID[enterprise.id][attr])
|
||||
changed.push attr unless attr is "$$hashKey"
|
||||
changed
|
||||
|
||||
resetAttribute: (enterprise, attribute) ->
|
||||
enterprise[attribute] = @pristine_by_id[enterprise.id][attribute]
|
||||
enterprise[attribute] = @pristineByID[enterprise.id][attribute]
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
angular.module("ofn.admin").filter "selectFilter", (blankOption) ->
|
||||
return (lineItems,selectedSupplier,selectedDistributor,selectedOrderCycle) ->
|
||||
filtered = []
|
||||
filtered.push lineItem for lineItem in lineItems when (angular.equals(selectedSupplier,"0") || lineItem.supplier.id == selectedSupplier) &&
|
||||
(angular.equals(selectedDistributor,"0") || lineItem.order.distributor.id == selectedDistributor) &&
|
||||
(angular.equals(selectedOrderCycle,"0") || lineItem.order.order_cycle.id == selectedOrderCycle)
|
||||
filtered
|
||||
@@ -0,0 +1,9 @@
|
||||
angular.module("admin.indexUtils").directive "datepicker", ->
|
||||
require: "ngModel"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
element.datepicker
|
||||
dateFormat: "yy-mm-dd"
|
||||
onSelect: (dateText, inst) ->
|
||||
scope.$apply (scope) ->
|
||||
# Fires ngModel.$parsers
|
||||
ngModel.$setViewValue dateText
|
||||
@@ -0,0 +1,6 @@
|
||||
angular.module("admin.indexUtils").directive "ignoreDirty", ->
|
||||
restrict: 'A'
|
||||
require: 'ngModel'
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
#TODO: This is broken, requires AngularJS > 1.3
|
||||
ngModel.$setDirty = angular.noop
|
||||
@@ -0,0 +1,7 @@
|
||||
angular.module("admin.indexUtils").directive "saveBar", ->
|
||||
restrict: "E"
|
||||
scope:
|
||||
save: "&"
|
||||
saving: "&"
|
||||
dirty: "&"
|
||||
templateUrl: "admin/save_bar.html"
|
||||
@@ -0,0 +1,9 @@
|
||||
angular.module("admin.indexUtils").directive "select2MinSearch", ($timeout) ->
|
||||
require: 'ngModel'
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
element.select2
|
||||
minimumResultsForSearch: attrs.select2MinSearch
|
||||
|
||||
ngModel.$formatters.push (value) ->
|
||||
element.select2('val', value)
|
||||
value
|
||||
@@ -0,0 +1,11 @@
|
||||
angular.module("admin.indexUtils").factory 'Dereferencer', ->
|
||||
new class Dereferencer
|
||||
dereference: (array, data)->
|
||||
if array
|
||||
for object, i in array
|
||||
array[i] = data[object.id]
|
||||
|
||||
dereferenceAttr: (array, attr, data)->
|
||||
if array
|
||||
for object in array
|
||||
object[attr] = data[object[attr].id] unless object[attr] == null
|
||||
@@ -0,0 +1,11 @@
|
||||
angular.module("admin.indexUtils").factory 'RequestMonitor', ($q) ->
|
||||
new class RequestMonitor
|
||||
loadQueue: $q.when([])
|
||||
loadId: 0
|
||||
loading: false
|
||||
|
||||
load: (promise) ->
|
||||
loadId = (@loadId += 1)
|
||||
@loading = true
|
||||
@loadQueue = $q.all([@loadQueue, promise]).then =>
|
||||
@loading = false if @loadId == loadId
|
||||
@@ -0,0 +1,181 @@
|
||||
angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $http, $q, Columns, Dereferencer, Orders, LineItems, Enterprises, OrderCycles, blankOption, VariantUnitManager, RequestMonitor) ->
|
||||
$scope.initialized = false
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.saving = false
|
||||
$scope.filteredLineItems = []
|
||||
$scope.confirmDelete = true
|
||||
$scope.startDate = formatDate daysFromToday -7
|
||||
$scope.endDate = formatDate daysFromToday 1
|
||||
$scope.bulkActions = [ { name: "Delete Selected", callback: 'deleteLineItems' } ]
|
||||
$scope.selectedUnitsProduct = {};
|
||||
$scope.selectedUnitsVariant = {};
|
||||
$scope.sharedResource = false
|
||||
$scope.columns = Columns.setColumns
|
||||
order_no: { name: "Order No.", visible: false }
|
||||
full_name: { name: "Name", visible: true }
|
||||
email: { name: "Email", visible: false }
|
||||
phone: { name: "Phone", visible: false }
|
||||
order_date: { name: "Order Date", visible: true }
|
||||
producer: { name: "Producer", visible: true }
|
||||
order_cycle: { name: "Order Cycle", visible: false }
|
||||
hub: { name: "Hub", visible: false }
|
||||
variant: { name: "Variant", visible: true }
|
||||
quantity: { name: "Quantity", visible: true }
|
||||
max: { name: "Max", visible: true }
|
||||
final_weight_volume: { name: "Weight/Volume", visible: false }
|
||||
price: { name: "Price", visible: false }
|
||||
|
||||
$scope.confirmRefresh = ->
|
||||
LineItems.allSaved() || confirm("Unsaved changes exist and will be lost if you continue.")
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.distributorFilter = blankOption().id
|
||||
$scope.supplierFilter = blankOption().id
|
||||
$scope.orderCycleFilter = blankOption().id
|
||||
$scope.quickSearch = ""
|
||||
|
||||
$scope.refreshData = ->
|
||||
unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == "0"
|
||||
$scope.startDate = OrderCycles.orderCyclesByID[$scope.orderCycleFilter].first_order
|
||||
$scope.endDate = OrderCycles.orderCyclesByID[$scope.orderCycleFilter].last_order
|
||||
|
||||
RequestMonitor.load $scope.orders = Orders.index("q[state_not_eq]": "canceled", "q[completed_at_not_null]": "true", "q[completed_at_gt]": "#{parseDate($scope.startDate)}", "q[completed_at_lt]": "#{parseDate($scope.endDate)}")
|
||||
RequestMonitor.load $scope.lineItems = LineItems.index("q[order][state_not_eq]": "canceled", "q[order][completed_at_not_null]": "true", "q[order][completed_at_gt]": "#{parseDate($scope.startDate)}", "q[order][completed_at_lt]": "#{parseDate($scope.endDate)}")
|
||||
|
||||
unless $scope.initialized
|
||||
RequestMonitor.load $scope.distributors = Enterprises.index(includeBlank: true, action: "for_line_items", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
|
||||
RequestMonitor.load $scope.orderCycles = OrderCycles.index(includeBlank: true, ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{daysFromToday(-90)}")
|
||||
RequestMonitor.load $scope.suppliers = Enterprises.index(includeBlank: true, action: "for_line_items", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
|
||||
|
||||
RequestMonitor.load $q.all([$scope.orders.$promise, $scope.distributors.$promise, $scope.orderCycles.$promise]).then ->
|
||||
Dereferencer.dereferenceAttr $scope.orders, "distributor", Enterprises.enterprisesByID
|
||||
Dereferencer.dereferenceAttr $scope.orders, "order_cycle", OrderCycles.orderCyclesByID
|
||||
|
||||
RequestMonitor.load $q.all([$scope.orders.$promise, $scope.suppliers.$promise, $scope.lineItems.$promise]).then ->
|
||||
Dereferencer.dereferenceAttr $scope.lineItems, "supplier", Enterprises.enterprisesByID
|
||||
Dereferencer.dereferenceAttr $scope.lineItems, "order", Orders.ordersByID
|
||||
$scope.bulk_order_form.$setPristine()
|
||||
unless $scope.initialized
|
||||
$scope.initialized = true
|
||||
$timeout ->
|
||||
$scope.resetSelectFilters()
|
||||
|
||||
$scope.refreshData()
|
||||
|
||||
$scope.submit = =>
|
||||
if $scope.bulk_order_form.$valid
|
||||
$scope.saving = true
|
||||
$q.all(LineItems.saveAll()).then(->
|
||||
$scope.bulk_order_form.$setPristine()
|
||||
$scope.saving = false
|
||||
).catch ->
|
||||
alert "Some errors must be resolved be before you can update orders.\nAny fields with red borders contain errors."
|
||||
else
|
||||
alert "Some errors must be resolved be before you can update orders.\nAny fields with red borders contain errors."
|
||||
|
||||
$scope.deleteLineItem = (lineItem) ->
|
||||
if ($scope.confirmDelete && confirm("Are you sure?")) || !$scope.confirmDelete
|
||||
LineItems.delete lineItem, =>
|
||||
$scope.lineItems.splice $scope.lineItems.indexOf(lineItem), 1
|
||||
|
||||
$scope.deleteLineItems = (lineItems) ->
|
||||
existingState = $scope.confirmDelete
|
||||
$scope.confirmDelete = false
|
||||
$scope.deleteLineItem lineItem for lineItem in lineItems when lineItem.checked
|
||||
$scope.confirmDelete = existingState
|
||||
|
||||
$scope.allBoxesChecked = ->
|
||||
checkedCount = $scope.filteredLineItems.reduce (count,lineItem) ->
|
||||
count + (if lineItem.checked then 1 else 0 )
|
||||
, 0
|
||||
checkedCount == $scope.filteredLineItems.length
|
||||
|
||||
$scope.toggleAllCheckboxes = ->
|
||||
changeTo = !$scope.allBoxesChecked()
|
||||
lineItem.checked = changeTo for lineItem in $scope.filteredLineItems
|
||||
|
||||
$scope.setSelectedUnitsVariant = (unitsProduct,unitsVariant) ->
|
||||
$scope.selectedUnitsProduct = unitsProduct
|
||||
$scope.selectedUnitsVariant = unitsVariant
|
||||
|
||||
$scope.sumUnitValues = ->
|
||||
sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
|
||||
sum + lineItem.final_weight_volume
|
||||
, 0
|
||||
|
||||
$scope.sumMaxUnitValues = ->
|
||||
sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
|
||||
sum + lineItem.max_quantity * lineItem.units_variant.unit_value
|
||||
, 0
|
||||
|
||||
$scope.allFinalWeightVolumesPresent = ->
|
||||
for i,lineItem of $scope.filteredLineItems
|
||||
return false if !lineItem.hasOwnProperty('final_weight_volume') || !(lineItem.final_weight_volume > 0)
|
||||
true
|
||||
|
||||
# How is this different to OptionValueNamer#name?
|
||||
# Should it be extracted to that class or VariantUnitManager?
|
||||
$scope.formattedValueWithUnitName = (value, unitsProduct, unitsVariant) ->
|
||||
# A Units Variant is an API object which holds unit properies of a variant
|
||||
if unitsProduct.hasOwnProperty("variant_unit") && (unitsProduct.variant_unit == "weight" || unitsProduct.variant_unit == "volume") && value > 0
|
||||
scale = VariantUnitManager.getScale(value, unitsProduct.variant_unit)
|
||||
Math.round(value/scale * 1000)/1000 + " " + VariantUnitManager.getUnitName(scale, unitsProduct.variant_unit)
|
||||
else
|
||||
''
|
||||
|
||||
$scope.fulfilled = (sumOfUnitValues) ->
|
||||
# A Units Variant is an API object which holds unit properies of a variant
|
||||
if $scope.selectedUnitsProduct.hasOwnProperty("group_buy_unit_size") && $scope.selectedUnitsProduct.group_buy_unit_size > 0 &&
|
||||
$scope.selectedUnitsProduct.hasOwnProperty("variant_unit") &&
|
||||
( $scope.selectedUnitsProduct.variant_unit == "weight" || $scope.selectedUnitsProduct.variant_unit == "volume" )
|
||||
Math.round( sumOfUnitValues / $scope.selectedUnitsProduct.group_buy_unit_size * 1000)/1000
|
||||
else
|
||||
''
|
||||
|
||||
$scope.unitsVariantSelected = ->
|
||||
!angular.equals($scope.selectedUnitsVariant,{})
|
||||
|
||||
$scope.weightAdjustedPrice = (lineItem) ->
|
||||
if lineItem.final_weight_volume > 0
|
||||
unit_value = lineItem.final_weight_volume / lineItem.quantity
|
||||
pristine_unit_value = LineItems.pristineByID[lineItem.id].final_weight_volume / LineItems.pristineByID[lineItem.id].quantity
|
||||
lineItem.price = LineItems.pristineByID[lineItem.id].price * (unit_value / pristine_unit_value)
|
||||
|
||||
$scope.unitValueLessThanZero = (lineItem) ->
|
||||
if lineItem.units_variant.unit_value <= 0
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
$scope.updateOnQuantity = (lineItem) ->
|
||||
if lineItem.quantity > 0
|
||||
lineItem.final_weight_volume = LineItems.pristineByID[lineItem.id].final_weight_volume * lineItem.quantity / LineItems.pristineByID[lineItem.id].quantity
|
||||
$scope.weightAdjustedPrice(lineItem)
|
||||
|
||||
daysFromToday = (days) ->
|
||||
now = new Date
|
||||
now.setHours(0)
|
||||
now.setMinutes(0)
|
||||
now.setSeconds(0)
|
||||
now.setDate( now.getDate() + days )
|
||||
now
|
||||
|
||||
formatDate = (date) ->
|
||||
year = date.getFullYear()
|
||||
month = twoDigitNumber date.getMonth() + 1
|
||||
day = twoDigitNumber date.getDate()
|
||||
return year + "-" + month + "-" + day
|
||||
|
||||
formatTime = (date) ->
|
||||
hours = twoDigitNumber date.getHours()
|
||||
mins = twoDigitNumber date.getMinutes()
|
||||
secs = twoDigitNumber date.getSeconds()
|
||||
return hours + ":" + mins + ":" + secs
|
||||
|
||||
parseDate = (dateString) ->
|
||||
new Date(Date.parse(dateString))
|
||||
|
||||
twoDigitNumber = (number) ->
|
||||
twoDigits = "" + number
|
||||
twoDigits = ("0" + number) if number < 10
|
||||
twoDigits
|
||||
@@ -0,0 +1,19 @@
|
||||
# Used with the ngChange directive to prevent updates to the relevant model unless a callback returns true
|
||||
angular.module("admin.lineItems").directive "confirmChange", ->
|
||||
restrict: "A"
|
||||
require: 'ngModel'
|
||||
scope:
|
||||
confirmChange: "&"
|
||||
link: (scope, element, attrs, ngModel) ->
|
||||
valid = null
|
||||
|
||||
ngModel.$parsers.push (val) =>
|
||||
return val if val == valid
|
||||
if scope.confirmChange()
|
||||
# ngModel is changed, triggers ngChange callback
|
||||
return valid = val
|
||||
else
|
||||
valid = ngModel.$modelValue
|
||||
ngModel.$setViewValue(valid)
|
||||
ngModel.$render()
|
||||
return valid
|
||||
@@ -0,0 +1,9 @@
|
||||
# Used on a link to prevent link clicks unless a callback returns true (probably asking for user confirmation)
|
||||
angular.module("admin.lineItems").directive "confirmLinkClick", ->
|
||||
restrict: "A"
|
||||
scope:
|
||||
confirmLinkClick: "&"
|
||||
link: (scope, element, attrs) ->
|
||||
element.bind "click", (event) ->
|
||||
unless scope.confirmLinkClick()
|
||||
event.preventDefault()
|
||||
@@ -0,0 +1,8 @@
|
||||
angular.module("admin.lineItems").filter "selectFilter", (blankOption, RequestMonitor) ->
|
||||
return (lineItems,selectedSupplier,selectedDistributor,selectedOrderCycle) ->
|
||||
filtered = []
|
||||
unless RequestMonitor.loading
|
||||
filtered.push lineItem for lineItem in lineItems when (angular.equals(selectedSupplier,"0") || lineItem.supplier.id == selectedSupplier) &&
|
||||
(angular.equals(selectedDistributor,"0") || lineItem.order.distributor.id == selectedDistributor) &&
|
||||
(angular.equals(selectedOrderCycle,"0") || lineItem.order.order_cycle.id == selectedOrderCycle)
|
||||
filtered
|
||||
@@ -1,6 +1,6 @@
|
||||
angular.module("ofn.admin").filter "variantFilter", ->
|
||||
angular.module("admin.lineItems").filter "variantFilter", ->
|
||||
return (lineItems,selectedUnitsProduct,selectedUnitsVariant,sharedResource) ->
|
||||
filtered = []
|
||||
filtered.push lineItem for lineItem in lineItems when (angular.equals(selectedUnitsProduct,{}) ||
|
||||
(lineItem.units_product.id == selectedUnitsProduct.id && (sharedResource || lineItem.units_variant.id == selectedUnitsVariant.id ) ) )
|
||||
filtered
|
||||
filtered
|
||||
@@ -0,0 +1 @@
|
||||
angular.module("admin.lineItems", ["admin.indexUtils", "admin.products", "admin.orders", "admin.enterprises", "admin.orderCycles"])
|
||||
@@ -0,0 +1,12 @@
|
||||
angular.module("admin.lineItems").factory 'LineItemResource', ($resource) ->
|
||||
$resource('/admin/:orders/:order_number/line_items/:id.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
'update':
|
||||
method: 'PUT'
|
||||
transformRequest: (data, headersGetter) =>
|
||||
line_item = {}
|
||||
line_item[attr] = data[attr] for attr in ["price", "quantity", "final_weight_volume"]
|
||||
angular.toJson(line_item: line_item)
|
||||
})
|
||||
@@ -0,0 +1,63 @@
|
||||
angular.module("admin.lineItems").factory 'LineItems', ($q, LineItemResource) ->
|
||||
new class LineItems
|
||||
lineItemsByID: {}
|
||||
pristineByID: {}
|
||||
|
||||
index: (params={}, callback=null) ->
|
||||
LineItemResource.index params, (data) =>
|
||||
@resetData()
|
||||
for lineItem in data
|
||||
@lineItemsByID[lineItem.id] = lineItem
|
||||
@pristineByID[lineItem.id] = angular.copy(lineItem)
|
||||
|
||||
(callback || angular.noop)(data)
|
||||
|
||||
resetData: ->
|
||||
@lineItemsByID = {}
|
||||
@pristineByID = {}
|
||||
|
||||
saveAll: ->
|
||||
for id, lineItem of @lineItemsByID
|
||||
lineItem.errors = {} # removes errors when line_item has been returned to original state
|
||||
@save(lineItem) if !@isSaved(lineItem)
|
||||
|
||||
save: (lineItem) ->
|
||||
deferred = $q.defer()
|
||||
lineItem.errors = {}
|
||||
lineItem.$update({id: lineItem.id, orders: "orders", order_number: lineItem.order.number})
|
||||
.then( (data) =>
|
||||
@pristineByID[lineItem.id] = angular.copy(lineItem)
|
||||
deferred.resolve(data)
|
||||
).catch (response) ->
|
||||
lineItem.errors = response.data.errors if response.data.errors?
|
||||
deferred.reject(response)
|
||||
deferred.promise
|
||||
|
||||
allSaved: ->
|
||||
for id, lineItem of @lineItemsByID
|
||||
return false unless @isSaved(lineItem)
|
||||
true
|
||||
|
||||
isSaved: (lineItem) ->
|
||||
@diff(lineItem).length == 0
|
||||
|
||||
diff: (lineItem) ->
|
||||
changed = []
|
||||
for attr, value of lineItem when not angular.equals(value, @pristineByID[lineItem.id][attr])
|
||||
changed.push attr if attr in ["price", "quantity", "final_weight_volume"]
|
||||
changed
|
||||
|
||||
resetAttribute: (lineItem, attribute) ->
|
||||
lineItem[attribute] = @pristineByID[lineItem.id][attribute]
|
||||
|
||||
delete: (lineItem, callback=null) ->
|
||||
deferred = $q.defer()
|
||||
lineItem.$delete({id: lineItem.id, orders: "orders", order_number: lineItem.order.number})
|
||||
.then( (data) =>
|
||||
delete @lineItemsByID[lineItem.id]
|
||||
delete @pristineByID[lineItem.id]
|
||||
(callback || angular.noop)(data)
|
||||
deferred.resolve(data)
|
||||
).catch (response) ->
|
||||
deferred.reject(response)
|
||||
deferred.promise
|
||||
@@ -1,11 +1,16 @@
|
||||
angular.module('admin.order_cycles', ['ngResource'])
|
||||
.controller('AdminCreateOrderCycleCtrl', ['$scope', '$filter', 'OrderCycle', 'Enterprise', 'EnterpriseFee', 'ocInstance', ($scope, $filter, OrderCycle, Enterprise, EnterpriseFee, ocInstance) ->
|
||||
angular.module('admin.orderCycles', ['ngResource', 'admin.utils'])
|
||||
.controller('AdminCreateOrderCycleCtrl', ['$scope', '$filter', 'OrderCycle', 'Enterprise', 'EnterpriseFee', 'ocInstance', 'StatusMessage', ($scope, $filter, OrderCycle, Enterprise, EnterpriseFee, ocInstance, StatusMessage) ->
|
||||
$scope.enterprises = Enterprise.index(coordinator_id: ocInstance.coordinator_id)
|
||||
$scope.supplier_enterprises = Enterprise.producer_enterprises
|
||||
$scope.distributor_enterprises = Enterprise.hub_enterprises
|
||||
$scope.supplied_products = Enterprise.supplied_products
|
||||
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
|
||||
|
||||
$scope.OrderCycle = OrderCycle
|
||||
$scope.order_cycle = OrderCycle.new({ coordinator_id: ocInstance.coordinator_id})
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded
|
||||
|
||||
@@ -74,19 +79,23 @@ angular.module('admin.order_cycles', ['ngResource'])
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = (event) ->
|
||||
event.preventDefault()
|
||||
OrderCycle.create()
|
||||
$scope.submit = (destination) ->
|
||||
OrderCycle.create(destination)
|
||||
])
|
||||
|
||||
.controller('AdminEditOrderCycleCtrl', ['$scope', '$filter', '$location', 'OrderCycle', 'Enterprise', 'EnterpriseFee', ($scope, $filter, $location, OrderCycle, Enterprise, EnterpriseFee) ->
|
||||
.controller('AdminEditOrderCycleCtrl', ['$scope', '$filter', '$location', 'OrderCycle', 'Enterprise', 'EnterpriseFee', 'StatusMessage', ($scope, $filter, $location, OrderCycle, Enterprise, EnterpriseFee, StatusMessage) ->
|
||||
order_cycle_id = $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
|
||||
$scope.enterprises = Enterprise.index(order_cycle_id: order_cycle_id)
|
||||
$scope.supplier_enterprises = Enterprise.producer_enterprises
|
||||
$scope.distributor_enterprises = Enterprise.hub_enterprises
|
||||
$scope.supplied_products = Enterprise.supplied_products
|
||||
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: order_cycle_id)
|
||||
|
||||
$scope.OrderCycle = OrderCycle
|
||||
$scope.order_cycle = OrderCycle.load(order_cycle_id)
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
|
||||
|
||||
@@ -155,9 +164,8 @@ angular.module('admin.order_cycles', ['ngResource'])
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = (event) ->
|
||||
event.preventDefault()
|
||||
OrderCycle.update()
|
||||
$scope.submit = (destination) ->
|
||||
OrderCycle.update(destination)
|
||||
])
|
||||
|
||||
.config(['$httpProvider', ($httpProvider) ->
|
||||
@@ -1,4 +1,6 @@
|
||||
angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, OrderCycle, Enterprise, EnterpriseFee, ocInstance) ->
|
||||
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, ocInstance) ->
|
||||
$scope.StatusMessage = StatusMessage
|
||||
$scope.OrderCycle = OrderCycle
|
||||
$scope.order_cycle = OrderCycle.new {coordinator_id: ocInstance.coordinator_id}, =>
|
||||
# TODO: make this a get method, which only fetches one enterprise
|
||||
$scope.enterprises = Enterprise.index {coordinator_id: ocInstance.coordinator_id}, (enterprises) =>
|
||||
@@ -39,7 +41,6 @@ angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl
|
||||
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
|
||||
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
|
||||
|
||||
$scope.submit = (event) ->
|
||||
event.preventDefault()
|
||||
$scope.submit = (destination) ->
|
||||
OrderCycle.mirrorIncomingToOutgoingProducts()
|
||||
OrderCycle.create()
|
||||
OrderCycle.create(destination)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
angular.module('admin.order_cycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, OrderCycle, Enterprise, EnterpriseFee) ->
|
||||
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, OrderCycle, Enterprise, EnterpriseFee, StatusMessage) ->
|
||||
$scope.orderCycleId = ->
|
||||
$location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
|
||||
|
||||
$scope.StatusMessage = StatusMessage
|
||||
$scope.enterprises = Enterprise.index(order_cycle_id: $scope.orderCycleId())
|
||||
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: $scope.orderCycleId())
|
||||
$scope.OrderCycle = OrderCycle
|
||||
$scope.order_cycle = OrderCycle.load $scope.orderCycleId(), (order_cycle) =>
|
||||
$scope.init()
|
||||
|
||||
@@ -32,7 +34,6 @@ angular.module('admin.order_cycles').controller "AdminSimpleEditOrderCycleCtrl",
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeCoordinatorFee(index)
|
||||
|
||||
$scope.submit = (event) ->
|
||||
event.preventDefault()
|
||||
$scope.submit = (destination) ->
|
||||
OrderCycle.mirrorIncomingToOutgoingProducts()
|
||||
OrderCycle.update()
|
||||
OrderCycle.update(destination)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.order_cycles").filter "filterExchangeVariants", ->
|
||||
angular.module("admin.orderCycles").filter "filterExchangeVariants", ->
|
||||
return (variants, rules) ->
|
||||
if variants? && rules?
|
||||
return (variant for variant in variants when variant in rules)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.order_cycles").filter "visibleProductVariants", ->
|
||||
angular.module("admin.orderCycles").filter "visibleProductVariants", ->
|
||||
return (product, exchange, rules) ->
|
||||
variants = product.variants.concat( [{ "id": product.master_id}] )
|
||||
return (variant for variant in variants when variant.id in rules[exchange.enterprise_id])
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
angular.module("admin.order_cycles").filter "visibleProducts", ($filter) ->
|
||||
angular.module("admin.orderCycles").filter "visibleProducts", ($filter) ->
|
||||
return (products, exchange, rules) ->
|
||||
return (product for product in products when $filter('visibleProductVariants')(product, exchange, rules).length > 0)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
angular.module('admin.orderCycles', ['ngResource', 'admin.indexUtils'])
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module('admin.order_cycles').factory('Enterprise', ($resource) ->
|
||||
angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
|
||||
Enterprise = $resource('/admin/enterprises/for_order_cycle/:enterprise_id.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
@@ -10,6 +10,8 @@ angular.module('admin.order_cycles').factory('Enterprise', ($resource) ->
|
||||
{
|
||||
Enterprise: Enterprise
|
||||
enterprises: {}
|
||||
producer_enterprises: []
|
||||
hub_enterprises: []
|
||||
supplied_products: []
|
||||
loaded: false
|
||||
|
||||
@@ -17,6 +19,8 @@ angular.module('admin.order_cycles').factory('Enterprise', ($resource) ->
|
||||
Enterprise.index params, (data) =>
|
||||
for enterprise in data
|
||||
@enterprises[enterprise.id] = enterprise
|
||||
@producer_enterprises.push(enterprise) if enterprise.is_primary_producer
|
||||
@hub_enterprises.push(enterprise) if enterprise.sells == 'any'
|
||||
|
||||
for product in enterprise.supplied_products
|
||||
@supplied_products.push(product)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module('admin.order_cycles').factory('EnterpriseFee', ($resource) ->
|
||||
angular.module('admin.orderCycles').factory('EnterpriseFee', ($resource) ->
|
||||
EnterpriseFee = $resource('/admin/enterprise_fees/for_order_cycle/:enterprise_fee_id.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window) ->
|
||||
OrderCycle = $resource '/admin/order_cycles/:action_name/:order_cycle_id.json', {}, {
|
||||
angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, StatusMessage) ->
|
||||
OrderCycleResource = $resource '/admin/order_cycles/:action_name/:order_cycle_id.json', {}, {
|
||||
'index': { method: 'GET', isArray: true}
|
||||
'new' : { method: 'GET', params: { action_name: "new" } }
|
||||
'create': { method: 'POST'}
|
||||
'update': { method: 'PUT'}}
|
||||
|
||||
{
|
||||
order_cycle: {}
|
||||
new class OrderCycle
|
||||
order_cycle: {incoming_exchanges: [], outgoing_exchanges: []}
|
||||
showProducts: {incoming: false, outgoing: false}
|
||||
|
||||
loaded: false
|
||||
|
||||
exchangeIds: (direction) ->
|
||||
parseInt(exchange.enterprise_id) for exchange in @exchangesByDirection(direction)
|
||||
|
||||
novelSupplier: (enterprise) =>
|
||||
id = enterprise?.id || parseInt(enterprise)
|
||||
@exchangeIds('incoming').indexOf(id) == -1
|
||||
|
||||
novelDistributor: (enterprise) =>
|
||||
id = enterprise?.id || parseInt(enterprise)
|
||||
@exchangeIds('outgoing').indexOf(id) == -1
|
||||
|
||||
exchangeSelectedVariants: (exchange) ->
|
||||
numActiveVariants = 0
|
||||
numActiveVariants++ for id, active of exchange.variants when active
|
||||
@@ -21,6 +33,10 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
|
||||
toggleProducts: (exchange) ->
|
||||
exchange.showProducts = !exchange.showProducts
|
||||
|
||||
toggleAllProducts: (direction) ->
|
||||
this.showProducts[direction] = !this.showProducts[direction]
|
||||
exchange.showProducts = this.showProducts[direction] for exchange in this.exchangesByDirection(direction)
|
||||
|
||||
setExchangeVariants: (exchange, variants, selected) ->
|
||||
direction = if exchange.incoming then "incoming" else "outgoing"
|
||||
editable = @order_cycle["editable_variants_for_#{direction}_exchanges"][exchange.enterprise_id] || []
|
||||
@@ -80,12 +96,18 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
|
||||
distributors = (exchange.enterprise_id for exchange in this.order_cycle.outgoing_exchanges)
|
||||
jQuery.unique(suppliers.concat(distributors)).sort()
|
||||
|
||||
exchangesByDirection: (direction) ->
|
||||
if direction == 'incoming'
|
||||
this.order_cycle.incoming_exchanges
|
||||
else
|
||||
this.order_cycle.outgoing_exchanges
|
||||
|
||||
removeDistributionOfVariant: (variant_id) ->
|
||||
for exchange in this.order_cycle.outgoing_exchanges
|
||||
exchange.variants[variant_id] = false
|
||||
|
||||
new: (params, callback=null) ->
|
||||
OrderCycle.new params, (oc) =>
|
||||
OrderCycleResource.new params, (oc) =>
|
||||
delete oc.$promise
|
||||
delete oc.$resolved
|
||||
angular.extend(@order_cycle, oc)
|
||||
@@ -100,7 +122,7 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
|
||||
|
||||
load: (order_cycle_id, callback=null) ->
|
||||
service = this
|
||||
OrderCycle.get {order_cycle_id: order_cycle_id}, (oc) ->
|
||||
OrderCycleResource.get {order_cycle_id: order_cycle_id}, (oc) ->
|
||||
delete oc.$promise
|
||||
delete oc.$resolved
|
||||
angular.extend(service.order_cycle, oc)
|
||||
@@ -123,22 +145,33 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
|
||||
|
||||
this.order_cycle
|
||||
|
||||
create: ->
|
||||
oc = new OrderCycle({order_cycle: this.dataForSubmit()})
|
||||
oc.$create (data) ->
|
||||
if data['success']
|
||||
$window.location = '/admin/order_cycles'
|
||||
else
|
||||
create: (destination) ->
|
||||
return unless @confirmNoDistributors()
|
||||
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
|
||||
oc.$create (data) ->
|
||||
if data['success']
|
||||
$window.location = destination
|
||||
else
|
||||
console.log('Failed to create order cycle')
|
||||
|
||||
update: ->
|
||||
oc = new OrderCycle({order_cycle: this.dataForSubmit()})
|
||||
oc.$update {order_cycle_id: this.order_cycle.id}, (data) ->
|
||||
if data['success']
|
||||
$window.location = '/admin/order_cycles'
|
||||
else
|
||||
update: (destination) ->
|
||||
return unless @confirmNoDistributors()
|
||||
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
|
||||
oc.$update {order_cycle_id: this.order_cycle.id, reloading: (if destination? then 1 else 0)}, (data) =>
|
||||
if data['success']
|
||||
if destination?
|
||||
$window.location = destination
|
||||
else
|
||||
StatusMessage.display 'success', 'Your order cycle has been updated.'
|
||||
else
|
||||
console.log('Failed to update order cycle')
|
||||
|
||||
confirmNoDistributors: ->
|
||||
if @order_cycle.outgoing_exchanges.length == 0
|
||||
confirm 'There are no distributors in this order cycle. This order cycle will not be visible to customers until you add one. Would you like to continue saving this order cycle?'
|
||||
else
|
||||
true
|
||||
|
||||
dataForSubmit: ->
|
||||
data = this.deepCopy()
|
||||
data = this.stripNonSubmittableAttributes(data)
|
||||
@@ -200,4 +233,3 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
|
||||
|
||||
for id, active of incoming.variants
|
||||
outgoing.variants[id] = active
|
||||
})
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
angular.module("admin.orderCycles").factory 'OrderCycleResource', ($resource) ->
|
||||
$resource('/admin/order_cycles/:id/:action.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
'update':
|
||||
method: 'PUT'
|
||||
})
|
||||
@@ -0,0 +1,40 @@
|
||||
angular.module("admin.orderCycles").factory 'OrderCycles', ($q, OrderCycleResource, blankOption) ->
|
||||
new class OrderCycles
|
||||
orderCyclesByID: {}
|
||||
pristineByID: {}
|
||||
|
||||
index: (params={}, callback=null) ->
|
||||
includeBlank = !!params['includeBlank']
|
||||
delete params['includeBlank']
|
||||
OrderCycleResource.index(params, (data) =>
|
||||
for orderCycle in data
|
||||
@orderCyclesByID[orderCycle.id] = orderCycle
|
||||
@pristineByID[orderCycle.id] = angular.copy(orderCycle)
|
||||
|
||||
(callback || angular.noop)(data)
|
||||
|
||||
data.unshift(blankOption()) if includeBlank
|
||||
data
|
||||
)
|
||||
|
||||
save: (order_cycle) ->
|
||||
deferred = $q.defer()
|
||||
order_cycle.$update({id: order_cycle.id})
|
||||
.then( (data) =>
|
||||
@pristineByID[order_cycle.id] = angular.copy(order_cycle)
|
||||
deferred.resolve(data)
|
||||
).catch (response) ->
|
||||
deferred.reject(response)
|
||||
deferred.promise
|
||||
|
||||
saved: (order_cycle) ->
|
||||
@diff(order_cycle).length == 0
|
||||
|
||||
diff: (order_cycle) ->
|
||||
changed = []
|
||||
for attr, value of order_cycle when not angular.equals(value, @pristineByID[order_cycle.id][attr])
|
||||
changed.push attr unless attr is "$$hashKey"
|
||||
changed
|
||||
|
||||
resetAttribute: (order_cycle, attribute) ->
|
||||
order_cycle[attribute] = @pristineByID[order_cycle.id][attribute]
|
||||
@@ -0,0 +1,22 @@
|
||||
angular.module("admin.orders").controller "ordersCtrl", ($scope, $compile, $attrs, shops, orderCycles) ->
|
||||
$scope.$compile = $compile
|
||||
$scope.shops = shops
|
||||
$scope.orderCycles = orderCycles
|
||||
for oc in $scope.orderCycles
|
||||
oc.name_and_status = "#{oc.name} (#{oc.status})"
|
||||
|
||||
$scope.distributor_id = $attrs.ofnDistributorId
|
||||
$scope.order_cycle_id = $attrs.ofnOrderCycleId
|
||||
|
||||
$scope.validOrderCycle = (oc, index, array) ->
|
||||
$scope.orderCycleHasDistributor oc, parseInt($scope.distributor_id)
|
||||
|
||||
$scope.distributorHasOrderCycles = (distributor) ->
|
||||
(oc for oc in orderCycles when @orderCycleHasDistributor(oc, distributor.id)).length > 0
|
||||
|
||||
$scope.orderCycleHasDistributor = (oc, distributor_id) ->
|
||||
distributor_ids = (d.id for d in oc.distributors)
|
||||
distributor_ids.indexOf(distributor_id) != -1
|
||||
|
||||
$scope.distributionChosen = ->
|
||||
$scope.distributor_id && $scope.order_cycle_id
|
||||
1
app/assets/javascripts/admin/orders/orders.js.coffee
Normal file
1
app/assets/javascripts/admin/orders/orders.js.coffee
Normal file
@@ -0,0 +1 @@
|
||||
angular.module("admin.orders", ['ngResource'])
|
||||
@@ -0,0 +1,8 @@
|
||||
angular.module("admin.orders").factory 'OrderResource', ($resource) ->
|
||||
$resource('/admin/orders/:id/:action.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
'update':
|
||||
method: 'PUT'
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
angular.module("admin.orders").factory 'Orders', ($q, OrderResource) ->
|
||||
new class Orders
|
||||
ordersByID: {}
|
||||
pristineByID: {}
|
||||
|
||||
index: (params={}, callback=null) ->
|
||||
OrderResource.index params, (data) =>
|
||||
for order in data
|
||||
@ordersByID[order.id] = order
|
||||
@pristineByID[order.id] = angular.copy(order)
|
||||
|
||||
(callback || angular.noop)(data)
|
||||
|
||||
save: (order) ->
|
||||
deferred = $q.defer()
|
||||
order.$update({id: order.number})
|
||||
.then( (data) =>
|
||||
@pristineByID[order.id] = angular.copy(order)
|
||||
deferred.resolve(data)
|
||||
).catch (response) ->
|
||||
deferred.reject(response)
|
||||
deferred.promise
|
||||
|
||||
saved: (order) ->
|
||||
@diff(order).length == 0
|
||||
|
||||
diff: (order) ->
|
||||
changed = []
|
||||
for attr, value of order when not angular.equals(value, @pristineByID[order.id][attr])
|
||||
changed.push attr unless attr is "$$hashKey"
|
||||
changed
|
||||
|
||||
resetAttribute: (order, attribute) ->
|
||||
order[attribute] = @pristineByID[order.id][attribute]
|
||||
@@ -1,2 +0,0 @@
|
||||
angular.module("ofn.admin").value "blankOption", ->
|
||||
{ id: "0", name: "All" }
|
||||
@@ -0,0 +1,11 @@
|
||||
angular.module("admin.utils").directive "watchValueAs", ->
|
||||
restrict: 'A'
|
||||
scope: {
|
||||
value: "=watchValueAs"
|
||||
}
|
||||
link: (scope, element, attrs) ->
|
||||
scope.value = element.val()
|
||||
|
||||
element.on "change blur load", ->
|
||||
scope.$apply ->
|
||||
scope.value = element.val()
|
||||
@@ -0,0 +1,2 @@
|
||||
angular.module("admin.utils").value "blankOption", ->
|
||||
{ id: "0", name: "All" }
|
||||
@@ -0,0 +1,26 @@
|
||||
angular.module("admin.utils").factory "StatusMessage", ($timeout) ->
|
||||
new class StatusMessage
|
||||
types:
|
||||
progress: {timeout: false, style: {color: '#ff9906'}}
|
||||
alert: {timeout: 5000, style: {color: 'grey'}}
|
||||
notice: {timeout: false, style: {color: 'grey'}}
|
||||
success: {timeout: 5000, style: {color: '#9fc820'}}
|
||||
failure: {timeout: false, style: {color: '#da5354'}}
|
||||
|
||||
statusMessage:
|
||||
text: ""
|
||||
style: {}
|
||||
|
||||
display: (type, text) ->
|
||||
@statusMessage.text = text
|
||||
@statusMessage.style = @types[type].style
|
||||
$timeout.cancel @statusMessage.timeout if @statusMessage.timeout
|
||||
timeout = @types[type].timeout
|
||||
if timeout
|
||||
@statusMessage.timeout = $timeout =>
|
||||
@clear()
|
||||
, timeout, true
|
||||
|
||||
clear: ->
|
||||
@statusMessage.text = ''
|
||||
@statusMessage.style = {}
|
||||
@@ -15,5 +15,5 @@ $(document).ready ->
|
||||
|
||||
$('td.cart-adjustments a').click ->
|
||||
$('.cart_adjustment').toggle()
|
||||
$(this).html('Item Handling Fees (included in item totals)')
|
||||
$(this).html(t('item_handling_fees'))
|
||||
false
|
||||
|
||||
@@ -7,6 +7,6 @@ Darkswarm.controller "ForgotCtrl", ($scope, $http, $location, AuthenticationServ
|
||||
$http.post("/user/spree_user/password", {spree_user: $scope.spree_user}).success (data)->
|
||||
$scope.sent = true
|
||||
.error (data) ->
|
||||
$scope.errors = "Email address not found"
|
||||
$scope.errors = t 'email_not_found'
|
||||
else
|
||||
$scope.errors = "You must provide an email address"
|
||||
$scope.errors = t 'email_required'
|
||||
|
||||
@@ -2,7 +2,7 @@ Darkswarm.controller "LoginCtrl", ($scope, $http, $window, AuthenticationService
|
||||
$scope.path = "/login"
|
||||
|
||||
$scope.submit = ->
|
||||
Loading.message = "Hold on a moment, we're logging you in"
|
||||
Loading.message = t 'logging_in'
|
||||
$http.post("/user/spree_user/sign_in", {spree_user: $scope.spree_user}).success (data)->
|
||||
if Redirections.after_login
|
||||
$window.location.href = $window.location.origin + Redirections.after_login
|
||||
|
||||
@@ -3,18 +3,18 @@ Darkswarm.controller "PaymentCtrl", ($scope, $timeout) ->
|
||||
$scope.name = "payment"
|
||||
|
||||
$scope.months = [
|
||||
{key: "January", value: "1"},
|
||||
{key: "February", value: "2"},
|
||||
{key: "March", value: "3"},
|
||||
{key: "April", value: "4"},
|
||||
{key: "May", value: "5"},
|
||||
{key: "June", value: "6"},
|
||||
{key: "July", value: "7"},
|
||||
{key: "August", value: "8"},
|
||||
{key: "September", value: "9"},
|
||||
{key: "October", value: "10"},
|
||||
{key: "November", value: "11"},
|
||||
{key: "December", value: "12"},
|
||||
{key: t("january"), value: "1"},
|
||||
{key: t("february"), value: "2"},
|
||||
{key: t("march"), value: "3"},
|
||||
{key: t("april"), value: "4"},
|
||||
{key: t("may"), value: "5"},
|
||||
{key: t("june"), value: "6"},
|
||||
{key: t("july"), value: "7"},
|
||||
{key: t("august"), value: "8"},
|
||||
{key: t("september"), value: "9"},
|
||||
{key: t("october"), value: "10"},
|
||||
{key: t("november"), value: "11"},
|
||||
{key: t("december"), value: "12"},
|
||||
]
|
||||
|
||||
$scope.years = [moment().year()..(moment().year()+15)]
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
Darkswarm.controller "GroupPageCtrl", ($scope, group_enterprises, Enterprises, MapConfiguration, OfnMap) ->
|
||||
Darkswarm.controller "GroupPageCtrl", ($scope, group_enterprises, Enterprises, MapConfiguration, OfnMap, visibleFilter) ->
|
||||
$scope.Enterprises = Enterprises
|
||||
|
||||
group_enterprises_ids = group_enterprises.map (enterprise) =>
|
||||
enterprise.id
|
||||
is_in_group = (enterprise) ->
|
||||
group_enterprises_ids.indexOf(enterprise.id) != -1
|
||||
all_enterprises_by_id = Enterprises.enterprises_by_id
|
||||
|
||||
$scope.group_producers = Enterprises.producers.filter is_in_group
|
||||
$scope.group_hubs = Enterprises.hubs.filter is_in_group
|
||||
dereferenced_enterprises = group_enterprises.map (enterprise) =>
|
||||
all_enterprises_by_id[enterprise.id]
|
||||
|
||||
visible_enterprises = visibleFilter dereferenced_enterprises
|
||||
|
||||
# TODO: this is duplicate code with app/assets/javascripts/darkswarm/services/enterprises.js.coffee
|
||||
# It would be better to load only the needed enterprises (group + related shops).
|
||||
$scope.group_producers = visible_enterprises.filter (enterprise) ->
|
||||
enterprise.category in ["producer_hub", "producer_shop", "producer"]
|
||||
$scope.group_hubs = visible_enterprises.filter (enterprise) ->
|
||||
enterprise.category in ["hub", "hub_profile", "producer_hub", "producer_shop"]
|
||||
|
||||
$scope.map = angular.copy MapConfiguration.options
|
||||
$scope.mapMarkers = OfnMap.enterprise_markers group_enterprises
|
||||
$scope.mapMarkers = OfnMap.enterprise_markers visible_enterprises
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Darkswarm.directive "ofnChangeHub", (CurrentHub, Cart) ->
|
||||
|
||||
if cart_will_need_emptying()
|
||||
elm.bind 'click', (ev)->
|
||||
if confirm "Are you sure? This will change your selected hub and remove any items in your shopping cart."
|
||||
if confirm t('confirm_hub_change')
|
||||
Cart.clear()
|
||||
else
|
||||
ev.preventDefault()
|
||||
|
||||
@@ -12,7 +12,7 @@ Darkswarm.directive "ofnChangeOrderCycle", (OrderCycle, Cart, storage) ->
|
||||
|
||||
elm.bind 'change', (ev)->
|
||||
if cart_needs_emptying()
|
||||
if confirm "Are you sure? This will change your selected order cycle and remove any items in your shopping cart."
|
||||
if confirm t('confirm_oc_change')
|
||||
Cart.clear()
|
||||
scope.changeOrderCycle()
|
||||
else
|
||||
|
||||
@@ -3,7 +3,7 @@ Darkswarm.directive 'mapSearch', ($timeout)->
|
||||
restrict: 'E'
|
||||
require: '^googleMap'
|
||||
replace: true
|
||||
template: '<input id="pac-input" placeholder="Type in a location..."></input>'
|
||||
template: '<input id="pac-input" placeholder="' + t('location_placeholder') + '"></input>'
|
||||
link: (scope, elem, attrs, ctrl)->
|
||||
$timeout =>
|
||||
map = ctrl.getMap()
|
||||
|
||||
@@ -9,5 +9,5 @@ Darkswarm.directive "ofnRegistrationLimitModal", (Navigation, $modal, Loading) -
|
||||
scope.modalInstance.result.then scope.close, scope.close
|
||||
|
||||
scope.close = ->
|
||||
Loading.message = "Taking you back to the home page"
|
||||
Loading.message = t 'going_back_to_home_page'
|
||||
Navigation.go "/"
|
||||
|
||||
@@ -5,6 +5,6 @@ Darkswarm.filter "date_in_words", ->
|
||||
Darkswarm.filter "sensible_timeframe", (date_in_wordsFilter)->
|
||||
(date) ->
|
||||
if moment().add('days', 2) < moment(date)
|
||||
"Orders open"
|
||||
t 'orders_open'
|
||||
else
|
||||
"Closing #{date_in_wordsFilter(date)}"
|
||||
t('closing') + date_in_wordsFilter(date)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
Darkswarm.filter "translate", ->
|
||||
(key, options) ->
|
||||
t(key, options)
|
||||
|
||||
Darkswarm.filter "t", ->
|
||||
(key, options) ->
|
||||
t(key, options)
|
||||
9
app/assets/javascripts/darkswarm/i18n.js.erb
Normal file
9
app/assets/javascripts/darkswarm/i18n.js.erb
Normal file
@@ -0,0 +1,9 @@
|
||||
<%# Defines a global I18n object containing the language of the current locale %>
|
||||
<%
|
||||
# Invalidate this asset if locale changes.
|
||||
Dir[Rails.root.join('config', 'locales', "#{I18n.default_locale}.yml").to_s].each do |f|
|
||||
depend_on(f)
|
||||
end
|
||||
%>
|
||||
<%- I18n.backend.send(:init_translations) unless I18n.backend.initialized? %>
|
||||
window.I18n = <%= I18n.backend.send(:translations)[I18n.default_locale].with_indifferent_access.to_json.html_safe %>
|
||||
12
app/assets/javascripts/darkswarm/i18n.translate.js.coffee
Normal file
12
app/assets/javascripts/darkswarm/i18n.translate.js.coffee
Normal file
@@ -0,0 +1,12 @@
|
||||
# Declares the translation function t.
|
||||
# You can use translate('login') or t('login') in Javascript.
|
||||
window.translate = (key, options = {}) ->
|
||||
unless 'I18n' of window
|
||||
console.log 'The I18n object is undefined. Cannot translate text.'
|
||||
return key
|
||||
return key unless key of I18n
|
||||
text = I18n[key]
|
||||
for name, value of options
|
||||
text = text.split("%{#{name}}").join(value)
|
||||
text
|
||||
window.t = window.translate
|
||||
@@ -32,10 +32,10 @@ window.FieldsetMixin = ($scope)->
|
||||
errors = for error, invalid of $scope.error(path)
|
||||
if invalid
|
||||
switch error
|
||||
when "required" then "can't be blank"
|
||||
when "number" then "must be number"
|
||||
when "email" then "must be email address"
|
||||
when "required" then t('error_required')
|
||||
when "number" then t('error_number')
|
||||
when "email" then t('error_email')
|
||||
|
||||
#server_errors = $scope.Order.errors[path.replace('order.', '')]
|
||||
#errors.push server_errors if server_errors?
|
||||
(errors.filter (error) -> error?).join ", "
|
||||
(errors.filter (error) -> error?).join ", "
|
||||
|
||||
@@ -28,6 +28,6 @@ Darkswarm.factory "AuthenticationService", (Navigation, $modal, $location, Redir
|
||||
if location.pathname in ["/", "/checkout"]
|
||||
Navigation.navigate "/"
|
||||
else
|
||||
Loading.message = "Taking you back to the home page"
|
||||
Loading.message = t 'going_back_to_home_page'
|
||||
location.hash = ""
|
||||
location.pathname = "/"
|
||||
|
||||
@@ -44,7 +44,7 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, storage)->
|
||||
unsaved: =>
|
||||
@dirty = true
|
||||
$(window).bind "beforeunload", ->
|
||||
"Your order hasn't been saved yet. Give us a few seconds to finish!"
|
||||
t 'order_not_saved_yet'
|
||||
|
||||
line_items_present: =>
|
||||
@line_items.filter (li)->
|
||||
|
||||
@@ -6,7 +6,7 @@ Darkswarm.factory 'Checkout', (CurrentOrder, ShippingMethods, PaymentMethods, $h
|
||||
ship_address_same_as_billing: true
|
||||
|
||||
submit: ->
|
||||
Loading.message = "Submitting your order: please wait"
|
||||
Loading.message = t 'submitting_order'
|
||||
$http.put('/checkout', {order: @preprocess()}).success (data, status)=>
|
||||
Navigation.go data.path
|
||||
.error (response, status)=>
|
||||
|
||||
@@ -11,7 +11,7 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
@enterprise[key] = value
|
||||
|
||||
create: =>
|
||||
Loading.message = "Creating " + @enterprise.name
|
||||
Loading.message = t('creating') + " " + @enterprise.name
|
||||
$http(
|
||||
method: "POST"
|
||||
url: "/api/enterprises"
|
||||
@@ -28,14 +28,13 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
Loading.clear()
|
||||
if data?.errors?
|
||||
errors = ("#{k.capitalize()} #{v[0]}" for k, v of data.errors when v.length > 0)
|
||||
alert "Failed to create your enterprise.\n" + errors.join('\n')
|
||||
alert t('failed_to_create_enterprise') + "\n" + errors.join('\n')
|
||||
else
|
||||
alert('Failed to create your enterprise.\nPlease ensure all fields are completely filled out.')
|
||||
alert(t('failed_to_create_enterprise_unknown'))
|
||||
)
|
||||
# RegistrationService.select('about')
|
||||
|
||||
update: (step) =>
|
||||
Loading.message = "Updating " + @enterprise.name
|
||||
Loading.message = t('updating') + " " + @enterprise.name
|
||||
$http(
|
||||
method: "PUT"
|
||||
url: "/api/enterprises/#{@enterprise.id}"
|
||||
@@ -48,9 +47,8 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
RegistrationService.select(step)
|
||||
).error((data) ->
|
||||
Loading.clear()
|
||||
alert('Failed to update your enterprise.\nPlease ensure all fields are completely filled out.')
|
||||
alert(t('failed_to_update_enterprise_unknown'))
|
||||
)
|
||||
# RegistrationService.select(step)
|
||||
|
||||
prepare: =>
|
||||
enterprise = {}
|
||||
|
||||
@@ -16,11 +16,11 @@ Darkswarm.factory "FilterSelectorsService", ->
|
||||
filterText: (active)=>
|
||||
total = @totalActive()
|
||||
if total == 0
|
||||
if active then "Hide filters" else "Filter by"
|
||||
if active then t('hide_filters') else t('filter_by')
|
||||
else if total == 1
|
||||
"1 filter applied"
|
||||
t 'one_filter_applied'
|
||||
else
|
||||
"#{@totalActive()} filters applied"
|
||||
@totalActive() + t('x_filters_applied')
|
||||
|
||||
clearAll: =>
|
||||
for selector in @selectors
|
||||
|
||||
@@ -19,5 +19,5 @@ angular.module('Darkswarm').factory "RegistrationService", (Navigation, $modal,
|
||||
@current_step
|
||||
|
||||
close: ->
|
||||
Loading.message = "Taking you back to the home page"
|
||||
Loading.message = t 'going_back_to_home_page'
|
||||
Navigation.go "/"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Place all the behaviors and hooks related to the matching controller here.
|
||||
# All this logic will automatically be available in application.js.
|
||||
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
|
||||
@@ -0,0 +1,10 @@
|
||||
.ofn_drop_down{ "ofn-drop-down" => true }
|
||||
%span
|
||||
%i.icon-check
|
||||
Actions
|
||||
%i{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
|
||||
%div.menu{ 'ng-show' => "expanded", style: 'width: 200px' }
|
||||
%a.menu_item{ 'ng-repeat' => "link in links", href: '{{link.url}}', target: "{{link.target || '_self'}}", data: { method: "{{ link.method || 'get' }}", confirm: "{{link.confirm}}" }, style: 'display: inline-block; width: 100%' }
|
||||
%span{ :style => 'text-align: center; display: inline-block; width: 20%'}
|
||||
%i{ ng: { class: "link.icon" } }
|
||||
%span{ style: "display: inline-block; width: auto"} {{ link.name }}
|
||||
@@ -15,7 +15,8 @@
|
||||
%h3 Hub Shop
|
||||
|
||||
%p
|
||||
%strong COST: 2% OF SALES, CAPPED AT $50 PER MONTH
|
||||
%strong
|
||||
%monthly-pricing-description{ joiner: "comma" }
|
||||
|
||||
%p Your enterprise is the backbone of your local food system. You aggregate produce from other enterprises and can sell it through your shop on the Open Food Network.
|
||||
|
||||
@@ -53,7 +54,8 @@
|
||||
%h3 Producer Shop
|
||||
|
||||
%p
|
||||
%strong COST: 2% OF SALES, CAPPED AT $50 PER MONTH
|
||||
%strong
|
||||
%monthly-pricing-description{ joiner: "comma" }
|
||||
|
||||
%p Sell your products directly to customers through your very own Open Food Network shopfront.
|
||||
|
||||
@@ -63,7 +65,8 @@
|
||||
%h3 Producer Hub
|
||||
|
||||
%p
|
||||
%strong COST: 2% OF SALES, CAPPED AT $50 PER MONTH
|
||||
%strong
|
||||
%monthly-pricing-description{ joiner: "comma" }
|
||||
|
||||
%p Your enterprise is the backbone of your local food system. You can sell your own produce as well as produce aggregated from other enterprises through your shopfront on the Open Food Network.
|
||||
|
||||
@@ -94,9 +97,7 @@
|
||||
%h3 Hub Shop
|
||||
%p Sell produce from others
|
||||
.bottom
|
||||
\2% OF SALES
|
||||
%br
|
||||
CAPPED AT $50 PER MONTH
|
||||
%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}" } }
|
||||
@@ -109,17 +110,14 @@
|
||||
%h3 Producer Shop
|
||||
%p Sell your own produce
|
||||
.bottom
|
||||
\2% OF SALES
|
||||
%br
|
||||
CAPPED AT $50 PER MONTH
|
||||
%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 Producer Hub
|
||||
%p Sell produce from self and others
|
||||
.bottom
|
||||
\2% OF SALES
|
||||
%br
|
||||
CAPPED AT $50 PER MONTH
|
||||
%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" } }
|
||||
|
||||
10
app/assets/javascripts/templates/admin/save_bar.html.haml
Normal file
10
app/assets/javascripts/templates/admin/save_bar.html.haml
Normal file
@@ -0,0 +1,10 @@
|
||||
#save-bar.animate-show{ ng: { show: 'dirty()' } }
|
||||
.twelve.columns.alpha
|
||||
%h5{ ng: { show: "dirty() && !saving()" } }
|
||||
You have unsaved changes
|
||||
%h5{ ng: { hide: "dirty() || saving()" } }
|
||||
All changes saved
|
||||
%h5{ ng: { show: "saving()" } }
|
||||
Saving...
|
||||
.four.columns.omega.text-right
|
||||
%input.red{type: "button", value: "Save Changes", ng: { click: "save()" } }
|
||||
@@ -1,5 +1,5 @@
|
||||
%tab#forgot{"ng-controller" => "ForgotCtrl",
|
||||
heading: "Forgot Password?",
|
||||
heading: "{{'forgot_password' | t}}",
|
||||
active: "active(path)",
|
||||
select: "select(path)"}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
.row
|
||||
.large-12.columns
|
||||
.alert-box.success.radius{"ng-show" => "sent"}
|
||||
An email with instructions on resetting your password has been sent!
|
||||
{{'password_reset_sent' | t}}
|
||||
|
||||
%div{"ng-show" => "!sent"}
|
||||
.alert-box.alert{"ng-show" => "errors != null"}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
.row
|
||||
.large-12.columns
|
||||
%label{for: "email"} Your email
|
||||
%label{for: "email"} {{'signup_email' | t}}
|
||||
%input.title.input-text{name: "email",
|
||||
type: "email",
|
||||
id: "email",
|
||||
@@ -27,4 +27,4 @@
|
||||
%input.button.primary{name: "commit",
|
||||
tabindex: "3",
|
||||
type: "submit",
|
||||
value: "Reset password"}
|
||||
value: "{{'reset_password' | t}}"}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%tab#login-content{"ng-controller" => "LoginCtrl",
|
||||
heading: "Log in",
|
||||
heading: "{{'label_login' | t}}",
|
||||
active: "active(path)",
|
||||
select: "select(path)"}
|
||||
%form{"ng-submit" => "submit()"}
|
||||
@@ -9,7 +9,7 @@
|
||||
{{ errors }}
|
||||
.row
|
||||
.large-12.columns
|
||||
%label{for: "email"} Email
|
||||
%label{for: "email"} {{'email' | t}}
|
||||
%input.title.input-text{name: "email",
|
||||
type: "email",
|
||||
id: "email",
|
||||
@@ -17,7 +17,7 @@
|
||||
"ng-model" => "spree_user.email"}
|
||||
.row
|
||||
.large-12.columns
|
||||
%label{for: "password"} Password
|
||||
%label{for: "password"} {{'password' | t}}
|
||||
%input.title.input-text{name: "password",
|
||||
type: "password",
|
||||
id: "password",
|
||||
@@ -31,10 +31,10 @@
|
||||
id: "remember_me",
|
||||
value: "1",
|
||||
"ng-model" => "spree_user.remember_me"}
|
||||
%label{for: "remember_me"} Remember Me
|
||||
%label{for: "remember_me"} {{'remember_me' | t}}
|
||||
.row
|
||||
.large-12.columns
|
||||
%input.button.primary{name: "commit",
|
||||
tabindex: "3",
|
||||
type: "submit",
|
||||
value: "Log in"}
|
||||
value: "{{'label_login' | t}}"}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%div.contact-container{bindonce: true}
|
||||
%div.modal-centered{"bo-if" => "enterprise.email || enterprise.website || enterprise.phone"}
|
||||
%p.modal-header Contact
|
||||
%p.modal-header {{'contact' | t}}
|
||||
%p{"bo-if" => "enterprise.phone", "bo-text" => "enterprise.phone"}
|
||||
|
||||
%p.word-wrap{"ng-if" => "enterprise.email"}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/ TODO: Rob add logic for taxons and properties too:
|
||||
/ %div{"ng-if" => "enterprise.long_description.length > 0 || enterprise.logo"}
|
||||
%div
|
||||
%p.modal-header About
|
||||
%p.modal-header {{'label_about' | t}}
|
||||
/ TODO: Rob - add in taxons and properties and property pop-overs
|
||||
|
||||
-# TODO: Add producer taxons and properties here
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
%div.modal-centered{bindonce: true, "bo-if" => "enterprise.twitter || enterprise.facebook || enterprise.linkedin || enterprise.instagram"}
|
||||
%p.modal-header Follow
|
||||
%p.modal-header {{'follow' | t}}
|
||||
.follow-icons
|
||||
%span{"bo-if" => "enterprise.twitter"}
|
||||
%a{"bo-href-i" => "http://twitter.com/{{enterprise.twitter}}", target: "_blank"}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
.row.pad-top{bindonce: true, "ng-if" => "enterprise.hubs.length > 0 && enterprise.is_distributor"}
|
||||
.cta-container.small-12.columns
|
||||
%label
|
||||
Shop for
|
||||
%strong{"bo-text" => "enterprise.name"}
|
||||
products at:
|
||||
%a.cta-hub{"ng-repeat" => "hub in enterprise.hubs",
|
||||
"bo-href" => "hub.path",
|
||||
"bo-class" => "{primary: hub.active, secondary: !hub.active}",
|
||||
"ofn-change-hub" => "hub"}
|
||||
%i.ofn-i_033-open-sign{"bo-if" => "hub.active"}
|
||||
%i.ofn-i_032-closed-sign{"bo-if" => "!hub.active"}
|
||||
.hub-name{"bo-text" => "hub.name"}
|
||||
.button-address{"bo-bind" => "[hub.address.city, hub.address.state_name] | printArray"}
|
||||
/ %i.ofn-i_007-caret-right
|
||||
@@ -2,16 +2,16 @@
|
||||
.cta-container.small-12.columns
|
||||
.row
|
||||
.small-4.columns
|
||||
%label{"active-table-hub-link" => "enterprise", change: "Change shop to:", shop: "Shop now at:"}
|
||||
%label{"active-table-hub-link" => "enterprise", change: "{{'change_shop' | t}}", shop: "{{'shop_at' | t}}"}
|
||||
.small-8.columns.right
|
||||
%label.right{"bo-if" => "enterprise.pickup || enterprise.delivery"}
|
||||
Delivery options:
|
||||
{{'hubs_delivery_options' | t}}:
|
||||
%span{"bo-if" => "enterprise.pickup"}
|
||||
%i.ofn-i_038-takeaway
|
||||
Pickup
|
||||
{{'hubs_pickup' | t}}
|
||||
%span{"bo-if" => "enterprise.delivery"}
|
||||
%i.ofn-i_039-delivery
|
||||
Delivery
|
||||
{{'hubs_delivery' | t}}
|
||||
.row
|
||||
.columns.small-12
|
||||
%a.cta-hub{"bo-href" => "enterprise.path",
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
.row
|
||||
.columns.small-12.fat
|
||||
%div{"bo-if" => "enterprise.name"}
|
||||
%label
|
||||
Shop for
|
||||
%span.turquoise{"bo-text" => "enterprise.name"}
|
||||
products at:
|
||||
%label{"bo-html" => "'shop_for_products_html' | t:{enterprise: enterprise.name}"}
|
||||
%div.show-for-medium-up{"bo-if" => "!enterprise.name"}
|
||||
|
||||
.row.cta-container
|
||||
|
||||
@@ -4,35 +4,35 @@
|
||||
.collapsed{"ng-show" => "!expanded"}
|
||||
%price-percentage{percentage: 'variant.basePricePercentage'}
|
||||
%a{"ng-click" => "expanded = !expanded"}
|
||||
Full price breakdown
|
||||
%span{"bo-text" => "'price_breakdown' | t"}
|
||||
%i.ofn-i_005-caret-down
|
||||
|
||||
.expanded{"ng-show" => "expanded"}
|
||||
%ul
|
||||
%li.cost
|
||||
.right {{ variant.price | localizeCurrency }}
|
||||
Item cost
|
||||
%span{"bo-text" => "'item_cost' | t"}
|
||||
%li.admin-fee{"bo-if" => "variant.fees.admin"}
|
||||
.right {{ variant.fees.admin | localizeCurrency }}
|
||||
Admin fee
|
||||
%span{"bo-text" => "'admin_fee' | t"}
|
||||
%li.sales-fee{"bo-if" => "variant.fees.sales"}
|
||||
.right {{ variant.fees.sales | localizeCurrency }}
|
||||
Sales fee
|
||||
%span{"bo-text" => "'sales_fee' | t"}
|
||||
%li.packing-fee{"bo-if" => "variant.fees.packing"}
|
||||
.right {{ variant.fees.packing | localizeCurrency }}
|
||||
Packing fee
|
||||
%span{"bo-text" => "'packing_fee' | t"}
|
||||
%li.transport-fee{"bo-if" => "variant.fees.transport"}
|
||||
.right {{ variant.fees.transport | localizeCurrency }}
|
||||
Transport fee
|
||||
%span{"bo-text" => "'transport_fee' | t"}
|
||||
%li.fundraising-fee{"bo-if" => "variant.fees.fundraising"}
|
||||
.right {{ variant.fees.fundraising | localizeCurrency }}
|
||||
Fundraising fee
|
||||
%span{"bo-text" => "'fundraising_fee' | t"}
|
||||
%li.total
|
||||
%strong
|
||||
.right = {{ variant.price_with_fees | localizeCurrency }}
|
||||
|
||||
|
||||
%a{"ng-click" => "expanded = !expanded"}
|
||||
Price graph
|
||||
%span{"bo-text" => "'price_graph' | t"}
|
||||
%i.ofn-i_006-caret-up
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.progress
|
||||
.right Fees
|
||||
.right {{'fees' | t}}
|
||||
.meter
|
||||
Item cost
|
||||
{{'item_cost' | t}}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.columns.small-12.large-6.product-header
|
||||
%h3{"bo-text" => "product.name"}
|
||||
%span
|
||||
%em from
|
||||
%em {{'products_from' | t}}
|
||||
%span{"bo-text" => "enterprise.name"}
|
||||
|
||||
%br
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
.row
|
||||
.small-12.columns
|
||||
%header
|
||||
%h2 Nice one!
|
||||
%h2 {{'enterprise_about_headline' | t}}
|
||||
%h5
|
||||
Now let's flesh out the details about
|
||||
{{'enterprise_about_message' | t}}
|
||||
%span{ ng: { class: "{brick: !enterprise.is_primary_producer, turquoise: enterprise.is_primary_producer}" } }
|
||||
{{ enterprise.name }}
|
||||
|
||||
@@ -13,45 +13,45 @@
|
||||
.row
|
||||
.small-12.columns
|
||||
.alert-box.info{ "ofn-inline-alert" => true, ng: { show: "visible" } }
|
||||
%h6 Success! {{ enterprise.name }} added to the Open Food Network
|
||||
%span If you exit this wizard at any stage, you need to click the confirmation link in the email you have received. This will take you to your admin interface where you can continue setting up your profile.
|
||||
%h6{ "ng-bind" => "'enterprise_success' | t:{enterprise: enterprise.name}" }
|
||||
%span {{'enterprise_registration_exit_message' | t}}
|
||||
%a.close{ ng: { click: "close()" } } ×
|
||||
|
||||
.small-12.large-8.columns
|
||||
.row
|
||||
.small-12.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_description' } Short Description:
|
||||
%input.chunky{ id: 'enterprise_description', placeholder: "A short sentence describing your enterprise", ng: { model: 'enterprise.description' } }
|
||||
%label{ for: 'enterprise_description' } {{'enterprise_description' | t}}:
|
||||
%input.chunky{ id: 'enterprise_description', placeholder: "{{'enterprise_description_placeholder' | t}}", ng: { model: 'enterprise.description' } }
|
||||
.row
|
||||
.small-12.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_long_desc' } Long Description:
|
||||
%textarea.chunky{ id: 'enterprise_long_desc', rows: 6, placeholder: "This is your opportunity to tell the story of your enterprise - what makes you different and wonderful? We'd suggest keeping your description to under 600 characters or 150 words.", ng: { model: 'enterprise.long_description' } }
|
||||
%small {{ enterprise.long_description.length }} characters / up to 600 recommended
|
||||
%label{ for: 'enterprise_long_desc' } {{'enterprise_long_desc' | t}}:
|
||||
%textarea.chunky{ id: 'enterprise_long_desc', rows: 6, placeholder: "{{'enterprise_long_desc_placeholder' | t}}", ng: { model: 'enterprise.long_description' } }
|
||||
%small{ "ng-bind" => "'enterprise_long_desc_length' | t:{num: enterprise.long_description.length}" }
|
||||
.small-12.large-4.columns
|
||||
.row
|
||||
.small-12.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_abn' } ABN:
|
||||
%input.chunky{ id: 'enterprise_abn', placeholder: "eg. 99 123 456 789", ng: { model: 'enterprise.abn' } }
|
||||
%label{ for: 'enterprise_abn' } {{'enterprise_abn' | t}}:
|
||||
%input.chunky{ id: 'enterprise_abn', placeholder: "{{'enterprise_abn_placeholder' | t}}", ng: { model: 'enterprise.abn' } }
|
||||
.row
|
||||
.small-12.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_acn' } ACN:
|
||||
%input.chunky{ id: 'enterprise_acn', placeholder: "eg. 123 456 789", ng: { model: 'enterprise.acn' } }
|
||||
%label{ for: 'enterprise_acn' } {{'enterprise_acn' | t}}:
|
||||
%input.chunky{ id: 'enterprise_acn', placeholder: "{{'enterprise_acn_placeholder' | t}}", ng: { model: 'enterprise.acn' } }
|
||||
.row
|
||||
.small-12.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_charges_sales_tax' }= t(:charges_sales_tax)
|
||||
%input{ id: 'enterprise_charges_sales_tax_true', type: 'radio', name: 'charges_sales_tax', value: 'true', required: true, ng: { model: 'enterprise.charges_sales_tax' } }
|
||||
%label{ for: 'enterprise_charges_sales_tax_true' } Yes
|
||||
%label{ for: 'enterprise_charges_sales_tax_true' } {{'say_yes' | t}}
|
||||
%input{ id: 'enterprise_charges_sales_tax_false', type: 'radio', name: 'charges_sales_tax', value: 'false', required: true, ng: { model: 'enterprise.charges_sales_tax' } }
|
||||
%label{ for: 'enterprise_charges_sales_tax_false' } No
|
||||
%label{ for: 'enterprise_charges_sales_tax_false' } {{'say_no' | t}}
|
||||
%span.error.small-12.columns{ ng: { show: "about.charges_sales_tax.$error.required && submitted" } }
|
||||
You need to make a selection.
|
||||
{{'enterprise_tax_required' | t}}
|
||||
|
||||
.row.buttons.pad-top
|
||||
.small-12.columns
|
||||
%input.button.primary.right{ type: "submit", value: "Continue" }
|
||||
%input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" }
|
||||
|
||||
|
||||
@@ -3,28 +3,27 @@
|
||||
.row
|
||||
.small-12.columns
|
||||
%header
|
||||
%h2 Greetings!
|
||||
%h5
|
||||
Who is responsible for managing {{ enterprise.name }}?
|
||||
%h2 {{'registration_greeting' | t}}
|
||||
%h5{ "ng-bind" => "'who_is_managing_enterprise' | t:{enterprise: enterprise.name}" }
|
||||
|
||||
%form{ name: 'contact', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('type',contact)" } }
|
||||
.row.content
|
||||
.small-12.medium-12.large-7.columns
|
||||
.row
|
||||
.small-12.columns.field
|
||||
%label{ for: 'enterprise_contact' } Primary Contact:
|
||||
%label{ for: 'enterprise_contact' } {{'enterprise_contact' | t}}:
|
||||
%input.chunky.small-12.columns{ id: 'enterprise_contact', name: 'contact', required: true, placeholder: "Contact Name", ng: { model: 'enterprise.contact' } }
|
||||
%span.error.small-12.columns{ ng: { show: "contact.contact.$error.required && submitted" } }
|
||||
You need to enter a primary contact.
|
||||
{{'enterprise_contact_required' | t}}
|
||||
.row
|
||||
.small-12.columns.field
|
||||
%label{ for: 'enterprise_email' } Email address:
|
||||
%label{ for: 'enterprise_email' } {{'enterprise_email' | t}}:
|
||||
%input.chunky.small-12.columns{ id: 'enterprise_email', name: 'email', type: 'email', required: true, placeholder: "eg. charlie@thefarm.com", ng: { model: 'enterprise.email' } }
|
||||
%span.error.small-12.columns{ ng: { show: "(contact.email.$error.email || contact.email.$error.required) && submitted" } }
|
||||
You need to enter valid email address.
|
||||
{{'enterprise_email_required' | t}}
|
||||
.row
|
||||
.small-12.columns.field
|
||||
%label{ for: 'enterprise_phone' } Phone number:
|
||||
%label{ for: 'enterprise_phone' } {{'enterprise_phone' | t}}:
|
||||
%input.chunky.small-12.columns{ id: 'enterprise_phone', name: 'phone', placeholder: "eg. (03) 1234 5678", ng: { model: 'enterprise.phone' } }
|
||||
.small-12.medium-12.large-5.hide-for-small-only
|
||||
/ %h6
|
||||
@@ -43,5 +42,5 @@
|
||||
|
||||
.row.buttons
|
||||
.small-12.columns
|
||||
%input.button.secondary{ type: "button", value: "Back", ng: { click: "select('details')" } }
|
||||
%input.button.primary.right{ type: "submit", value: "Continue" }
|
||||
%input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "select('details')" } }
|
||||
%input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" }
|
||||
|
||||
@@ -3,75 +3,62 @@
|
||||
.row
|
||||
.small-12.columns
|
||||
%header
|
||||
%h2 Let's Get Started
|
||||
%h5{ bo: { if: "enterprise.type != 'own'" } } Woot! First we need to know a little bit about your enterprise:
|
||||
%h5{ bo: { if: "enterprise.type == 'own'" } } Woot! First we need to know a little bit about your farm:
|
||||
%h2 {{'registration_detail_headline' | t}}
|
||||
%h5{ bo: { if: "enterprise.type != 'own'" } } {{'registration_detail_enterprise' | t}}
|
||||
%h5{ bo: { if: "enterprise.type == 'own'" } } {{'registration_detail_producer' | t}}
|
||||
|
||||
%form{ name: 'details', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "selectIfValid('contact',details)" } }
|
||||
|
||||
.row
|
||||
.small-12.medium-9.large-12.columns.end
|
||||
.field
|
||||
%label{ for: 'enterprise_name', bo: { if: "enterprise.type != 'own'" } } Enterprise Name:
|
||||
%label{ for: 'enterprise_name', bo: { if: "enterprise.type == 'own'" } } Farm Name:
|
||||
%input.chunky{ id: 'enterprise_name', name: 'name', placeholder: "e.g. Charlie's Awesome Farm", required: true, ng: { model: 'enterprise.name' } }
|
||||
%label{ for: 'enterprise_name', bo: { if: "enterprise.type != 'own'" } } {{'registration_detail_name_enterprise' | t}}
|
||||
%label{ for: 'enterprise_name', bo: { if: "enterprise.type == 'own'" } } {{'registration_detail_name_producer' | t}}
|
||||
%input.chunky{ id: 'enterprise_name', name: 'name', placeholder: "{{'registration_detail_name_placeholder' | t}}", required: true, ng: { model: 'enterprise.name' } }
|
||||
%span.error{ ng: { show: "details.name.$error.required && submitted" } }
|
||||
Please choose a unique name for your enterprise
|
||||
{{'registration_detail_name_error' | t}}
|
||||
|
||||
.row
|
||||
.small-12.medium-9.large-6.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_address' } Address line 1:
|
||||
%input.chunky{ id: 'enterprise_address', name: 'address1', required: true, placeholder: "e.g. 123 Cranberry Drive", required: true, ng: { model: 'enterprise.address.address1' } }
|
||||
%label{ for: 'enterprise_address' } {{'registration_detail_address1' | t}}
|
||||
%input.chunky{ id: 'enterprise_address', name: 'address1', required: true, placeholder: "{{'registration_detail_address1_placeholder' | t}}", required: true, ng: { model: 'enterprise.address.address1' } }
|
||||
%span.error{ ng: { show: "details.address1.$error.required && submitted" } }
|
||||
Please enter an address
|
||||
{{'registration_detail_address1_error' | t}}
|
||||
.field
|
||||
%label{ for: 'enterprise_address2' } Address line 2:
|
||||
%label{ for: 'enterprise_address2' } {{'registration_detail_address2' | t}}
|
||||
%input.chunky{ id: 'enterprise_address2', name: 'address2', required: false, placeholder: "", required: false, ng: { model: 'enterprise.address.address2' } }
|
||||
|
||||
.small-12.medium-9.large-6.columns.end
|
||||
.row
|
||||
.small-12.medium-8.large-8.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_city' } Suburb:
|
||||
%input.chunky{ id: 'enterprise_city', name: 'city', required: true, placeholder: "e.g. Northcote", ng: { model: 'enterprise.address.city' } }
|
||||
%label{ for: 'enterprise_city' } {{'registration_detail_suburb' | t}}
|
||||
%input.chunky{ id: 'enterprise_city', name: 'city', required: true, placeholder: "{{'registration_detail_suburb_placeholder' | t}}", ng: { model: 'enterprise.address.city' } }
|
||||
%span.error{ ng: { show: "details.city.$error.required && submitted" } }
|
||||
Please enter a suburb
|
||||
{{'registration_detail_suburb_error' | t}}
|
||||
.small-12.medium-4.large-4.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_zipcode' } Postcode:
|
||||
%input.chunky{ id: 'enterprise_zipcode', name: 'zipcode', required: true, placeholder: "e.g. 3070", ng: { model: 'enterprise.address.zipcode' } }
|
||||
%label{ for: 'enterprise_zipcode' } {{'registration_detail_postcode' | t}}
|
||||
%input.chunky{ id: 'enterprise_zipcode', name: 'zipcode', required: true, placeholder: "{{'registration_detail_postcode_placeholder' | t}}", ng: { model: 'enterprise.address.zipcode' } }
|
||||
%span.error{ ng: { show: "details.zipcode.$error.required && submitted" } }
|
||||
Postcode required
|
||||
{{'registration_detail_postcode_error' | t}}
|
||||
.row
|
||||
.small-12.medium-4.large-4.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_state' } State:
|
||||
%label{ for: 'enterprise_state' } {{'registration_detail_state' | t}}
|
||||
%select.chunky{ id: 'enterprise_state', name: 'state', ng: { model: 'enterprise.address.state_id', options: 's.id as s.abbr for s in enterprise.country.states', show: 'countryHasStates()', required: 'countryHasStates()' } }
|
||||
%span.error{ ng: { show: "details.state.$error.required && submitted" } }
|
||||
State required
|
||||
{{'registration_detail_state_error' | t}}
|
||||
.small-12.medium-8.large-8.columns
|
||||
.field
|
||||
%label{ for: 'enterprise_country' } Country:
|
||||
%label{ for: 'enterprise_country' } {{'registration_detail_country' | t}}
|
||||
%select.chunky{ id: 'enterprise_country', name: 'country', required: true, ng: { model: 'enterprise.country', options: 'c as c.name for c in countries' } }
|
||||
%span.error{ ng: { show: "details.country.$error.required && submitted" } }
|
||||
Please select a country
|
||||
/ .small-12.medium-12.large-5.hide-for-small-only
|
||||
/ %h6
|
||||
/ Location display
|
||||
/ %i.ofn-i_013-help.has-tip{ 'data-tooltip' => true, title: "Choose how you want to display your enterprise's address on the Open Food Network. By default, full location is shown everywhere including street name and number."}
|
||||
/ .row
|
||||
/ .small-12.columns
|
||||
/ %label.indent-checkbox
|
||||
/ %input{ type: 'checkbox', id: 'enterpise_suburb_only', ng: { model: 'enterprise.suburb_only' } }
|
||||
/ Hide my street name and street number from the public (ie. only show the suburb)
|
||||
/ .small-12.columns
|
||||
/ %label.indent-checkbox
|
||||
/ %input{ type: 'checkbox', id: 'enterprise_on_map', ng: { model: 'enterprise.on_map' } }
|
||||
/ Blur my location on the map (show an approximate, not exact pin)
|
||||
{{'registration_detail_country_error' | t}}
|
||||
|
||||
|
||||
.row.buttons
|
||||
.small-12.columns
|
||||
%hr
|
||||
%input.button.primary.right{ type: "submit", value: "Continue" }
|
||||
%input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" }
|
||||
|
||||
@@ -2,23 +2,14 @@
|
||||
.row
|
||||
.small-12.columns.pad-top
|
||||
%header
|
||||
%h2 Finished!
|
||||
%h2 {{'registration_finished_headline' | t}}
|
||||
.panel.callout
|
||||
%p
|
||||
Thanks for filling out the details for
|
||||
%span{ ng: { class: "{brick: !enterprise.is_primary_producer, turquoise: enterprise.is_primary_producer}" } }
|
||||
{{ enterprise.name }}
|
||||
%p You can change or update your enterprise at any stage by logging into Open Food Network and going to Admin.
|
||||
%p{ "ng-bind" => "'registration_finished_thanks' | t:{enterprise: enterprise.name}" }
|
||||
%p {{'registration_finished_login' | t}}
|
||||
.row
|
||||
.small-12.columns.text-center
|
||||
%h4
|
||||
Activate
|
||||
%span{ ng: { class: "{brick: !enterprise.is_primary_producer, turquoise: enterprise.is_primary_producer}" } }
|
||||
{{ enterprise.name }}
|
||||
%h4{ "ng-bind" => "'registration_finished_activate' | t:{enterprise: enterprise.name}" }
|
||||
|
||||
%p
|
||||
We've sent a confirmation email to
|
||||
%strong {{ enterprise.email }} if it hasn't been activated before.
|
||||
%br Please follow the instructions there to make your enterprise visible on the Open Food Network.
|
||||
%p{ "ng-bind-html" => "t('registration_finished_activate_instruction_html', {email: enterprise.email})"}
|
||||
|
||||
%a.button.primary{ type: "button", href: "/" } Open Food Network home >
|
||||
%a.button.primary{ type: "button", href: "/" } {{'registration_finished_action' | t}} >
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
.row
|
||||
.small-12.columns
|
||||
%header
|
||||
%h2 Thanks!
|
||||
%h5 Let's upload some pretty pictures so your profile looks great! :)
|
||||
%h2 {{'registration_images_headline' | t}}
|
||||
%h5 {{'registration_images_description' | t}}
|
||||
|
||||
%form{ name: 'images', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "select('social')" } }
|
||||
.row{ ng: { repeat: 'image_step in imageSteps', show: "imageStep == image_step" } }
|
||||
@@ -18,5 +18,5 @@
|
||||
|
||||
.row.buttons.pad-top{ ng: { if: "imageStep == 'promo'" } }
|
||||
.small-12.columns
|
||||
%input.button.secondary{ type: "button", value: "Back", ng: { click: "imageSelect('logo')" } }
|
||||
%input.button.primary.right{ type: "submit", value: "Continue" }
|
||||
%input.button.secondary{ type: "button", value: "{{'back' | t}}", ng: { click: "imageSelect('logo')" } }
|
||||
%input.button.primary.right{ type: "submit", value: "{{'continue' | t}}" }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user