Compare commits

..

3 Commits

Author SHA1 Message Date
Maikel Linke
3c3c3394a5 Add spanish translations manually
A change in the Transifex API made the automated commit fail. Hence
doing it manually here.
2017-07-12 11:30:47 +10:00
Transifex-Openfoodnetwork
5b3816fa9e Updating translations for config/locales/fr.yml [skip ci] 2017-07-01 16:17:12 +10:00
Transifex-Openfoodnetwork
3507bae002 Updating translations for config/locales/nb.yml [skip ci] 2017-06-30 17:54:18 +10:00
1104 changed files with 9492 additions and 46553 deletions

View File

@@ -1,37 +1,13 @@
version: "2"
plugins:
engines:
rubocop:
enabled: true
channel: "rubocop-0-55"
scss-lint:
enabled: false
duplication:
enabled: true
exclude_patterns:
- "db/**"
- "config/initializers/active_record_postgresql_referential_integrity_patch.rb"
checks:
argument-count:
enabled: false
complex-logic:
enabled: true
file-lines:
enabled: false
method-complexity:
enabled: false
method-count:
enabled: false
method-lines:
enabled: false
nested-control-flow:
enabled: true
return-statements:
enabled: true
similar-code:
enabled: true
identical-code:
enabled: true
exclude_patterns:
- "spec/**/*"
- "vendor/**/*"
- "app/assets/javascripts/shared/*"
ratings:
paths:
- app/**
- lib/**
- "**.rb"
exclude_paths:
- spec/**/*
- vendor/**/*

View File

@@ -1,42 +0,0 @@
<!--- If what you want to file is not a bug, please use the [Feature
template](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Feature-template)
instead -->
<!--- Provide a general summary of the issue in the Title above -->
## Description
<!--- Provide a more detailed introduction to the issue itself, and why you consider it to be a bug -->
## Expected Behavior
<!--- Tell us what should happen -->
## Actual Behavior
<!--- Tell us what happens instead -->
## Steps to Reproduce
<!--- Provide an unambiguous set of steps to reproduce this bug -->
<!--- Include code to reproduce, if relevant -->
1.
2.
3.
4.
## Animated Gif/Screenshot
<!-- Provide a screenshot or brief animated gif reproducing the bug. Linux users can use
[Peek](https://github.com/phw/peek#ubuntu) while Mac users can use [Recordit](http://recordit.co/) -->
## Context
<!--- How has this bug affected you? What were you trying to accomplish? -->
## Severity
<!--- Use the [Bug severity
guideline](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Bug-severity) to assign one to this bug -->
## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
* Version used:
* Browser name and version:
* Operating System and version (desktop or mobile):
## Possible Fix
<!--- Not obligatory, but suggest a fix or reason for the bug -->

View File

@@ -1,32 +0,0 @@
#### What? Why?
Closes #[the issue number this PR is related to]
[Explain why is this change needed and the solution you propose. Provide
context for others to understand it]
#### What should we test?
[List which features should be tested and how]
[Should we test on mobile?]
#### Release notes
[In case this should be present in the release notes, please write them or
remove this section otherwise]
#### How is this related to the Spree upgrade?
[Any known conflicts with the Spree Upgrade? explain them or remove this section
otherwise]
#### Discourse thread
[Is there a discussion about this in Discourse? add the link if so or remove
this section otherwise]
#### Dependencies
[Does this PR depend on another one? add the link of so or remove this section
otherwise]

3
.gitignore vendored
View File

@@ -1,6 +1,5 @@
.bundle
.rbenv-version
.byebug_history
.swp
*.swo
*.swp
@@ -32,6 +31,7 @@ public/stylesheets
public/images
public/spree
config/abr.yml
config/heroku_env.rb
config/newrelic.yml
config/initializers/feature_toggle.rb
config/initializers/db2fog.rb
@@ -40,4 +40,3 @@ coverage
libpeerconnection.log
/config/application.yml
node_modules
vendor/bundle/

View File

@@ -1 +0,0 @@
5.12.0

View File

@@ -11,11 +11,7 @@ AllCops:
- 'db/**/*'
- 'config/**/*'
- 'script/**/*'
- 'vendor/**/*'
- 'node_modules/**/*'
- !ruby/regexp /old_and_unused\.rb$/
# The parser gem fails to parse this file with out current Ruby version.
- 'spec/factories.rb'
# OFN SETTINGS
# Cop settings that have been agreed upon by the OFN community
@@ -29,14 +25,6 @@ Style/Documentation:
Style/StringLiterals:
Enabled: false
Style/HashSyntax:
Enabled: true
EnforcedStyle: ruby19_no_mixed_keys
Layout/MultilineMethodCallIndentation:
Enabled: true
EnforcedStyle: indented
# TEMPORARY/CONTESTED SETTINGS
# These are still to be decided upon, but recommended for inclusion by
# oeoeaio after scrutinising offenses the codebase
@@ -59,10 +47,6 @@ Lint/UselessAssignment:
Rails/DynamicFindBy:
Enabled: false
# Same as above, #find_by is not available until Rails 4
Rails/FindBy:
Enabled: false
# This should be the programmer's discretion, perhaps we should review all of
# the uses of it an make specific exceptions though.
Rails/SkipsModelValidations:
@@ -145,11 +129,7 @@ Style/TrailingCommaInArguments:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styletrailingcommainarguments
Style/TrailingCommaInArrayLiteral:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styletrailingcommainliteral
Style/TrailingCommaInHashLiteral:
Style/TrailingCommaInLiteral:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styletrailingcommainliteral
@@ -157,10 +137,6 @@ Style/WordArray:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylewordarray
Style/SymbolArray:
Enabled: false
StyleGuide: https://rubocop.readthedocs.io/en/latest/cops_style/#stylesymbolarray
Lint/AmbiguousRegexpLiteral:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#lintambiguousregexpliteral

File diff suppressed because it is too large Load Diff

View File

@@ -4,8 +4,6 @@ cache: bundler
bundler_args: --without development
rvm:
- "2.1.5"
addons:
postgresql: "9.5"
# Set the timezone for phantomjs with TZ
# Set the timezone for karma with TIMEZONE
@@ -42,6 +40,7 @@ before_script:
script:
- 'if [ "$KARMA" = "true" ]; then bundle exec rake karma:run; else echo "Skipping karma run"; fi'
#- "KNAPSACK_GENERATE_REPORT=true bundle exec rspec spec"
- "bundle exec rake 'knapsack:rspec[--tag ~performance]'"
after_success:

View File

@@ -1,68 +1,36 @@
See this here post on raising a github issue:
https://community.openfoodnetwork.org/t/how-to-raise-a-github-issue/912
# Contributing
We love pull requests from everyone. Any contribution is valuable, but there are two issue streams that we especially love people to work on:
1) Our delivery backlog, is managed via a ZenHub board (ZenHub extensions are available for most major browsers). We use a Kanban-style approach, whereby devs pick issues from the top of the backlog which has been organised according to current priorities. If you have some time and are interested in working on some issues from the backlog, please make yourself known on the [#dev](https://openfoodnetwork.slack.com/messages/C2GQ45KNU) channel on Slack and we can direct you to the most appropriate issue to pick up.
We love pull requests from everyone. Here are some instructions for
contributing code to Open Food Network. See the [developer wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki) for more information.
2) Our list of bugs and other self-contained issues that we consider to be a good starting point for new contributors, or devs who arent able to commit to seeing a whole feature through. These issues are marked with the `# good first issue` label.
Fork, then clone the repo:
## Set up
git clone git@github.com:your-username/openfoodnetwork.git
Set up your local development environment by following the appropriate guide from the `Development environment setup` section in the [developer wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki).
Follow the instructions in README.markdown to set up your machine.
Add an `upstream` remote that points to the main repo:
Make sure the tests pass:
cd ~/location-of-your-local-ofn-repo
git remote add upstream https://github.com/openfoodfoundation/openfoodnetwork
rspec spec
If you haven't already done so, fork this repo using the `Fork` button in the top-right corner of this screen. Then ensure that your fork is listed as the `origin` remote on your local machine.
Make your change. Add tests for your change. Make the tests pass:
git remote set-url origin https://github.com/your-username/openfoodnetwork
rspec spec
Fetch the latest version of `master` from `upstream` (ie. the main repo):
Push to your fork and [submit a pull request][pr].
git fetch upstream master
[pr]: https://github.com/openfoodfoundation/openfoodnetwork/compare/
Create a new branch on your local machine for (based on `upstream/master`):
At this point you're waiting on us. We may suggest some changes or
improvements or alternatives.
git checkout -b branch-name-here --no-track upstream/master
To increase the chance that your pull request is swiftly accepted:
If you want to run the whole test suite, we recommend using a free CI service to run your tests in parallel. Running the whole suite locally in series is likely to take > 40 minutes. [TravisCI][travis] and [SemaphoreCI][semaphore] both work great in our experience. Either way, make sure the tests pass on your new branch:
bundle exec rspec spec
## Making a change
Make your changes to the codebase. We recommend using TDD. Add a test, make changes and get the test suite back to green.
bundle exec rspec spec
Once the tests are passing you can commit your changes. See [Making a great commit][great-commit] for more tips.
git add .
git commit -m "Add a concise commit message describing your change here"
Push your changes to a branch on your fork:
git push origin branch-name-here
## Submitting a Pull Request
Use the GitHub UI to submit a [new pull request][pr] against upstream/master. To increase the chances that your pull request is swiftly accepted please have a look at our guide to [making a great pull request][great-pr].
TL;DR:
* Write tests
* Make sure the whole test suite is passing
* Keep your PR small, with a single focus
* Maintain a clean commit history
* Use a style consistent with the rest of the codebase
* Before submitting, [rebase your work][rebase] on the current master branch
From here, your pull request will progress through the [Review, Test, Merge & Deploy process][process].
[pr]: https://github.com/openfoodfoundation/openfoodnetwork/compare/
[great-pr]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Making-a-great-pull-request
[great-commit]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Making-a-great-commit
[process]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/The-process-of-review%2C-test%2C-merge-and-deploy
[rebase]: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/workflow-walkthrough
[travis]: https://travis-ci.org/
[semaphore]: https://semaphoreci.com/

61
Gemfile
View File

@@ -1,39 +1,30 @@
source 'https://rubygems.org'
ruby "2.1.5"
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
gem 'rails', '~> 3.2.22'
gem 'rails', '3.2.21'
gem 'rails-i18n', '~> 3.0.0'
gem 'i18n', '~> 0.6.11'
gem 'i18n-js', '~> 3.0.0'
# Patched version. See http://rubysec.com/advisories/CVE-2015-5312/.
gem 'nokogiri', '>= 1.6.7.1'
gem 'pg'
gem 'spree', github: 'openfoodfoundation/spree', branch: 'step-6a', ref: '86bf87f1b1e1b299edc8cd10a2486e44ba0a3987'
gem 'spree', github: 'openfoodfoundation/spree', branch: 'spree-upgrade-step1c'
gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable'
gem 'spree_auth_devise', github: 'openfoodfoundation/spree_auth_devise', branch: 'spree-upgrade-intermediate'
gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '1-3-stable'
# Our branch contains two changes
# - Pass customer email and phone number to PayPal (merged to upstream master)
# - Change type of password from string to password to hide it in the form
gem 'spree_paypal_express', github: "openfoodfoundation/better_spree_paypal_express", branch: "spree-upgrade-intermediate"
#gem 'spree_paypal_express', github: "spree-contrib/better_spree_paypal_express", branch: "1-3-stable"
gem 'stripe', '~> 3.3.1'
# We need at least this version to have Digicert's root certificate
# which is needed for Pin Payments (and possibly others).
gem 'activemerchant', '~> 1.78'
gem 'oauth2', '~> 1.2.0' # Used for Stripe Connect
gem 'jwt', '~> 1.5'
gem 'spree_paypal_express', :github => "openfoodfoundation/better_spree_paypal_express", :branch => "hide-password"
#gem 'spree_paypal_express', :github => "spree-contrib/better_spree_paypal_express", :branch => "1-3-stable"
gem 'delayed_job_active_record'
gem 'daemons'
# Fix bug in simple_form preventing collection_check_boxes usage within form_for block
# When merged, revert to upstream gem
gem 'simple_form', github: 'RohanM/simple_form'
gem 'simple_form', :github => 'RohanM/simple_form'
gem 'unicorn'
gem 'angularjs-rails', '1.5.5'
@@ -51,15 +42,14 @@ gem 'representative_view'
gem 'rabl'
gem "active_model_serializers"
gem 'oj'
gem 'deface', github: 'spree/deface', ref: '1110a13'
gem 'deface', :github => 'spree/deface', :ref => '1110a13'
gem 'paperclip'
gem 'dalli'
gem 'geocoder'
gem 'gmaps4rails'
gem 'spinjs-rails'
gem 'rack-ssl', require: 'rack/ssl'
gem 'rack-rewrite'
gem 'custom_error_message', github: 'jeremydurham/custom-err-msg'
gem 'rack-ssl', :require => 'rack/ssl'
gem 'custom_error_message', :github => 'jeremydurham/custom-err-msg'
gem 'angularjs-file-upload-rails', '~> 1.1.6'
gem 'roadie-rails', '~> 1.0.3'
gem 'figaro'
@@ -67,7 +57,6 @@ gem 'blockenspiel'
gem 'acts-as-taggable-on', '~> 3.4'
gem 'paper_trail', '~> 3.0.8'
gem 'diffy'
gem 'skylight', '< 2.0'
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary'
@@ -75,7 +64,6 @@ gem 'wkhtmltopdf-binary'
gem 'foreigner'
gem 'immigrant'
gem 'roo', '~> 2.7.0'
gem 'roo-xls', '~> 1.1.0'
gem 'whenever', require: false
@@ -103,22 +91,23 @@ gem 'jquery-rails'
gem 'jquery-migrate-rails'
gem 'css_splitter'
gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', ref: '60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c'
gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz'
group :test, :development do
# Pretty printed test output
gem 'fuubar', '~> 2.2.0'
gem 'rspec-rails', ">= 3.5.2"
gem 'turn', '~> 0.8.3', :require => false
gem 'fuubar'
gem 'rspec-rails'
gem 'shoulda-matchers'
gem "factory_bot_rails", require: false
gem 'capybara', '>= 2.15.4'
gem 'database_cleaner', '0.7.1', require: false
gem 'factory_girl_rails', :require => false
gem 'capybara'
gem 'database_cleaner', '0.7.1', :require => false
gem 'awesome_print'
gem 'letter_opener', '>= 1.4.1'
gem 'letter_opener'
gem 'timecop'
gem 'poltergeist', '>= 1.16.0'
gem 'poltergeist'
gem 'rspec-retry'
gem 'json_spec', '~> 1.1.4'
gem 'json_spec'
gem 'unicorn-rails'
gem 'atomic'
gem 'knapsack'
@@ -131,20 +120,14 @@ group :test do
end
group :development do
gem 'byebug', '~> 9.0.0' # 9.1 requires ruby 2.2
gem 'pry-byebug', '>= 3.4.3'
gem 'pry-byebug'
gem 'debugger-linecache'
gem 'guard'
gem 'listen', '3.0.8' # 3.1.0 requires ruby 2.2
gem 'guard-livereload'
gem 'rack-livereload'
gem 'guard-rails'
gem 'guard-rspec', '~> 4.7.3'
gem 'guard-zeus'
gem 'guard-rspec'
gem 'parallel_tests'
gem 'rubocop', '>= 0.49.1'
# 1.0.9 fixed openssl issues on macOS https://github.com/eventmachine/eventmachine/issues/602
# While we don't require this gem directly, no dependents forced the upgrade to a version
# greater than 1.0.9, so we just required the latest available version here.
gem 'eventmachine', '>= 1.2.3'
end

View File

@@ -1,5 +1,5 @@
GIT
remote: https://github.com/RohanM/simple_form.git
remote: git://github.com/RohanM/simple_form.git
revision: 45f08a213b40f3d4bda5f5398db841137587160a
specs:
simple_form (2.0.2)
@@ -7,104 +7,74 @@ GIT
activemodel (~> 3.0)
GIT
remote: https://github.com/jeremydurham/custom-err-msg.git
remote: git://github.com/jeremydurham/custom-err-msg.git
revision: 3a8ec9dddc7a5b0aab7c69a6060596de300c68f4
specs:
custom_error_message (1.1.1)
GIT
remote: https://github.com/openfoodfoundation/better_spree_paypal_express.git
revision: 8d95f4544c682634812becaf50999fba0cd04df0
branch: spree-upgrade-intermediate
remote: git://github.com/openfoodfoundation/better_spree_paypal_express.git
revision: 840d973cd5bd3250b17674a624dad494aeb09eb3
branch: hide-password
specs:
spree_paypal_express (2.0.3)
paypal-sdk-merchant (= 1.106.1)
spree_core (~> 1.3.99)
spree_core (~> 1.3.4)
GIT
remote: https://github.com/openfoodfoundation/ofn-qz.git
revision: 60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c
ref: 60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c
remote: git://github.com/openfoodfoundation/ofn-qz.git
revision: 024680ccea429b2e5428d7b964fa67c52add34ec
specs:
ofn-qz (0.1.0)
railties (~> 3.1)
GIT
remote: https://github.com/openfoodfoundation/spree.git
revision: 86bf87f1b1e1b299edc8cd10a2486e44ba0a3987
ref: 86bf87f1b1e1b299edc8cd10a2486e44ba0a3987
branch: step-6a
remote: git://github.com/openfoodfoundation/spree.git
revision: a4c439570b77afa50f9e36299811f293232bd281
branch: spree-upgrade-step1c
specs:
spree (1.3.99)
spree_api (= 1.3.99)
spree_backend (= 1.3.99)
spree_cmd (= 1.3.99)
spree_core (= 1.3.99)
spree_dash (= 1.3.99)
spree_frontend (= 1.3.99)
spree_promo (= 1.3.99)
spree_sample (= 1.3.99)
spree_api (1.3.99)
rabl (= 0.7.2)
spree_core (= 1.3.99)
versioncake (= 0.4.0)
spree_backend (1.3.99)
deface (>= 0.9.0)
jquery-rails (~> 2.0)
rails (~> 3.2.8)
select2-rails (~> 3.2)
spree_api (= 1.3.99)
spree_core (= 1.3.99)
stringex (~> 1.3.2)
spree_cmd (1.3.99)
thor (>= 0.14.6)
spree_core (1.3.99)
activemerchant (~> 1.50)
acts_as_list (= 0.1.9)
activemerchant (~> 1.50.0)
acts_as_list (= 0.1.4)
awesome_nested_set (= 2.1.5)
aws-sdk (~> 1.11.1)
cancan (= 1.6.8)
deface (>= 0.9.0)
ffaker (~> 1.15.0)
highline (= 1.6.15)
httparty (= 0.9.0)
highline (= 1.6.11)
jquery-rails (~> 2.0)
json (>= 1.5.5)
kaminari (= 0.13.0)
money (= 5.1.0)
money (= 5.0.0)
paperclip (~> 3.0)
rabl (= 0.7.2)
rails (~> 3.2.13)
ransack (= 0.7.2)
select2-rails (~> 3.2)
state_machine (= 1.2.0)
stringex (~> 1.3.2)
truncate_html (= 0.9.2)
spree_dash (1.3.99)
httparty (~> 0.9.0)
spree_backend (= 1.3.99)
spree_frontend (= 1.3.99)
spree_frontend (1.3.99)
deface (>= 0.9.0)
jquery-rails (~> 2.2.1)
rails (~> 3.2.8)
select2-rails (~> 3.2)
spree_api (= 1.3.99)
httparty (~> 0.8.1)
spree_core (= 1.3.99)
spree_promo (1.3.99)
spree_core (= 1.3.99)
stringex (~> 1.3.2)
spree_sample (1.3.99)
spree_core (= 1.3.99)
GIT
remote: https://github.com/openfoodfoundation/spree_auth_devise.git
revision: da9eecefc6fe13dedf4c6f3febec79caad839ec3
branch: spree-upgrade-intermediate
specs:
spree_auth_devise (2.0.0)
devise (~> 2.2.5)
devise-encryptable (= 0.1.2)
spree_backend (~> 1.3.6)
spree_core (~> 1.3.6)
spree_frontend (~> 1.3.6)
GIT
remote: https://github.com/spree/deface.git
remote: git://github.com/spree/deface.git
revision: 1110a1336252109bce7f98f9182042e0bc2930ae
ref: 1110a13
specs:
@@ -114,7 +84,18 @@ GIT
rails (>= 3.1)
GIT
remote: https://github.com/spree/spree_i18n.git
remote: git://github.com/spree/spree_auth_devise.git
revision: ba95589a85368297c844f096c2a0c121e5b08138
branch: 1-3-stable
specs:
spree_auth_devise (1.3.0)
cancan (~> 1.6.7)
devise (~> 2.2.3)
devise-encryptable (= 0.1.2)
spree_core
GIT
remote: git://github.com/spree/spree_i18n.git
revision: 752eb67204e9c5a4e22b62591a8fd55fe2285e43
branch: 1-3-stable
specs:
@@ -124,7 +105,7 @@ GIT
spree_core (>= 1.1)
GIT
remote: https://github.com/willrjmarshall/foundation_rails_helper.git
remote: git://github.com/willrjmarshall/foundation_rails_helper.git
revision: 4d5d53fdc4b1fb71e66524d298c5c635de82cfbb
branch: rails3
specs:
@@ -137,12 +118,12 @@ GEM
remote: https://rubygems.org/
specs:
CFPropertyList (2.3.2)
actionmailer (3.2.22.5)
actionpack (= 3.2.22.5)
actionmailer (3.2.21)
actionpack (= 3.2.21)
mail (~> 2.5.4)
actionpack (3.2.22.5)
activemodel (= 3.2.22.5)
activesupport (= 3.2.22.5)
actionpack (3.2.21)
activemodel (= 3.2.21)
activesupport (= 3.2.21)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
@@ -152,30 +133,29 @@ GEM
sprockets (~> 2.2.1)
active_model_serializers (0.8.3)
activemodel (>= 3.0)
activemerchant (1.78.0)
activesupport (>= 3.2.14, < 6.x)
activemerchant (1.50.0)
activesupport (>= 3.2.14, < 5.0.0)
builder (>= 2.1.2, < 4.0.0)
i18n (>= 0.6.9)
nokogiri (~> 1.4)
activemodel (3.2.22.5)
activesupport (= 3.2.22.5)
activemodel (3.2.21)
activesupport (= 3.2.21)
builder (~> 3.0.0)
activerecord (3.2.22.5)
activemodel (= 3.2.22.5)
activesupport (= 3.2.22.5)
activerecord (3.2.21)
activemodel (= 3.2.21)
activesupport (= 3.2.21)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.22.5)
activemodel (= 3.2.22.5)
activesupport (= 3.2.22.5)
activesupport (3.2.22.5)
activeresource (3.2.21)
activemodel (= 3.2.21)
activesupport (= 3.2.21)
activesupport (3.2.21)
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
acts-as-taggable-on (3.5.0)
activerecord (>= 3.2, < 5)
acts_as_list (0.1.9)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
acts_as_list (0.1.4)
addressable (2.3.3)
andand (1.3.3)
angular-rails-templates (0.2.0)
railties (>= 3.1)
@@ -183,8 +163,9 @@ GEM
tilt
angularjs-file-upload-rails (1.1.6)
angularjs-rails (1.5.5)
ansi (1.4.2)
arel (3.0.3)
ast (2.4.0)
ast (2.3.0)
atomic (1.1.99)
awesome_nested_set (2.1.5)
activerecord (>= 3.0.0)
@@ -193,28 +174,33 @@ GEM
json (~> 1.4)
nokogiri (>= 1.4.4)
uuidtools (~> 2.1)
bcrypt (3.1.11)
bcrypt (3.1.7)
bcrypt-ruby (3.1.5)
bcrypt (>= 3.1.3)
blockenspiel (0.4.5)
bugsnag (4.1.0)
builder (3.0.4)
byebug (9.0.6)
byebug (2.7.0)
columnize (~> 0.3)
debugger-linecache (~> 1.2)
cancan (1.6.8)
capybara (2.18.0)
capybara (2.7.1)
addressable
mini_mime (>= 0.1.3)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (>= 2.0, < 4.0)
xpath (~> 2.0)
celluloid (0.15.2)
timers (~> 1.1.0)
chronic (0.10.2)
chunky_png (1.3.4)
climate_control (0.1.0)
climate_control (0.0.3)
activesupport (>= 3.0)
cliver (0.3.2)
cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0)
coderay (1.1.2)
coderay (1.0.9)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
@@ -222,7 +208,8 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.10.0)
colorize (0.8.1)
colorize (0.7.7)
columnize (0.9.0)
compass (1.0.3)
chunky_png (~> 1.2)
compass-core (~> 1.0.2)
@@ -239,8 +226,8 @@ GEM
compass (~> 1.0.0)
sass-rails (<= 5.0.1)
sprockets (< 2.13)
crack (0.4.3)
safe_yaml (~> 1.0.0)
crack (0.4.1)
safe_yaml (~> 0.9.0)
css_parser (1.3.5)
addressable
css_splitter (0.4.5)
@@ -253,11 +240,11 @@ GEM
fog (~> 1.0)
rails (~> 3.0)
debugger-linecache (1.2.0)
delayed_job (4.1.4)
activesupport (>= 3.0, < 5.2)
delayed_job_active_record (4.1.2)
activerecord (>= 3.0, < 5.2)
delayed_job (>= 3.0, < 5)
delayed_job (4.0.4)
activesupport (>= 3.0, < 4.2)
delayed_job_active_record (4.0.2)
activerecord (>= 3.0, < 4.2)
delayed_job (>= 3.0, < 4.1)
devise (2.2.8)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
@@ -265,24 +252,22 @@ GEM
warden (~> 1.2.1)
devise-encryptable (0.1.2)
devise (>= 2.1.0)
diff-lcs (1.3)
diff-lcs (1.2.4)
diffy (3.1.0)
em-websocket (0.5.1)
em-websocket (0.5.0)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
http_parser.rb (~> 0.5.3)
erubis (2.7.0)
eventmachine (1.2.3)
eventmachine (1.0.8)
excon (0.45.4)
execjs (2.6.0)
factory_bot (4.8.2)
factory_girl (3.3.0)
activesupport (>= 3.0.0)
factory_bot_rails (4.8.2)
factory_bot (~> 4.8.2)
factory_girl_rails (3.3.0)
factory_girl (~> 3.3.0)
railties (>= 3.0.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
ffaker (1.15.0)
ffi (1.9.18)
ffi (1.9.3)
figaro (0.7.0)
bundler (~> 1.0)
rails (>= 3, < 5)
@@ -403,44 +388,38 @@ GEM
foundation-rails (5.5.0.0)
railties (>= 3.1.0)
sass (>= 3.2.0, < 3.4)
fuubar (2.2.0)
rspec-core (~> 3.0)
fuubar (1.3.3)
rspec (>= 2.14.0, < 3.1.0)
ruby-progressbar (~> 1.4)
geocoder (1.1.8)
gmaps4rails (1.5.6)
guard (2.14.1)
guard (2.2.4)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
listen (~> 2.1)
lumberjack (~> 1.0)
nenv (~> 0.1)
notiffany (~> 0.0)
pry (>= 0.9.12)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-compat (1.2.1)
guard-livereload (2.5.2)
guard-livereload (2.0.1)
em-websocket (~> 0.5)
guard (~> 2.8)
guard-compat (~> 1.0)
guard (~> 2.0)
multi_json (~> 1.8)
guard-rails (0.7.2)
guard (~> 2.11)
guard-compat (~> 1.0)
guard-rspec (4.7.3)
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
guard-rails (0.4.7)
guard (>= 0.2.2)
guard-rspec (4.0.4)
guard (>= 2.1.1)
rspec (~> 2.14)
guard-zeus (0.0.1)
guard
zeus
haml (4.0.4)
tilt
highline (1.6.15)
highline (1.6.11)
hike (1.2.3)
http_parser.rb (0.6.0)
httparty (0.9.0)
http_parser.rb (0.5.3)
httparty (0.8.3)
multi_json (~> 1.0)
multi_xml
i18n (0.6.11)
i18n-js (3.0.0)
i18n (~> 0.6, >= 0.6.6)
immigrant (0.1.6)
activerecord (>= 3.0)
foreigner (>= 1.2.1)
@@ -448,60 +427,50 @@ GEM
ipaddress (0.8.0)
journey (1.0.4)
jquery-migrate-rails (1.2.1)
jquery-rails (2.2.2)
jquery-rails (2.3.0)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.8.6)
json_spec (1.1.5)
json (1.8.3)
json_spec (1.1.1)
multi_json (~> 1.0)
rspec (>= 2.0, < 4.0)
jwt (1.5.4)
rspec (~> 2.0)
kaminari (0.13.0)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
railties (>= 3.0.0)
kgio (2.9.3)
knapsack (1.16.0)
knapsack (1.5.1)
rake
launchy (2.4.3)
timecop (>= 0.1.0)
launchy (2.1.2)
addressable (~> 2.3)
letter_opener (1.6.0)
launchy (~> 2.2)
letter_opener (1.0.0)
launchy (>= 2.0.4)
libv8 (3.16.14.11)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
lumberjack (1.0.12)
mail (2.5.5)
listen (2.2.0)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
lumberjack (1.0.4)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
method_source (0.9.0)
method_source (0.8.2)
mime-types (1.25.1)
mini_mime (0.1.4)
mini_portile2 (2.1.0)
mini_portile2 (2.0.0)
momentjs-rails (2.5.1)
railties (>= 3.1)
money (5.1.0)
i18n (~> 0.6.0)
money (5.0.0)
i18n (~> 0.4)
json
multi_json (1.12.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nenv (0.3.0)
multi_xml (0.5.5)
newrelic_rpm (3.12.0.288)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
oauth2 (1.2.0)
faraday (>= 0.8, < 0.10)
jwt (~> 1.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
nokogiri (1.6.7.2)
mini_portile2 (~> 2.0.0.rc2)
oj (2.1.2)
orm_adapter (0.5.0)
paper_trail (3.0.9)
paper_trail (3.0.8)
activerecord (>= 3.0, < 5.0)
activesupport (>= 3.0, < 5.0)
paperclip (3.5.4)
@@ -512,70 +481,71 @@ GEM
parallel (1.11.2)
parallel_tests (2.14.1)
parallel
parser (2.5.1.0)
ast (~> 2.4.0)
parser (2.4.0.0)
ast (~> 2.2)
paypal-sdk-core (0.2.10)
multi_json (~> 1.0)
xml-simple
paypal-sdk-merchant (1.106.1)
paypal-sdk-core (~> 0.2.3)
pg (0.13.2)
poltergeist (1.16.0)
poltergeist (1.9.0)
capybara (~> 2.1)
cliver (~> 0.3.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
polyamorous (0.5.0)
activerecord (~> 3.0)
polyglot (0.3.5)
powerpack (0.1.1)
pry (0.11.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-byebug (3.4.3)
byebug (>= 9.0, < 9.1)
pry (~> 0.10)
public_suffix (3.0.0)
pry (0.9.12.2)
coderay (~> 1.0.5)
method_source (~> 0.8)
slop (~> 3.4)
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.7)
rack-cache (1.7.1)
rack-cache (1.6.1)
rack (>= 0.4)
rack-livereload (0.3.16)
rack-livereload (0.3.15)
rack
rack-rewrite (1.5.1)
rack-ssl (1.3.4)
rack
rack-test (0.6.3)
rack (>= 1.0)
rails (3.2.22.5)
actionmailer (= 3.2.22.5)
actionpack (= 3.2.22.5)
activerecord (= 3.2.22.5)
activeresource (= 3.2.22.5)
activesupport (= 3.2.22.5)
rails (3.2.21)
actionmailer (= 3.2.21)
actionpack (= 3.2.21)
activerecord (= 3.2.21)
activeresource (= 3.2.21)
activesupport (= 3.2.21)
bundler (~> 1.0)
railties (= 3.2.22.5)
railties (= 3.2.21)
rails-i18n (3.0.1)
i18n (~> 0.5)
rails (>= 3.0.0, < 4.0.0)
railties (3.2.22.5)
actionpack (= 3.2.22.5)
activesupport (= 3.2.22.5)
railties (3.2.21)
actionpack (= 3.2.21)
activesupport (= 3.2.21)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rainbow (3.0.0)
rainbow (2.2.2)
rake
raindrops (0.13.0)
rake (10.5.0)
rake (11.3.0)
ransack (0.7.2)
actionpack (~> 3.0)
activerecord (~> 3.0)
polyamorous (~> 0.5.0)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rb-fsevent (0.9.3)
rb-inotify (0.9.2)
ffi (>= 0.5.0)
rdoc (3.12.2)
json (~> 1.4)
redcarpet (3.2.3)
@@ -597,44 +567,33 @@ GEM
roo (2.7.1)
nokogiri (~> 1)
rubyzip (~> 1.1, < 2.0.0)
roo-xls (1.1.0)
nokogiri
roo (>= 2.0.0beta1, < 3)
spreadsheet (> 0.9.0)
rspec (3.7.0)
rspec-core (~> 3.7.0)
rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.7.0)
rspec-core (3.7.0)
rspec-support (~> 3.7.0)
rspec-expectations (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-rails (3.7.2)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-core (2.14.4)
rspec-expectations (2.14.0)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.14.2)
rspec-rails (2.14.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.7.0)
rspec-expectations (~> 3.7.0)
rspec-mocks (~> 3.7.0)
rspec-support (~> 3.7.0)
rspec-retry (0.5.6)
rspec-core (> 3.3, < 3.8)
rspec-support (3.7.0)
rubocop (0.55.0)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-retry (0.4.2)
rspec-core
rubocop (0.49.1)
parallel (~> 1.10)
parser (>= 2.5)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 2.2.2, < 4.0)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-ole (1.2.12.1)
ruby-progressbar (1.8.1)
rubyzip (1.2.1)
safe_yaml (1.0.4)
rubyzip (1.2.0)
safe_yaml (0.9.5)
sass (3.3.14)
sass-rails (3.2.6)
railties (~> 3.2.0)
@@ -642,15 +601,11 @@ GEM
tilt (~> 1.3)
select2-rails (3.5.10)
thor (~> 0.14)
shellany (0.0.1)
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
skylight (1.6.1)
shoulda-matchers (1.1.0)
activesupport (>= 3.0.0)
slop (3.4.5)
spinjs-rails (1.3)
rails (>= 3.1)
spreadsheet (1.1.4)
ruby-ole (>= 1.0)
sprockets (2.2.3)
hike (~> 1.2)
multi_json (~> 1.0)
@@ -658,26 +613,27 @@ GEM
tilt (~> 1.1, != 1.3.0)
state_machine (1.2.0)
stringex (1.3.3)
stripe (3.3.1)
faraday (~> 0.9)
therubyracer (0.12.0)
libv8 (~> 3.16.14.0)
ref
thor (0.20.0)
thor (0.19.1)
tilt (1.4.1)
timecop (0.9.1)
timecop (0.8.1)
timers (1.1.0)
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
truncate_html (0.9.2)
truncate_html (0.5.5)
turbo-sprockets-rails3 (0.3.6)
railties (> 3.2.8, < 4.0.0)
sprockets (>= 2.0.0)
tzinfo (0.3.54)
turn (0.8.3)
ansi
tzinfo (0.3.49)
uglifier (2.7.1)
execjs (>= 0.3.0)
json (>= 1.8.0)
unicode-display_width (1.3.2)
unicode-display_width (1.3.0)
unicorn (4.9.0)
kgio (~> 2.6)
rack
@@ -690,12 +646,12 @@ GEM
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
warden (1.2.7)
warden (1.2.3)
rack (>= 1.0)
webmock (1.8.11)
webmock (1.13.0)
addressable (>= 2.2.7)
crack (>= 0.1.7)
websocket-driver (0.7.0)
crack (>= 0.3.2)
websocket-driver (0.6.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
whenever (0.9.2)
@@ -703,16 +659,17 @@ GEM
chronic (>= 0.6.3)
wicked_pdf (1.1.0)
wkhtmltopdf-binary (0.12.3.1)
xml-simple (1.1.5)
xpath (2.1.0)
xml-simple (1.1.4)
xpath (2.0.0)
nokogiri (~> 1.3)
zeus (0.15.4)
method_source (>= 0.6.7)
PLATFORMS
ruby
DEPENDENCIES
active_model_serializers
activemerchant (~> 1.78)
acts-as-taggable-on (~> 3.4)
andand
angular-rails-templates (~> 0.2.0)
@@ -723,8 +680,7 @@ DEPENDENCIES
aws-sdk
blockenspiel
bugsnag
byebug (~> 9.0.0)
capybara (>= 2.15.4)
capybara
coffee-rails (~> 3.2.1)
compass-rails
css_splitter
@@ -737,72 +693,65 @@ DEPENDENCIES
deface!
delayed_job_active_record
diffy
eventmachine (>= 1.2.3)
factory_bot_rails
factory_girl_rails
figaro
foreigner
foundation-icons-sass-rails
foundation-rails
foundation_rails_helper!
fuubar (~> 2.2.0)
fuubar
geocoder
gmaps4rails
guard
guard-livereload
guard-rails
guard-rspec (~> 4.7.3)
guard-rspec
guard-zeus
haml
i18n (~> 0.6.11)
i18n-js (~> 3.0.0)
immigrant
jquery-migrate-rails
jquery-rails
json_spec (~> 1.1.4)
jwt (~> 1.5)
json_spec
knapsack
letter_opener (>= 1.4.1)
listen (= 3.0.8)
letter_opener
momentjs-rails
newrelic_rpm
nokogiri (>= 1.6.7.1)
oauth2 (~> 1.2.0)
ofn-qz!
oj
paper_trail (~> 3.0.8)
paperclip
parallel_tests
pg
poltergeist (>= 1.16.0)
pry-byebug (>= 3.4.3)
poltergeist
pry-byebug
rabl
rack-livereload
rack-rewrite
rack-ssl
rails (~> 3.2.22)
rails (= 3.2.21)
rails-i18n (~> 3.0.0)
redcarpet
representative_view
roadie-rails (~> 1.0.3)
roo (~> 2.7.0)
roo-xls (~> 1.1.0)
rspec-rails (>= 3.5.2)
rspec-rails
rspec-retry
rubocop (>= 0.49.1)
sass (~> 3.3)
sass-rails (~> 3.2.3)
shoulda-matchers
simple_form!
skylight (< 2.0)
spinjs-rails
spree!
spree_auth_devise!
spree_i18n!
spree_paypal_express!
stripe (~> 3.3.1)
therubyracer
timecop
truncate_html
turbo-sprockets-rails3
turn (~> 0.8.3)
uglifier (>= 1.0.3)
unicorn
unicorn-rails
@@ -815,4 +764,4 @@ RUBY VERSION
ruby 2.1.5p273
BUNDLED WITH
1.16.1
1.15.1

View File

@@ -5,7 +5,45 @@ guard 'livereload' do
watch(%r{app/views/.+\.(erb|haml|slim)$})
watch(%r{app/helpers/.+\.rb})
watch(%r{public/.+\.(css|js|html)})
#watch(%r{config/locales/.+\.yml})
# Rails Assets Pipeline
watch(%r{(app|vendor)(/assets/\w+/(.+\.(css|js|html|png|jpg))).*}) { |m| "/assets/#{m[3]}" }
end
#guard 'rails' do
#watch('Gemfile.lock')
#watch(%r{^(config|lib)/.*})
#end
#guard 'zeus' do
## uses the .rspec file
## --colour --fail-fast --format documentation --tag ~slow
#watch(%r{^spec/.+_spec\.rb$})
#watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
#watch(%r{^app/(.+)\.haml$}) { |m| "spec/#{m[1]}.haml_spec.rb" }
#watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
#watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/requests/#{m[1]}_spec.rb"] }
#end
#guard :rspec do
#watch(%r{^spec/.+_spec\.rb$})
#watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
#watch('spec/spec_helper.rb') { "spec" }
## Rails example
#watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
#watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
#watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
#watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
#watch('config/routes.rb') { "spec/routing" }
#watch('app/controllers/application_controller.rb') { "spec/controllers" }
## Capybara features specs
#watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
## Turnip features and steps
#watch(%r{^spec/acceptance/(.+)\.feature$})
#watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
#end

View File

@@ -1,6 +1,5 @@
[![Build Status](https://travis-ci.org/openfoodfoundation/openfoodnetwork.svg?branch=master)](https://travis-ci.org/openfoodfoundation/openfoodnetwork)
[![Code Climate](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork.png)](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork)
[![View performance data on Skylight](https://badges.skylight.io/status/EiXQ6sSKij8y.svg)](https://oss.skylight.io/app/applications/EiXQ6sSKij8y)
# Open Food Network
@@ -46,23 +45,44 @@ You can download the source with the command:
### Get it running
For those new to Rails, the following tutorial will help get you up to speed with configuring a [Rails environment](http://guides.rubyonrails.org/getting_started.html).
For those new to Rails, the following tutorial will help get you up to speed with configuring a Rails environment: http://guides.rubyonrails.org/getting_started.html .
When ready, run `script/setup`. If the script succeeds you're ready to start developing. If not, take a look at the output as it should be informative enough to help you troubleshoot.
First, check your dependencies: Ensure that you have Ruby 2.1.5 installed:
If you run into any other issues getting your local environment up and running please consult [the wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki).
ruby --version
If still you get stuck do not hesitate to open an issue reporting the full output of the script.
Install the project's gem dependencies:
cd openfoodnetwork
bundle install
Configure the site:
cp config/application.yml.example config/application.yml
edit config/application.yml
Create a PostgreSQL user:
* Login as your system postrgresql priviledged user: `sudo -i -u postgres` (this may vary on your OS). Now your prompt looks like: `[postgres@your_host ~]$`
* Create the `ofn` database superuser and give it the password `f00d`:
Now, your dreams of spinning up a development server can be realised:
```
bundle exec rails server
```
To login as Spree default user, use:
```
email: spree@example.com
password: spree123
createuser -s -P ofn
```
Create the development and test databases, using the settings specified in `config/database.yml`, and populate them with a schema and seed data:
rake db:setup
Load some default data for your environment:
rake openfoodnetwork:dev:load_sample_data
At long last, your dreams of spinning up a development server can be realised:
rails server
### Testing
Tests, both unit and integration, are based on RSpec. To run the test suite, first prepare the test database:
@@ -87,9 +107,6 @@ If you want karma to automatically rerun the tests on file modification, use:
./script/karma start
### Multilingual
Do not forget to run `rake tmp:cache:clear` after locales are updated to reload I18n js translations.
## Credits
* Andrew Spinks (http://github.com/andrewspinks)
@@ -102,10 +119,7 @@ Do not forget to run `rake tmp:cache:clear` after locales are updated to reload
* Maikel Linke (https://github.com/mkllnk)
* Lynne Davis (https://github.com/lin-d-hop)
* Paul Mackay (https://github.com/pmackay)
* Steve Pettitt (https://github.com/stveep)
* Matt Yorkley (https://github.com/Matt-Yorkley)
* Pau Pérez (https://github.com/sauloperez)
* Enrico Stano (https://github.com/enricostano)
* Steve Petitt (https://github.com/stveep)
## Licence

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

View File

@@ -1,14 +1,3 @@
angular.module("ofn.admin", [
"ngResource",
"mm.foundation",
"angularFileUpload",
"ngAnimate",
"admin.utils",
"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, */*"

View File

@@ -14,12 +14,12 @@
//= require angular-resource
//= require angular-animate
//= require angular-sanitize
//= require admin/spree_backend
//= require admin/spree_core
//= require admin/spree_auth
//= require admin/spree_promo
//= require admin/spree_paypal_express
//= require ../shared/ng-infinite-scroll.min.js
//= require ../shared/ng-tags-input.min.js
//= require moment
//= require angular-rails-templates
//= require_tree ../templates/admin
//= require ./admin_ofn
@@ -36,12 +36,10 @@
//= require ./orders/orders
//= require ./order_cycles/order_cycles
//= require ./payment_methods/payment_methods
//= require ./product_import/product_import
//= require ./products/products
//= require ./resources/resources
//= require ./shipping_methods/shipping_methods
//= require ./side_menu/side_menu
//= require ./subscriptions/subscriptions
//= require ./tag_rules/tag_rules
//= require ./taxons/taxons
//= require ./utils/utils
@@ -50,17 +48,8 @@
//= require textAngular-rangy.min.js
//= require textAngular-sanitize.min.js
//= require textAngular.min.js
//= require i18n/translations
//= require darkswarm/i18n.js
//= require darkswarm/i18n.translate.js
//= require moment
//= require moment/en-gb.js
//= require moment/es.js
//= require moment/fr.js
//= require moment/it.js
//= require moment/nb.js
//= require moment/pt-br.js
//= require moment/sv.js
//= require ../shared/mm-foundation-tpls-0.8.0.min.js
//= require angularjs-file-upload
//= require_tree .

View File

@@ -28,11 +28,11 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.filterTaxons = [{id: "0", name: ""}].concat $scope.taxons
$scope.producerFilter = "0"
$scope.categoryFilter = "0"
$scope.importDateFilter = "0"
$scope.products = BulkProducts.products
$scope.filteredProducts = []
$scope.currentFilters = []
$scope.limit = 15
$scope.productsWithUnsavedVariants = []
$scope.query = ""
$scope.DisplayProperties = DisplayProperties
@@ -44,7 +44,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
.catch (message) ->
$scope.api_error_msg = message
$scope.$watchCollection '[query, producerFilter, categoryFilter, importDateFilter]', ->
$scope.$watchCollection '[query, producerFilter, categoryFilter]', ->
$scope.limit = 15 # Reset limit whenever searching
$scope.fetchProducts = ->
@@ -53,9 +53,6 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.resetProducts()
$scope.loading = false
$timeout ->
if $scope.showLatestImport
$scope.importDateFilter = $scope.importDates[1].id
$scope.resetProducts = ->
DirtyProducts.clear()
@@ -95,7 +92,6 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.query = ""
$scope.producerFilter = "0"
$scope.categoryFilter = "0"
$scope.importDateFilter = "0"
$scope.editWarn = (product, variant) ->
if (DirtyProducts.count() > 0 and confirm(t("unsaved_changes_confirmation"))) or (DirtyProducts.count() == 0)
@@ -118,6 +114,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
display_name: null
on_hand: null
price: null
$scope.productsWithUnsavedVariants.push product
DisplayProperties.setShowVariants product.id, true
@@ -199,7 +196,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
filters: $scope.currentFilters
).success((data) ->
DirtyProducts.clear()
BulkProducts.updateVariantLists(data.products || [])
BulkProducts.updateVariantLists(data.products, $scope.productsWithUnsavedVariants)
$timeout -> $scope.displaySuccess()
).error (data, status) ->
if status == 400 && data.errors? && data.errors.length > 0

View File

@@ -14,8 +14,8 @@ angular.module("admin.businessModelConfiguration").controller "BusinessModelConf
$scope.cappedBill()
$scope.capReached = ->
return t('no') if !$scope.cap? || Number($scope.cap) == 0
if $scope.bill() >= Number($scope.cap) then t('yes') else t('no')
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

View File

@@ -0,0 +1,2 @@
angular.module("ofn.admin").controller "enterprisesDashboardCtrl", ($scope) ->
$scope.activeTab = "hubs"

View File

@@ -12,7 +12,7 @@ angular.module("admin.customers").controller "customersCtrl", ($scope, $q, $filt
$scope.$watch "shop_id", ->
if $scope.shop_id?
CurrentShop.shop = $filter('filter')($scope.shops, {id: parseInt($scope.shop_id)}, true)[0]
CurrentShop.shop = $filter('filter')($scope.shops, {id: $scope.shop_id})[0]
Customers.index({enterprise_id: $scope.shop_id}).then (data) ->
pendingChanges.removeAll()
$scope.customers_form.$setPristine()

View File

@@ -2,7 +2,6 @@ angular.module("admin.customers").directive 'editAddressDialog', ($compile, $tem
restrict: 'A'
scope: true
link: (scope, element, attr) ->
template = null
scope.errors = []
scope.$watch 'address.country_id', (newVal) ->
@@ -19,19 +18,19 @@ angular.module("admin.customers").directive 'editAddressDialog', ($compile, $tem
else
scope.errors.push(t('admin.customers.index.update_address_error'))
template = $compile($templateCache.get('admin/edit_address_dialog.html'))(scope)
template.dialog(DialogDefaults)
element.bind 'click', (e) ->
if e.target.id == 'bill-address-link'
scope.addressType = 'bill_address'
else
scope.addressType = 'ship_address'
scope.address = scope.customer[scope.addressType]
scope.states = scope.filter_states(scope.address?.country_id)
template = $compile($templateCache.get('admin/edit_address_dialog.html'))(scope)
template.dialog(DialogDefaults)
template.dialog('open')
scope.$apply()
scope.filter_states = (countryID) ->
return [] unless countryID
$filter('filter')(scope.availableCountries, {id: parseInt(countryID)}, true)[0].states
$filter('filter')(scope.availableCountries, {id: countryID})[0].states

View File

@@ -12,10 +12,7 @@ angular.module("admin.customers").directive 'newCustomerDialog', ($compile, $tem
scope.submitted = true
scope.errors = []
if scope.new_customer_form.$valid
params =
enterprise_id: CurrentShop.shop.id
email: scope.email
Customers.add(params).$promise.then (data) ->
Customers.add(scope.email).$promise.then (data) ->
if data.id
scope.email = ""
scope.submitted = false
@@ -24,7 +21,7 @@ angular.module("admin.customers").directive 'newCustomerDialog', ($compile, $tem
if response.data.errors
scope.errors.push(error) for error in response.data.errors
else
scope.errors.push(t('js.customers.could_not_create') + " '#{scope.email}'")
scope.errors.push("Sorry! Could not create '#{scope.email}'")
return
# Compile modal template
@@ -38,4 +35,4 @@ angular.module("admin.customers").directive 'newCustomerDialog', ($compile, $tem
if CurrentShop.shop.id
template.dialog('open')
else
alert(t('js.customers.select_shop'))
alert('Please select a shop first')

View File

@@ -8,4 +8,4 @@ angular.module("ofn.admin").directive "datetimepicker", ->
onSelect: (dateText, inst) ->
scope.$apply (scope) ->
# Fires ngModel.$parsers
ngModel.$setViewValue dateText
ngModel.$setViewValue dateText

View File

@@ -1,6 +0,0 @@
angular.module("ofn.admin").directive "select2NoSearch", ($timeout) ->
restrict: 'CA'
link: (scope, element, attrs) ->
$timeout ->
element.select2
minimumResultsForSearch: Infinity

View File

@@ -1 +1 @@
angular.module("admin.dropdown", ['admin.utils'])
angular.module("admin.dropdown", ['templates'])

View File

@@ -2,7 +2,7 @@ angular.module('admin.enterpriseFees').directive 'spreeDeleteResource', ->
(scope, element, attrs) ->
if scope.enterprise_fee.id
url = '/admin/enterprise_fees/' + scope.enterprise_fee.id
html = '<a href="' + url + '" class="delete-resource icon_link icon-trash no-text" data-action="remove" data-confirm="' + t('are_you_sure') + '" url="' + url + '"></a>'
html = '<a href="' + url + '" class="delete-resource icon_link icon-trash no-text" data-action="remove" data-confirm="Are you sure?" url="' + url + '"></a>'
#var html = '<a href="'+url+'" class="delete-resource" data-confirm="Are you sure?"><img alt="Delete" src="/assets/admin/icons/delete.png" /> Delete</a>';
element.append html
return

View File

@@ -1 +0,0 @@
angular.module("admin.enterpriseRoles", [])

View File

@@ -1,18 +0,0 @@
# Used in enterprise new and edit forms to reset the state when the country is changed
angular.module("admin.enterprises").controller 'countryCtrl', ($scope, availableCountries) ->
$scope.countries = availableCountries
$scope.countriesById = $scope.countries.reduce (obj, country) ->
obj[country.id] = country
obj
, {}
$scope.$watch 'Enterprise.address.country_id', (newID, oldID) ->
$scope.clearState() unless $scope.addressStateMatchesCountry()
$scope.clearState = ->
$scope.Enterprise.address.state_id = null
$scope.addressStateMatchesCountry = ->
$scope.countriesById[$scope.Enterprise.address.country_id].states.some (state) ->
state.id == $scope.Enterprise.address.state_id

View File

@@ -1,19 +1,18 @@
angular.module("admin.enterprises")
.controller "enterpriseCtrl", ($scope, $http, $window, NavigationCheck, enterprise, EnterprisePaymentMethods, EnterpriseShippingMethods, SideMenu, StatusMessage) ->
.controller "enterpriseCtrl", ($scope, $window, NavigationCheck, enterprise, EnterprisePaymentMethods, EnterpriseShippingMethods, SideMenu, StatusMessage) ->
$scope.Enterprise = enterprise
$scope.PaymentMethods = EnterprisePaymentMethods.paymentMethods
$scope.ShippingMethods = EnterpriseShippingMethods.shippingMethods
$scope.navClear = NavigationCheck.clear
$scope.pristineEmail = $scope.Enterprise.email
$scope.menu = SideMenu
$scope.newManager = { id: null, email: (t('add_manager')) }
$scope.newManager = { id: '', email: (t('add_manager')) }
$scope.StatusMessage = StatusMessage
$scope.$watch 'enterprise_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t('admin.unsaved_changes') if newValue
$scope.$watch 'newManager', (newValue) ->
$scope.addManager($scope.newManager) if newValue
$scope.setFormDirty = ->
$scope.$apply ->
$scope.enterprise_form.$setDirty()
@@ -29,7 +28,7 @@ angular.module("admin.enterprises")
# from a directive "nav-check" in the page - if we pass it here it will be called in the test suite,
# and on all new uses of this contoller, and we might not want that.
enterpriseNavCallback = ->
if $scope.enterprise_form != undefined && $scope.enterprise_form.$dirty
if $scope.enterprise_form.$dirty
t('admin.unsaved_confirm_leave')
# Register the NavigationCheck callback
@@ -37,33 +36,17 @@ angular.module("admin.enterprises")
$scope.removeManager = (manager) ->
if manager.id?
if manager.id == $scope.Enterprise.owner.id or manager.id == parseInt($scope.receivesNotifications)
return
for i, user of $scope.Enterprise.users when user.id == manager.id
$scope.Enterprise.users.splice i, 1
$scope.enterprise_form?.$setDirty()
if $scope.enterprise_form?
$scope.enterprise_form.$setDirty()
$scope.addManager = (manager) ->
if manager.id? and angular.isNumber(manager.id) and manager.email?
if manager.id? and manager.email?
manager =
id: manager.id
email: manager.email
confirmed: manager.confirmed
if (user for user in $scope.Enterprise.users when user.id == manager.id).length == 0
$scope.Enterprise.users.unshift(manager)
$scope.enterprise_form?.$setDirty()
$scope.Enterprise.users.push manager
else
alert ("#{manager.email}" + " " + t("is_already_manager"))
$scope.inviteManager = ->
$scope.invite_errors = $scope.invite_success = null
email = $scope.newUser
$http.post("/admin/manager_invitations", {email: email, enterprise_id: $scope.Enterprise.id}).success (data)->
$scope.addManager({id: data.user, email: email})
$scope.invite_success = t('user_invited', email: email)
.error (data) ->
$scope.invite_errors = data.errors
$scope.resetModal = ->
$scope.newUser = $scope.invite_errors = $scope.invite_success = null

View File

@@ -30,27 +30,27 @@ angular.module("admin.enterprises").controller 'enterprisesCtrl', ($scope, $q, E
$scope.producerTextFor = (enterprise) ->
switch enterprise.is_primary_producer
when true
t('js.enterprises.producer')
"Producer"
else
t('js.enterprises.non_producer')
"Non-Producer"
$scope.packageTextFor = (enterprise) ->
switch enterprise.is_primary_producer
when true
switch enterprise.sells
when "none"
t('js.profile')
"Profile"
when "own"
t('js.shop')
"Shop"
when "any"
t('js.hub')
"Hub"
else
t('js.choose')
"Choose"
else
switch enterprise.sells
when "none"
t('js.profile')
"Profile"
when "any"
t('js.hub')
"Hub"
else
t('js.choose')
"Choose"

View File

@@ -14,7 +14,7 @@ angular.module("admin.enterprises").controller 'indexPanelCtrl', ($scope, Enterp
, (response) ->
$scope.saving = false
if response.status == 422 && response.data.errors?
message = t('js.resolve_errors') + ':\n'
message = 'Please resolve the following errors:\n'
for attr, msg of response.data.errors
message += "#{attr} #{msg}\n"
alert(message)

View File

@@ -1,5 +0,0 @@
angular.module("admin.enterprises").controller 'NewEnterpriseController', ($scope, defaultCountryID) ->
$scope.Enterprise =
address:
country_id: defaultCountryID
state_id: null

View File

@@ -22,7 +22,7 @@ angular.module("admin.enterprises")
{ name: 'users', label: t('users'), icon_class: "icon-user" }
]
SideMenu.init()
$scope.select(0)
$scope.showItem = (item) ->
if item.show?

View File

@@ -1,11 +0,0 @@
angular.module('admin.enterprises').directive 'enterpriseLimit', (InfoDialog) ->
restrict: 'A'
scope: {
limit_reached: '=enterpriseLimit',
modal_message: '@modalMessage'
}
link: (scope, element, attr) ->
element.bind 'click', (event)->
if scope.limit_reached
event.preventDefault()
InfoDialog.open 'error', scope.modal_message

View File

@@ -1,7 +1,7 @@
angular.module("admin.enterprises")
.factory "EnterprisePaymentMethods", (enterprise, PaymentMethods) ->
new class EnterprisePaymentMethods
paymentMethods: PaymentMethods.all
paymentMethods: PaymentMethods.paymentMethods
constructor: ->
for payment_method in @paymentMethods

View File

@@ -1,7 +1,7 @@
angular.module("admin.enterprises")
.factory "EnterpriseShippingMethods", (enterprise, ShippingMethods) ->
new class EnterpriseShippingMethods
shippingMethods: ShippingMethods.all
shippingMethods: ShippingMethods.shippingMethods
constructor: ->
for shipping_method in @shippingMethods

View File

@@ -19,16 +19,16 @@ angular.module("admin.enterprises").factory 'PermalinkChecker', ($q, $http) ->
if data.length > @MAX_PERMALINK_LENGTH || !data.match(/^[\w-]+$/)
deferredRequest.resolve
permalink: permalink
available: t('js.error')
available: "Error"
else
deferredRequest.resolve
permalink: data
available: t('available')
available: "Available"
).error (data,status) =>
if status == 409
deferredRequest.resolve
permalink: data
available: t('js.unavailable')
available: "Unavailable"
else
# Something went wrong or request was aborted
deferredRequest.reject()

View File

@@ -1,4 +0,0 @@
angular.module("ofn.admin").filter "importDate", ($filter) ->
return (products, importDate) ->
return products if importDate == "0"
$filter('filter')( products, { import_date: importDate } )

View File

@@ -1,4 +1,4 @@
angular.module("admin.utils").directive "datepicker", ->
angular.module("admin.indexUtils").directive "datepicker", ->
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
element.datepicker

View File

@@ -1,4 +1,4 @@
angular.module("admin.utils").directive "ofnSelect2", ($sanitize, $timeout, $filter) ->
angular.module("admin.indexUtils").directive "ofnSelect2", ($sanitize, $timeout, $filter) ->
require: 'ngModel'
restrict: 'C'
scope:
@@ -14,11 +14,8 @@ angular.module("admin.utils").directive "ofnSelect2", ($sanitize, $timeout, $fil
scope.text ?= 'name'
scope.multiple ?= false
scope.filter ?= -> true
scope.placeholder ?= t('admin.choose')
if scope.data.$promise
# Initialize with empty data set, while we wait for data
element.select2(data:[], placeholder: scope.placeholder)
scope.data.$promise.then -> init()
else
init()
@@ -42,7 +39,6 @@ angular.module("admin.utils").directive "ofnSelect2", ($sanitize, $timeout, $fil
item.name = $sanitize(item.name) for item in scope.data
element.select2
multiple: scope.multiple
placeholder: scope.placeholder
minimumResultsForSearch: scope.minSearch || 0
data: ->
filtered = $filter('filter')(scope.data,scope.filter)

View File

@@ -1,2 +1 @@
angular.module("admin.indexUtils", ['admin.resources', 'ngSanitize', 'templates', 'admin.utils']).config ($httpProvider) ->
$httpProvider.defaults.headers.common["X-CSRF-Token"] = $("meta[name=csrf-token]").attr("content");
angular.module("admin.indexUtils", ['admin.resources', 'ngSanitize', 'templates', 'admin.utils']).config ($httpProvider) ->

View File

@@ -1,16 +1,14 @@
angular.module("admin.indexUtils").factory 'Panels', ->
new class Panels
all: []
panels: []
register: (ctrl, object, selected=null) ->
if ctrl? && object?
existing = @panelFor(object)
newPanel = { ctrl: ctrl, object: object, selected: selected }
if existing then angular.extend(existing, newPanel) else @all.push(newPanel)
@panels.push { ctrl: ctrl, object: object, selected: selected }
ctrl.select(selected) if selected?
toggle: (object, name, state=null) ->
panel = @panelFor(object)
panel = @findPanelByObject(object)
if panel.selected == name
@select(panel, null) unless state == "open"
else
@@ -20,5 +18,5 @@ angular.module("admin.indexUtils").factory 'Panels', ->
panel.selected = name
panel.ctrl.select(name)
panelFor: (object) ->
(@all.filter (panel) -> panel.object == object)[0]
findPanelByObject: (object) ->
(panel for panel in @panels when panel.object == object)[0]

View File

@@ -6,7 +6,7 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
add: (id, attr, change) =>
@pendingChanges["#{id}"] = {} unless @pendingChanges.hasOwnProperty("#{id}")
@pendingChanges["#{id}"]["#{attr}"] = change
StatusMessage.display('notice', t('admin.unsaved_changes'))
StatusMessage.display('notice', "You have made #{@changeCount(@pendingChanges)} unsaved changes")
removeAll: =>
@pendingChanges = {}
@@ -21,16 +21,16 @@ angular.module("admin.indexUtils").factory "pendingChanges", ($q, resources, Sta
submitAll: (form=null) =>
all = []
@errors = []
StatusMessage.display('progress', t('js.saving'))
StatusMessage.display('progress', "Saving...")
for id, objectChanges of @pendingChanges
for attrName, change of objectChanges
all.push @submit(change)
$q.all(all).then =>
if @errors.length == 0
StatusMessage.display('success', t('js.all_changes_saved_successfully'))
StatusMessage.display('success', "All changes saved successfully")
form.$setPristine() if form?
else
StatusMessage.display('failure', t('js.oh_no'))
StatusMessage.display('failure', "Oh no! I was unable to save your changes")
all
submit: (change) ->

View File

@@ -10,7 +10,7 @@ angular.module("admin.indexUtils").factory "SpreeApiAuth", ($q, $http, SpreeApiK
deferred.resolve()
.error (response) ->
error = response?.error || t('js.unauthorized')
error = response?.error || "You are unauthorised to access this page."
deferred.reject(error)
deferred.promise

View File

@@ -3,8 +3,8 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
$scope.RequestMonitor = RequestMonitor
$scope.filteredLineItems = []
$scope.confirmDelete = true
$scope.startDate = moment().startOf('day').subtract(7, 'days').format('YYYY-MM-DD')
$scope.endDate = moment().startOf('day').format('YYYY-MM-DD')
$scope.startDate = formatDate daysFromToday -7
$scope.endDate = formatDate daysFromToday 1
$scope.bulkActions = [ { name: t("admin.orders.bulk_management.actions_delete"), callback: 'deleteLineItems' } ]
$scope.selectedUnitsProduct = {}
$scope.selectedUnitsVariant = {}
@@ -22,16 +22,16 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
$scope.refreshData = ->
unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == 0
$scope.startDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_open_at).format('YYYY-MM-DD')
$scope.endDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_close_at).startOf('day').format('YYYY-MM-DD')
$scope.startDate = OrderCycles.byID[$scope.orderCycleFilter].first_order
$scope.endDate = OrderCycles.byID[$scope.orderCycleFilter].last_order
RequestMonitor.load $scope.orders = Orders.index("q[state_not_eq]": "canceled", "q[completed_at_not_null]": "true", "q[completed_at_gteq]": "#{moment($scope.startDate).format()}", "q[completed_at_lt]": "#{moment($scope.endDate).add(1,'day').format()}")
RequestMonitor.load $scope.lineItems = LineItems.index("q[order][state_not_eq]": "canceled", "q[order][completed_at_not_null]": "true", "q[order][completed_at_gteq]": "#{moment($scope.startDate).format()}", "q[order][completed_at_lt]": "#{moment($scope.endDate).add(1,'day').format()}")
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(action: "visible", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(90,'days').format()}")
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
RequestMonitor.load $scope.distributors = Enterprises.index(action: "for_line_items", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{daysFromToday(-90)}")
RequestMonitor.load $scope.suppliers = Enterprises.index(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.byID
@@ -51,13 +51,13 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
$scope.$watch 'bulk_order_form.$dirty', (newVal, oldVal) ->
if newVal == true
StatusMessage.display 'notice', t('js.unsaved_changes')
StatusMessage.display 'notice', "You have unsaved changes"
$scope.submit = ->
if $scope.bulk_order_form.$valid
StatusMessage.display 'progress', t('js.saving')
StatusMessage.display 'progress', "Saving..."
$q.all(LineItems.saveAll()).then(->
StatusMessage.display 'success', t('js.all_changes_saved')
StatusMessage.display 'success', "All changes saved"
$scope.bulk_order_form.$setPristine()
).catch ->
StatusMessage.display 'failure', t "unsaved_changes_error"
@@ -142,3 +142,31 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
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

View File

@@ -1,11 +1,10 @@
angular.module('admin.orderCycles')
.controller 'AdminCreateOrderCycleCtrl', ($scope, $filter, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
.controller 'AdminCreateOrderCycleCtrl', ($scope, $filter, $window, 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.schedules = Schedules.index()
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.new({ coordinator_id: ocInstance.coordinator_id})
@@ -19,7 +18,7 @@ angular.module('admin.orderCycles')
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
@@ -85,8 +84,9 @@ angular.module('admin.orderCycles')
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
StatusMessage.display 'progress', "Saving..."
OrderCycle.create(destination)
$scope.cancel = (destination) ->
$window.location = destination

View File

@@ -1,12 +1,11 @@
angular.module('admin.orderCycles')
.controller 'AdminEditOrderCycleCtrl', ($scope, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor) ->
.controller 'AdminEditOrderCycleCtrl', ($scope, $filter, $location, $window, 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.schedules = Schedules.index()
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.load(order_cycle_id)
@@ -20,7 +19,7 @@ angular.module('admin.orderCycles')
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
@@ -88,11 +87,11 @@ angular.module('admin.orderCycles')
$scope.submit = (destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
StatusMessage.display 'progress', "Saving..."
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
StatusMessage.display 'progress', "Saving..."
OrderCycle.update(destination, $scope.order_cycle_form)
$scope.cancel = (destination) ->

View File

@@ -1,45 +0,0 @@
angular.module("admin.orderCycles").controller "OrderCyclesCtrl", ($scope, $q, Columns, StatusMessage, RequestMonitor, OrderCycles, Enterprises, Schedules, Dereferencer) ->
$scope.RequestMonitor = RequestMonitor
$scope.columns = Columns.columns
$scope.saveAll = -> OrderCycles.saveChanges($scope.order_cycles_form)
$scope.ordersCloseAtLimit = -31 # days
$scope.involvingFilter = 0
$scope.scheduleFilter = 0
compileData = ->
for schedule in $scope.schedules
Dereferencer.dereference(schedule.order_cycles, OrderCycles.byID)
for orderCycle in $scope.orderCycles
coordinator = Enterprises.byID[orderCycle.coordinator.id]
orderCycle.coordinator = coordinator if coordinator?
Dereferencer.dereference(orderCycle.producers, Enterprises.byID)
Dereferencer.dereference(orderCycle.shops, Enterprises.byID)
Dereferencer.dereference(orderCycle.schedules, Schedules.byID)
orderCycle.involvedEnterpriseIDs = [orderCycle.coordinator.id]
orderCycle.producerNames = orderCycle.producers.map((producer) -> orderCycle.involvedEnterpriseIDs.push(producer.id); producer.name).join(", ")
orderCycle.shopNames = orderCycle.shops.map((shop) -> orderCycle.involvedEnterpriseIDs.push(shop.id); shop.name).join(", ")
# NOTE: this is using the Enterprises service from the admin.enterprises module
RequestMonitor.load ($scope.enterprises = Enterprises.index(action: "visible", ams_prefix: "basic")).$promise
$scope.schedules = Schedules.index()
$scope.orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}")
RequestMonitor.load $q.all([$scope.enterprises.$promise, $scope.schedules.$promise, $scope.orderCycles.$promise]).then -> compileData()
$scope.$watch 'order_cycles_form.$dirty', (newVal, oldVal) ->
StatusMessage.display 'notice', "You have unsaved changes" if newVal
$scope.showMore = (days) ->
$scope.ordersCloseAtLimit -= days
existingIDs = Object.keys(OrderCycles.byID)
orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}", "q[id_not_in][]": existingIDs)
orderCycles.$promise.then ->
$scope.orderCycles.push(orderCycle) for orderCycle in orderCycles
compileData()
daysFromToday = (days) ->
now = new Date
now.setHours(0)
now.setMinutes(0)
now.setSeconds(0)
now.setDate( now.getDate() + days )
now

View File

@@ -1,7 +1,6 @@
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, ocInstance) ->
$scope.StatusMessage = StatusMessage
$scope.OrderCycle = OrderCycle
$scope.schedules = Schedules.index()
$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) =>
@@ -27,7 +26,7 @@ angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl"
OrderCycle.order_cycle.coordinator_id = enterprise.id
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
$scope.removeDistributionOfVariant = angular.noop
@@ -50,7 +49,7 @@ angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl"
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
StatusMessage.display 'progress', "Saving..."
OrderCycle.mirrorIncomingToOutgoingProducts()
OrderCycle.create(destination)

View File

@@ -1,11 +1,10 @@
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, StatusMessage) ->
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, $window, 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.schedules = Schedules.index()
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.load $scope.orderCycleId(), (order_cycle) =>
$scope.init()
@@ -17,7 +16,7 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl",
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded
$scope.init = ->
$scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0]
@@ -43,7 +42,7 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl",
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
StatusMessage.display 'progress', "Saving..."
OrderCycle.mirrorIncomingToOutgoingProducts()
OrderCycle.update(destination, $scope.order_cycle_form)

View File

@@ -1,23 +0,0 @@
angular.module("admin.orderCycles").directive "changeWarning", (ConfirmDialog) ->
restrict: "A"
scope:
orderCycle: '=changeWarning'
link: (scope, element, attrs) ->
acknowledged = false
cancel = 'admin.order_cycles.date_warning.cancel'
proceed = 'admin.order_cycles.date_warning.proceed'
msg = 'admin.order_cycles.date_warning.msg'
options = { cancel: t(cancel), confirm: t(proceed) }
isOpen = (orderCycle) ->
moment(orderCycle.orders_open_at, "YYYY-MM-DD HH:mm:SS Z").isBefore() &&
moment(orderCycle.orders_close_at, "YYYY-MM-DD HH:mm:SS Z").isAfter()
element.focus ->
count = scope.orderCycle.subscriptions_count
return if acknowledged
return unless isOpen(scope.orderCycle)
return if count < 1
ConfirmDialog.open('info', t(msg, n: count), options).then ->
acknowledged = true
element.siblings('img').trigger('click')

View File

@@ -1,26 +0,0 @@
angular.module("admin.orderCycles").directive 'orderCyclesSelector', ($timeout, OrderCycles) ->
restrict: 'C'
templateUrl: 'admin/order_cycles_selector.html'
link: (scope, element, attr) ->
scope.orderCycles = OrderCycles.all.filter (oc) -> oc.viewing_as_coordinator
$timeout ->
scope.selections =
available: scope.availableOrderCycles[0]
selected: scope.selectedOrderCycles[0]
scope.add = (orderCycle) ->
orderCycle ?= scope.selections.available
index = scope.availableOrderCycles.indexOf(orderCycle)
if index > -1
scope.selectedOrderCycles.push orderCycle
scope.selections.available = scope.availableOrderCycles[index+1] || scope.availableOrderCycles[index-1]
scope.selections.selected = orderCycle
scope.remove = (orderCycle) ->
orderCycle ?= scope.selections.selected
index = scope.selectedOrderCycles.indexOf(orderCycle)
if index > -1
scope.selectedOrderCycles.splice(index, 1)
scope.selections.selected = scope.selectedOrderCycles[index] || scope.selectedOrderCycles[index-1]
scope.selections.available = orderCycle

View File

@@ -1,63 +0,0 @@
angular.module("admin.orderCycles").directive 'scheduleDialog', ($window, $compile, $injector, $templateCache, DialogDefaults, OrderCycles, Schedules) ->
restrict: 'A'
scope:
scheduleId: '@'
showMore: '&'
link: (scope, element, attr) ->
# Link opening of dialog to click event on element
element.bind 'click', (e) ->
existing = Schedules.byID[scope.scheduleId]
scope.schedule =
id: existing?.id
name: existing?.name || ''
order_cycle_ids: existing?.order_cycle_ids || []
scope.selectedOrderCycles = []
scope.selectedOrderCycles.push orderCycle for orderCycle in (existing?.order_cycles || [])
scope.submitted = false
scope.errors = []
# Compile modal template
scope.template = $compile($templateCache.get('admin/schedule_dialog.html'))(scope)
# Set Dialog options
settings = angular.copy(DialogDefaults)
scope.template.dialog(angular.extend(settings,{width: $window.innerWidth * 0.6}))
scope.template.dialog(close: -> scope.template.remove())
scope.template.dialog('open')
scope.close = ->
scope.template.dialog('close')
return
scope.delete = ->
if confirm(t('are_you_sure'))
Schedules.remove(scope.schedule).$promise.then (data) ->
scope.close()
, (response) ->
errors = response.data.errors
if errors?
scope.errors.push errors[0]
else
scope.errors.push "Could not delete schedule: #{scope.schedule.name}"
scope.loadMore = ->
scope.showMore().then ->
scope.availableOrderCycles = (orderCycle for id, orderCycle of OrderCycles.byID when orderCycle.id not in scope.schedule.order_cycle_ids)
scope.submit = ->
scope.schedule_form.$setPristine()
scope.submitted = true
scope.errors = []
return scope.errors.push(t('admin.order_cycles.index.no_order_cycles_error')) unless scope.selectedOrderCycles.length > 0
scope.schedule.order_cycle_ids = scope.selectedOrderCycles.map (oc) -> oc.id
if scope.schedule_form.$valid
method = if scope.schedule.id? then Schedules.update else Schedules.add
method(scope.schedule).$promise.then (data) ->
if data.id
scope.submitted = false
scope.template.dialog('close')
, (response) ->
if response.data.errors
scope.errors.push(error) for error in response.data.errors
else
scope.errors.push("Sorry! Could not create '#{scope.name}'")
return

View File

@@ -1,15 +0,0 @@
angular.module("admin.orderCycles").directive 'scheduleList', (RequestMonitor, Schedules) ->
restrict: 'E'
scope:
orderCycle: '='
template: "<div><span ng-repeat='schedule in schedules'>{{ schedule.name + ($last ? '' : ', ')}}</span></div>"
link: (scope, element, attr) ->
scope.schedules = []
scope.$watchCollection 'orderCycle.schedule_ids', (newValue, oldValue) ->
return unless newValue? && RequestMonitor.loadId > 0 # Request for schedules needs to have been sent
scope.schedules = []
RequestMonitor.loadQueue.then ->
for id in scope.orderCycle.schedule_ids
schedule = Schedules.byID[id]
scope.schedules.push schedule if schedule?

View File

@@ -1,7 +0,0 @@
angular.module("admin.orderCycles").filter "available", ($filter) ->
return (orderCycles, selectedOrderCycles) ->
return orderCycles unless selectedOrderCycles?.length > 0
$filter('filter')(orderCycles, (orderCycle) ->
(selectedOrderCycles.indexOf(orderCycle) == -1) &&
(orderCycle.coordinator.id == selectedOrderCycles[0].coordinator.id)
)

View File

@@ -1,6 +0,0 @@
angular.module("admin.orderCycles").filter "involving", ($filter) ->
return (orderCycles, enterpriseID) ->
return orderCycles if enterpriseID == 0
$filter('filter')(orderCycles, (orderCycle) ->
enterpriseID in orderCycle.involvedEnterpriseIDs
)

View File

@@ -1,6 +0,0 @@
angular.module("admin.orderCycles").filter "schedule", ($filter) ->
return (orderCycles, scheduleID) ->
return orderCycles if scheduleID == 0
$filter('filter')(orderCycles, (orderCycle) ->
scheduleID in orderCycle.schedules.map (oc) -> oc.id
)

View File

@@ -0,0 +1,32 @@
angular.module('admin.orderCycles', ['admin.utils', 'admin.indexUtils', 'ngTagsInput'])
.config ($httpProvider) ->
$httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
.directive 'datetimepicker', ($parse) ->
(scope, element, attrs) ->
# using $parse instead of scope[attrs.datetimepicker] for cases
# where attrs.datetimepicker is 'foo.bar.lol'
$(element).datetimepicker
dateFormat: 'yy-mm-dd'
timeFormat: 'HH:mm:ss'
showOn: "button"
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>"
buttonImageOnly: true
stepMinute: 15
onSelect: (dateText, inst) ->
scope.$apply ->
parsed = $parse(attrs.datetimepicker)
parsed.assign(scope, dateText)
.directive 'ofnOnChange', ->
(scope, element, attrs) ->
element.bind 'change', ->
scope.$apply(attrs.ofnOnChange)
.directive 'ofnSyncDistributions', ->
(scope, element, attrs) ->
element.bind 'change', ->
if !$(this).is(':checked')
scope.$apply ->
scope.removeDistributionOfVariant(attrs.ofnSyncDistributions)

View File

@@ -1,37 +0,0 @@
angular.module('admin.orderCycles', ['ngTagsInput', 'admin.indexUtils', 'admin.enterprises'])
.config ($httpProvider) ->
$httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')
.directive 'datetimepicker', ($timeout, $parse) ->
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
$timeout ->
# using $parse instead of scope[attrs.datetimepicker] for cases
# where attrs.datetimepicker is 'foo.bar.lol'
$(element).datetimepicker
dateFormat: 'yy-mm-dd'
timeFormat: 'HH:mm:ss'
showOn: "button"
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>"
buttonImageOnly: true
stepMinute: 15
onSelect: (dateText, inst) ->
scope.$apply(->
element.val(dateText)
parsed = $parse(attrs.datetimepicker)
parsed.assign(scope, dateText)
)
.directive 'ofnOnChange', ->
(scope, element, attrs) ->
element.bind 'change', ->
scope.$apply(attrs.ofnOnChange)
.directive 'ofnSyncDistributions', ->
(scope, element, attrs) ->
element.bind 'change', ->
if !$(this).is(':checked')
scope.$apply ->
scope.removeDistributionOfVariant(attrs.ofnSyncDistributions)

View File

@@ -151,32 +151,27 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
return unless @confirmNoDistributors()
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
oc.$create (data) ->
$window.location = destination
, (response) ->
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])
if data['success']
$window.location = destination
else
StatusMessage.display('failure', 'Failed to create order cycle')
console.log('Failed to create order cycle')
update: (destination, form) ->
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) =>
form.$setPristine() if form
if destination?
$window.location = destination
if data['success']
form.$setPristine() if form
if destination?
$window.location = destination
else
StatusMessage.display 'success', 'Your order cycle has been updated.'
else
StatusMessage.display 'success', t('js.order_cycles.update_success')
, (response) ->
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])
else
StatusMessage.display('failure', 'Failed to create order cycle')
console.log('Failed to update order cycle')
confirmNoDistributors: ->
if @order_cycle.outgoing_exchanges.length == 0
confirm t('js.order_cycles.no_distributors')
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
@@ -209,7 +204,6 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
delete order_cycle.editable_variants_for_incoming_exchanges
delete order_cycle.editable_variants_for_outgoing_exchanges
delete order_cycle.visible_variants_for_outgoing_exchanges
delete order_cycle.subscriptions_count
order_cycle
removeInactiveExchanges: (order_cycle) ->

View File

@@ -1,7 +1,5 @@
angular.module("admin.orders").directive 'customerSearchOverride', ->
restrict: 'C'
scope:
distributorId: '@'
link: (scope, element, attr) ->
formatCustomerResult = (customer) ->
customerTemplate
@@ -11,14 +9,13 @@ angular.module("admin.orders").directive 'customerSearchOverride', ->
element.select2
placeholder: Spree.translations.choose_a_customer
minimumInputLength: 3
ajax:
url: '/admin/search/customers.json'
datatype: 'json'
data: (term, page) ->
{
q: term
distributor_id: scope.distributorId # modified
distributor_id: $('#distributor_id').val() # modified
}
results: (data, page) ->
{ results: data }
@@ -56,4 +53,7 @@ angular.module("admin.orders").directive 'customerSearchOverride', ->
return
$('#order_email').val customer.email
$('#user_id').val customer.user_id # modified
$('#guest_checkout_true').prop 'checked', false
$('#guest_checkout_false').prop 'checked', true
$('#guest_checkout_false').prop 'disabled', false
customer.email

View File

@@ -1,18 +0,0 @@
angular.module("admin.paymentMethods").controller "StripeController", ($scope, $http, shops) ->
$scope.shops = shops
$scope.stripe_account = {}
$scope.$watch "paymentMethod.preferred_enterprise_id", (newID, oldID) ->
return unless newID?
$scope.stripe_account = {}
$http.get("/admin/stripe_accounts/status.json?enterprise_id=#{newID}").success (data) ->
angular.extend($scope.stripe_account, data)
.error (response) ->
$scope.stripe_account.status = "request_failed"
$scope.current_enterprise_stripe_path = ->
return unless $scope.paymentMethod.preferred_enterprise_id?
permalink = shops.filter((shop) ->
shop.id == $scope.paymentMethod.preferred_enterprise_id
)[0].permalink
"/admin/enterprises/#{permalink}/edit#/payment_methods"

View File

@@ -1,33 +0,0 @@
// Override of Spree's logic in the file of the same name
// Changes made as per https://github.com/spree/spree/commit/8a3a80b08abf80fbed2fcee4b429ba1caf68baf1
// which allows the form partial in admin/payments/new to be switched using radio buttons
// We can remove this file when we reach 2.3.0
$(document).ready(function() {
if ($("#new_payment").is("*")) {
$('.payment_methods_radios').click(
function() {
$('.payment-methods').hide();
if (this.checked) {
$('#payment_method_' + this.value).show();
}
}
);
$('.payment_methods_radios').each(
function() {
if (this.checked) {
$('#payment_method_' + this.value).show();
} else {
$('#payment_method_' + this.value).hide();
}
}
);
$(".card_new").radioControlsVisibilityOfElement('.card_form');
$('select.jump_menu').change(function(){
window.location = this.options[this.selectedIndex].value;
});
}
});

View File

@@ -1,4 +1,4 @@
angular.module("admin.productImport").controller "DropdownPanelsCtrl", ($scope) ->
angular.module("ofn.admin").controller "DropdownPanelsCtrl", ($scope) ->
$scope.active = false
$scope.togglePanel = ->

View File

@@ -1,12 +0,0 @@
angular.module("admin.productImport").controller "ImportFeedbackCtrl", ($scope) ->
$scope.count = (items) ->
total = 0
angular.forEach items, (item) ->
total++
total
$scope.attribute_invalid = (attribute, line_number) ->
$scope.entries[line_number]['errors'][attribute] != undefined
$scope.ignore_fields = ['variant_unit', 'variant_unit_scale', 'unit_description']

View File

@@ -1,161 +0,0 @@
angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $http, $filter, ProductImportService, $timeout) ->
$scope.entries = {}
$scope.update_counts = {}
$scope.reset_counts = {}
$scope.updates = {}
$scope.updated_total = 0
$scope.updated_ids = []
$scope.update_errors = []
$scope.chunks = 0
$scope.completed = 0
$scope.percentage = "0%"
$scope.started = false
$scope.finished = false
$scope.countResettable = () ->
angular.forEach $scope.supplier_product_counts, (value, key) ->
$scope.reset_counts[key] = value
if $scope.update_counts[key]
$scope.reset_counts[key] -= $scope.update_counts[key]
$scope.resetProgress = () ->
$scope.chunks = 0
$scope.completed = 0
$scope.percentage = "0%"
$scope.started = false
$scope.finished = false
$scope.step = 'settings'
$scope.confirmSettings = () ->
$scope.step = 'import'
$scope.viewResults = () ->
$scope.countResettable()
$scope.step = 'results'
$scope.resetProgress()
$scope.acceptResults = () ->
$scope.step = 'save'
$scope.finalResults = () ->
$scope.step = 'complete'
$scope.start = () ->
$scope.started = true
$scope.percentage = "1%"
total = $scope.item_count
size = 100
$scope.chunks = Math.ceil(total / size)
i = 0
while i < $scope.chunks
start = (i*size)+1
end = (i+1)*size
if $scope.step == 'import'
$scope.processImport(start, end)
if $scope.step == 'save'
$scope.processSave(start, end)
i++
$scope.processImport = (start, end) ->
$scope.getSettings() if $scope.importSettings == null
$http(
url: $scope.import_url
method: 'POST'
data:
'start': start
'end': end
'filepath': $scope.filepath
'settings': $scope.importSettings
).success((data, status, headers, config) ->
angular.merge($scope.entries, angular.fromJson(data['entries']))
$scope.sortUpdates(data['reset_counts'])
$scope.updateProgress()
).error((data, status, headers, config) ->
$scope.exception = data
console.error(data)
)
$scope.importSettings = null
$scope.getSettings = () ->
$scope.importSettings = ProductImportService.getSettings()
$scope.sortUpdates = (data) ->
angular.forEach data, (value, key) ->
if (key in $scope.update_counts)
$scope.update_counts[key] += value['updates_count']
else
$scope.update_counts[key] = value['updates_count']
$scope.processSave = (start, end) ->
$scope.getSettings() if $scope.importSettings == null
$http(
url: $scope.save_url
method: 'POST'
data:
'start': start
'end': end
'filepath': $scope.filepath
'settings': $scope.importSettings
).success((data, status, headers, config) ->
$scope.sortResults(data['results'])
angular.forEach data['updated_ids'], (id) ->
$scope.updated_ids.push(id)
angular.forEach data['errors'], (error) ->
$scope.update_errors.push(error)
$scope.updateProgress()
).error((data, status, headers, config) ->
$scope.exception = data
console.error(data)
)
$scope.sortResults = (results) ->
angular.forEach results, (value, key) ->
if ($scope.updates[key] != undefined)
$scope.updates[key] += value
else
$scope.updates[key] = value
$scope.updated_total += value
$scope.resetAbsent = () ->
enterprises_to_reset = []
angular.forEach $scope.importSettings, (settings, enterprise) ->
if settings['reset_all_absent']
enterprises_to_reset.push(enterprise)
if enterprises_to_reset.length && $scope.updated_ids.length
$http(
url: $scope.reset_url
method: 'POST'
data:
'filepath': $scope.filepath
'settings': $scope.importSettings
'reset_absent': true,
'updated_ids': $scope.updated_ids,
'enterprises_to_reset': enterprises_to_reset
).success((data, status, headers, config) ->
console.log(data)
$scope.updates.products_reset = data
).error((data, status, headers, config) ->
console.error(data)
)
$scope.updateProgress = () ->
$scope.completed++
$scope.percentage = String(Math.round(($scope.completed / $scope.chunks) * 100)) + '%'
if $scope.completed == $scope.chunks
$scope.finished = true
$scope.resetAbsent() if $scope.step == 'save'

View File

@@ -1,38 +1,13 @@
angular.module("admin.productImport").controller "ImportOptionsFormCtrl", ($scope, $rootScope, ProductImportService) ->
angular.module("ofn.admin").controller "ImportOptionsFormCtrl", ($scope, $rootScope, ProductImportService) ->
$scope.initForm = () ->
$scope.settings = {} if $scope.settings == undefined
$scope.settings[$scope.supplierId] = {
import_into: 'product_list'
defaults:
count_on_hand:
mode: 'overwrite_all'
on_hand:
mode: 'overwrite_all'
tax_category_id:
mode: 'overwrite_all'
shipping_category_id:
mode: 'overwrite_all'
available_on:
mode: 'overwrite_all'
}
$scope.import_into = 'product_list'
$scope.toggleResetAbsent = () ->
confirmed = confirm 'This will set stock level to zero on all products for this \n' +
'enterprise that are not present in the uploaded file.' if $scope.resetAbsent
$scope.updateImportInto = () ->
$scope.import_into = $scope.settings[$scope.supplierId]['import_into']
$scope.$watch 'settings', (updated) ->
ProductImportService.updateSettings(updated)
, true
$scope.toggleResetAbsent = (id) ->
checked = $scope.settings[id]['reset_all_absent']
confirmed = confirm t('js.product_import.confirmation') if checked
if confirmed or !checked
ProductImportService.updateResetAbsent($scope.supplierId, $scope.reset_counts[$scope.supplierId], checked)
if confirmed or !$scope.resetAbsent
ProductImportService.updateResetAbsent($scope.supplierId, $scope.resetCount, $scope.resetAbsent)
else
$scope.settings[id]['reset_all_absent'] = false
$scope.resetAbsent = false
$scope.resetTotal = ProductImportService.resetTotal

View File

@@ -1,32 +0,0 @@
angular.module("admin.productImport").filter 'entriesFilterValid', ->
(entries, type) ->
if type == 'all'
return entries
filtered = {}
angular.forEach entries, (entry, line_number) ->
validates_as = entry.validates_as
if type == 'valid' and validates_as != '' \
or type == 'invalid' and validates_as == '' \
or type == 'create_product' and validates_as == 'new_product' or validates_as == 'new_variant' \
or type == 'update_product' and validates_as == 'existing_variant' \
or type == 'create_inventory' and validates_as == 'new_inventory_item' \
or type == 'update_inventory' and validates_as == 'existing_inventory_item'
filtered[line_number] = entry
filtered
angular.module("admin.productImport").filter 'entriesFilterSupplier', ->
(entries, supplier) ->
if supplier == 'all'
return entries
filtered = {}
angular.forEach entries, (entry, line_number) ->
if supplier == entry.attributes['supplier']
filtered[line_number] = entry
filtered

View File

@@ -1,3 +0,0 @@
angular.module("admin.productImport", ["ngResource"]).config ($httpProvider) ->
$httpProvider.defaults.headers.common["X-CSRF-Token"] = $("meta[name=csrf-token]").attr("content")
$httpProvider.defaults.headers.common["Accept"] = "application/json, text/javascript, */*"

View File

@@ -1,8 +1,7 @@
angular.module("admin.productImport").factory "ProductImportService", ($rootScope) ->
angular.module("ofn.admin").factory "ProductImportService", ($rootScope) ->
new class ProductImportService
suppliers: {}
resetTotal: 0
settings: {}
updateResetAbsent: (supplierId, resetCount, resetAbsent) ->
if resetAbsent
@@ -14,8 +13,3 @@ angular.module("admin.productImport").factory "ProductImportService", ($rootScop
$rootScope.resetTotal = @resetTotal
updateSettings: (updated) ->
angular.merge(@settings, updated)
getSettings: () ->
@settings

View File

@@ -1,8 +0,0 @@
angular.module("ofn.admin").controller "ProductImageCtrl", ($scope, ProductImageService) ->
$scope.imageUploader = ProductImageService.imageUploader
$scope.imagePreview = ProductImageService.imagePreview
$scope.$watch 'product.image_url', (newValue, oldValue) ->
if newValue != oldValue
$scope.imagePreview = newValue
$scope.uploadModal.close()

View File

@@ -1,6 +0,0 @@
angular.module("ofn.admin").directive "imageModal", ($modal, ProductImageService) ->
restrict: 'C'
link: (scope, elem, attrs, ctrl) ->
elem.on "click", (ev) =>
scope.uploadModal = $modal.open(templateUrl: 'admin/modals/image_upload.html', controller: ctrl, scope: scope, windowClass: 'product-image-upload')
ProductImageService.configure(scope.product)

View File

@@ -1,15 +0,0 @@
angular.module("ofn.admin").factory "ProductImageService", (FileUploader, SpreeApiKey) ->
new class ProductImageService
imagePreview: null
imageUploader: new FileUploader
headers:
'X-Spree-Token': SpreeApiKey
autoUpload: true
configure: (product) =>
@imageUploader.url = "/api/product_images/#{product.id}"
@imagePreview = product.image_url
@imageUploader.onSuccessItem = (image, response) =>
product.thumb_url = response.thumb_url
product.image_url = response.image_url

View File

@@ -12,10 +12,11 @@ angular.module("admin.products").factory "VariantUnitManager", ->
@variantUnitOptions: ->
options = for unit_type, scale_with_name of @unitNames
unit_type_cap = unit_type[0].toUpperCase() + unit_type[1..-1]
for scale in @unitScales(unit_type)
name = @getUnitName(scale, unit_type)
["#{I18n.t(unit_type)} (#{name})", "#{unit_type}_#{scale}"]
options.push [[I18n.t('items'), 'items']]
["#{unit_type_cap} (#{name})", "#{unit_type}_#{scale}"]
options.push [['Items', 'items']]
[].concat options...
@getScale: (value, unitType) ->

View File

@@ -1,5 +1,5 @@
angular.module("admin.resources").factory 'LineItemResource', ($resource) ->
$resource('/admin/bulk_line_items/:id.json', {}, {
$resource('/admin/:orders/:order_number/line_items/:id.json', {}, {
'index':
method: 'GET'
isArray: true

View File

@@ -5,9 +5,4 @@ angular.module("admin.resources").factory 'OrderCycleResource', ($resource) ->
isArray: true
'update':
method: 'PUT'
'bulkUpdate':
method: 'POST'
isArray: true
params:
action: 'bulk_update'
})

View File

@@ -1,16 +0,0 @@
angular.module("admin.resources").factory 'ScheduleResource', ($resource) ->
$resource('/admin/schedules/:id/:action.json', {}, {
'index':
method: 'GET'
isArray: true
'create':
method: 'POST'
'update':
method: 'PUT'
params:
id: '@id'
'destroy':
method: 'DELETE'
params:
id: '@id'
})

View File

@@ -1,14 +1,13 @@
angular.module("admin.resources").factory "Customers", ($q, $injector, InfoDialog, RequestMonitor, CustomerResource) ->
angular.module("admin.resources").factory "Customers", ($q, InfoDialog, RequestMonitor, CustomerResource, CurrentShop) ->
new class Customers
all: []
byID: {}
pristineByID: {}
constructor: ->
if $injector.has('customers')
@load($injector.get('customers'))
add: (params) ->
add: (email) ->
params =
enterprise_id: CurrentShop.shop.id
email: email
CustomerResource.create params, (customer) =>
if customer.id
@all.unshift customer
@@ -25,7 +24,7 @@ angular.module("admin.resources").factory "Customers", ($q, $injector, InfoDialo
if errors?
InfoDialog.open 'error', errors[0]
else
InfoDialog.open 'error', t('js.resources.could_not_delete_customer') + ": #{customer.email}"
InfoDialog.open 'error', "Could not delete customer: #{customer.email}"
index: (params) ->
@clear()

View File

@@ -26,7 +26,7 @@ angular.module("admin.resources").factory 'LineItems', ($q, LineItemResource) ->
save: (lineItem) ->
deferred = $q.defer()
lineItem.errors = {}
lineItem.$update({id: lineItem.id})
lineItem.$update({id: lineItem.id, orders: "orders", order_number: lineItem.order.number})
.then( (data) =>
@pristineByID[lineItem.id] = angular.copy(lineItem)
deferred.resolve(data)
@@ -54,7 +54,7 @@ angular.module("admin.resources").factory 'LineItems', ($q, LineItemResource) ->
delete: (lineItem, callback=null) ->
deferred = $q.defer()
lineItem.$delete({id: lineItem.id})
lineItem.$delete({id: lineItem.id, orders: "orders", order_number: lineItem.order.number})
.then( (data) =>
delete @byID[lineItem.id]
delete @pristineByID[lineItem.id]

View File

@@ -1,4 +1,4 @@
angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCycleResource, RequestMonitor, StatusMessage) ->
angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCycleResource) ->
new class OrderCycles
all: []
byID: {}
@@ -8,13 +8,14 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
if $injector.has('orderCycles')
@load($injector.get('orderCycles'))
index: (params={}) ->
request = OrderCycleResource.index params, (data) => @load(data)
RequestMonitor.load(request.$promise)
request
index: (params={}, callback=null) ->
OrderCycleResource.index params, (data) =>
@load(data)
(callback || angular.noop)(data)
data
load: (orderCycles) ->
for orderCycle in orderCycles when orderCycle.id not in Object.keys(@byID)
for orderCycle in orderCycles
@all.push orderCycle
@byID[orderCycle.id] = orderCycle
@pristineByID[orderCycle.id] = angular.copy(orderCycle)
@@ -29,44 +30,14 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
deferred.reject(response)
deferred.promise
saveChanges: (form) ->
changed = {}
for id, orderCycle of @byID when not @saved(orderCycle)
changed[Object.keys(changed).length] = @changesFor(orderCycle)
if Object.keys(changed).length > 0
StatusMessage.display('progress', "Saving...")
OrderCycleResource.bulkUpdate { order_cycle_set: { collection_attributes: changed } }, (data) =>
for orderCycle in data
delete orderCycle.coordinator
delete orderCycle.producers
delete orderCycle.distributors
angular.extend(@byID[orderCycle.id], orderCycle)
angular.extend(@pristineByID[orderCycle.id], orderCycle)
form.$setPristine() if form?
StatusMessage.display('success', "Order cycles have been updated.")
, (response) =>
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])
else
StatusMessage.display('failure', "Oh no! I was unable to save your changes.")
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 if attr in @attrsToSave()
changed.push attr unless attr is "$$hashKey"
changed
changesFor: (orderCycle) ->
changes = { id: orderCycle.id }
for attr, value of orderCycle when not angular.equals(value, @pristineByID[orderCycle.id][attr])
changes[attr] = orderCycle[attr] if attr in @attrsToSave()
changes
attrsToSave: ->
['orders_open_at','orders_close_at']
resetAttribute: (order_cycle, attribute) ->
order_cycle[attribute] = @pristineByID[order_cycle.id][attribute]

View File

@@ -1,7 +1,7 @@
angular.module("admin.resources")
.factory "PaymentMethods", ($injector) ->
new class PaymentMethods
all: []
paymentMethods: []
byID: {}
pristineByID: {}
@@ -11,6 +11,6 @@ angular.module("admin.resources")
load: (paymentMethods) ->
for paymentMethod in paymentMethods
@all.push paymentMethod
@paymentMethods.push paymentMethod
@byID[paymentMethod.id] = paymentMethod
@pristineByID[paymentMethod.id] = angular.copy(paymentMethod)

View File

@@ -1,46 +0,0 @@
angular.module("admin.resources").factory "Schedules", ($q, $injector, RequestMonitor, ScheduleResource, OrderCycles, Dereferencer, StatusMessage) ->
new class Schedules
all: []
byID: {}
constructor: ->
if $injector.has('schedules')
@load($injector.get('schedules'))
load: (schedules) ->
for schedule in schedules
@all.push schedule
@byID[schedule.id] = schedule
add: (params) =>
ScheduleResource.create params, (schedule) =>
@byID[schedule.id] = schedule if schedule.id?
Dereferencer.dereference(schedule.order_cycles, OrderCycles.byID)
orderCycle.schedules.push(schedule) for orderCycle in schedule.order_cycles
StatusMessage.display 'success', "#{t('admin.order_cycles.index.created_schedule')}: '#{schedule.name}'"
update: (params) =>
ScheduleResource.update params, (schedule) =>
if schedule.id?
Dereferencer.dereference(schedule.order_cycles, OrderCycles.byID)
for orderCycle in @byID[schedule.id].order_cycles when orderCycle.id not in schedule.order_cycle_ids
if orderCycle.schedules # Only if we need to update the schedules
orderCycle.schedules.splice(i, 1) for s, i in orderCycle.schedules by -1 when s.id == schedule.id
for orderCycle in schedule.order_cycles when orderCycle.id not in @byID[schedule.id].order_cycle_ids
orderCycle.schedules.push(@byID[schedule.id])
angular.extend(@byID[schedule.id], schedule)
StatusMessage.display 'success', "#{t('admin.order_cycles.index.updated_schedule')}: '#{schedule.name}'"
remove: (schedule) ->
params = id: schedule.id
ScheduleResource.destroy params, =>
for orderCycle in @byID[schedule.id].order_cycles
if orderCycle.schedules # Only if we need to update the schedules
orderCycle.schedules.splice(i, 1) for s, i in orderCycle.schedules by -1 when s.id == schedule.id
delete @byID[schedule.id]
StatusMessage.display 'success', "#{t('admin.order_cycles.index.deleted_schedule')}: '#{schedule.name}'"
index: ->
request = ScheduleResource.index (data) => @load(data)
RequestMonitor.load(request.$promise)
request

View File

@@ -1,7 +1,7 @@
angular.module("admin.resources")
.factory "ShippingMethods", ($injector) ->
new class ShippingMethods
all: []
shippingMethods: []
byID: {}
pristineByID: {}
@@ -11,6 +11,6 @@ angular.module("admin.resources")
load: (shippingMethods) ->
for shippingMethod in shippingMethods
@all.push shippingMethod
@shippingMethods.push shippingMethod
@byID[shippingMethod.id] = shippingMethod
@pristineByID[shippingMethod.id] = angular.copy(shippingMethod)

View File

@@ -1,4 +1,4 @@
angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher, $http) ->
angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher) ->
new class BulkProducts
products: []
@@ -11,14 +11,20 @@ angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher,
PagedFetcher.fetch url, (data) => @addProducts data.products
cloneProduct: (product) ->
$http.post("/api/products/" + product.id + "/clone").success (data) =>
dataFetcher("/api/products/" + data.id + "?template=bulk_show").then (newProduct) =>
dataFetcher("/admin/products/" + product.permalink_live + "/clone.json").then (data) =>
# Ideally we would use Spree's built in respond_override helper here to redirect the
# user after a successful clone with .json in the accept headers
# However, at the time of writing there appears to be an issue which causes the
# respond_with block in the destroy action of Spree::Admin::Product to break
# when a respond_overrride for the clone action is used.
id = data.product.id
dataFetcher("/api/products/" + id + "?template=bulk_show").then (newProduct) =>
@unpackProduct newProduct
@insertProductAfter(product, newProduct)
updateVariantLists: (serverProducts) ->
for server_product in serverProducts
product = @findProductInList(server_product.id, @products)
updateVariantLists: (serverProducts, productsWithUnsavedVariants) ->
for product in productsWithUnsavedVariants
server_product = @findProductInList(product.id, serverProducts)
product.variants = server_product.variants
@loadVariantUnitValues product

View File

@@ -1,6 +1,6 @@
angular.module("ofn.admin").factory "ofnConfirmHandler", (pendingChanges, $compile, $q) ->
return (scope, callback) ->
template = "<div id='dialog-div' style='padding: 10px'><h6>" + t('js.services.unsaved_changes_message') + "</h6></div>"
template = "<div id='dialog-div' style='padding: 10px'><h6>Unsaved changes currently exist, save now or ignore?</h6></div>"
dialogDiv = $compile(template)(scope)
return ->
if pendingChanges.changeCount(pendingChanges.pendingChanges) > 0

View File

@@ -26,7 +26,7 @@ angular.module("ofn.admin").factory 'EnterpriseRelationships', ($http, enterpris
permission_presentation: (permission) ->
switch permission
when "add_to_order_cycle" then t('js.services.add_to_order_cycle')
when "manage_products" then t('js.services.manage_products')
when "edit_profile" then t('js.services.edit_profile')
when "create_variant_overrides" then t('js.services.add_products_to_inventory')
when "add_to_order_cycle" then "add to order cycle"
when "manage_products" then "manage products"
when "edit_profile" then "edit profile"
when "create_variant_overrides" then "add products to inventory"

View File

@@ -1,21 +1,9 @@
angular.module("admin.side_menu")
.factory "SideMenu", ($location) ->
.factory "SideMenu", ->
new class SideMenu
items: []
selected: null
# Checks for path and uses it to set the view
# If no path, loads first view
init: =>
path = $location.path()?.match(/^\/\w+$/)?[0]
index = if path
name = path[1..]
@items.indexOf(@find_by_name(name))
else
0
@select(index)
setItems: (items) =>
@items = items
item.visible = true for item in @items
@@ -25,7 +13,6 @@ angular.module("admin.side_menu")
@selected.selected = false if @selected
@selected = @items[index]
@selected.selected = true
$location.path(@selected.name)
find_by_name: (name) =>
for item in @items when item.name is name

View File

@@ -1,26 +0,0 @@
angular.module("admin.subscriptions").controller "AddressController", ($scope, $filter, StatusMessage, availableCountries) ->
$scope.countries = availableCountries
$scope.statesFor = (country_id) ->
return [] unless country_id
$filter('filter')(availableCountries, {id: country_id})[0].states
$scope.billStates = $scope.statesFor($scope.subscription.bill_address.country_id)
$scope.shipStates = $scope.statesFor($scope.subscription.ship_address.country_id)
$scope.registerNextCallback 'address', ->
$scope.subscription_form.$submitted = true
if $scope.subscription_address_form.$valid
$scope.subscription_form.$setPristine()
StatusMessage.clear()
$scope.setView('products')
else
StatusMessage.display 'failure', t('admin.subscriptions.details.invalid_error')
$scope.registerBackCallback 'address', ->
StatusMessage.clear()
$scope.setView('details')
$scope.$watch 'subscription.bill_address.country_id', (newValue, oldValue) ->
$scope.billStates = $scope.statesFor(newValue) if newValue?
$scope.$watch 'subscription.ship_address.country_id', (newValue, oldValue) ->
$scope.shipStates = $scope.statesFor(newValue) if newValue?

View File

@@ -1,43 +0,0 @@
angular.module("admin.subscriptions").controller "DetailsController", ($scope, $http, CustomerResource, StatusMessage) ->
$scope.cardRequired = false
$scope.registerNextCallback 'details', ->
$scope.subscription_form.$submitted = true
return unless $scope.validate()
$scope.subscription_form.$setPristine()
StatusMessage.clear()
$scope.setView('address')
$scope.$watch "subscription.customer_id", (newValue, oldValue) ->
return if !newValue?
$scope.loadCustomer(newValue) unless $scope.subscription.id?
$scope.$watch "subscription.payment_method_id", (newValue, oldValue) ->
return if !newValue?
paymentMethod = ($scope.paymentMethods.filter (pm) -> pm.id == newValue)[0]
return unless paymentMethod?
$scope.cardRequired = (paymentMethod.type == "Spree::Gateway::StripeConnect")
$scope.loadCustomer() if $scope.cardRequired && !$scope.customer
$scope.loadCustomer = ->
params = { id: $scope.subscription.customer_id }
params.ams_prefix = 'subscription' unless $scope.subscription.id
$scope.customer = CustomerResource.get params, (response) ->
for address in ['bill_address','ship_address']
return unless response[address]
delete response[address].id
return if $scope.subscription[address].address1?
angular.extend($scope.subscription[address], response[address])
$scope.shipAddressFromBilling() unless response.ship_address?.address1?
$scope.validate = ->
return true if $scope.subscription_details_form.$valid && $scope.creditCardOk()
StatusMessage.display 'failure', t('admin.subscriptions.details.invalid_error')
false
$scope.creditCardOk = ->
return true unless $scope.cardRequired
return false unless $scope.customer
return false unless $scope.customer.allow_charges
return false unless $scope.customer.default_card_present
true

View File

@@ -1,10 +0,0 @@
angular.module("admin.subscriptions").controller "OrderUpdateIssuesController", ($scope, OrderCycles) ->
$scope.proxyOrders = $scope.options.proxyOrders
$scope.orderCycleName = (id) ->
OrderCycles.byID[id].name
$scope.orderCycleCloses = (id) ->
closes_at = moment(OrderCycles.byID[id].orders_close_at)
text = if closes_at > moment() then t('js.closes') else t('js.closed')
"#{text} #{closes_at.fromNow()}"

View File

@@ -1,22 +0,0 @@
angular.module("admin.subscriptions").controller "OrdersPanelController", ($scope, OrderCycles) ->
$scope.subscription = $scope.object
$scope.cancelOrder = (order) ->
if confirm(t('are_you_sure'))
$scope.subscription.cancelOrder(order)
$scope.resumeOrder = (order) ->
if confirm(t('are_you_sure'))
$scope.subscription.resumeOrder(order)
$scope.orderCycleName = (id) ->
OrderCycles.byID[id].name
$scope.orderCycleCloses = (id) ->
oc = OrderCycles.byID[id]
return t('js.subscriptions.close_date_not_set') unless oc?.orders_close_at?
closes_at = moment(oc.orders_close_at)
text = if closes_at > moment() then t('js.subscriptions.closes') else t('js.subscription.closed')
"#{text} #{closes_at.fromNow()}"
$scope.stateText = (state) -> t("spree.order_state.#{state}")

View File

@@ -1,13 +0,0 @@
angular.module("admin.subscriptions").controller "ProductsController", ($scope, StatusMessage) ->
$scope.registerNextCallback 'products', ->
$scope.subscription_form.$submitted = true
if $scope.subscription.subscription_line_items.length > 0
$scope.subscription_form.$setPristine()
StatusMessage.clear()
$scope.setView('review')
else
StatusMessage.display 'failure', 'Please add at least one product'
$scope.registerBackCallback 'products', ->
StatusMessage.clear()
$scope.setView('address')

View File

@@ -1,23 +0,0 @@
angular.module("admin.subscriptions").controller "ProductsPanelController", ($scope, Subscriptions, StatusMessage) ->
$scope.subscription = $scope.object
$scope.distributor_id = $scope.subscription.shop_id
$scope.saving = false
$scope.saved = ->
pristine = Subscriptions.pristineByID[$scope.subscription.id].subscription_line_items
return false unless angular.equals($scope.subscription.subscription_line_items, pristine)
true
$scope.save = ->
$scope.saving = true
StatusMessage.display 'progress', 'Saving...'
$scope.subscription.update().then (response) ->
$scope.saving = false
StatusMessage.display 'success', 'Saved'
, (response) ->
$scope.saving = false
if response.data?.errors?
keys = Object.keys(response.data.errors)
StatusMessage.display 'failure', response.data.errors[keys[0]][0]
else
StatusMessage.display 'success', 'Saved'

View File

@@ -1,8 +0,0 @@
angular.module("admin.subscriptions").controller "ReviewController", ($scope, Customers, Schedules, PaymentMethods, ShippingMethods) ->
$scope.formatAddress = (a) ->
formatted = []
formatted.push "#{a.firstname} #{a.lastname}"
formatted.push a.address1
formatted.push a.city
formatted.push a.zipcode
formatted.join(", ")

View File

@@ -1,27 +0,0 @@
angular.module("admin.subscriptions").controller "SubscriptionController", ($scope, Subscription, SubscriptionForm, Customers, Schedules, PaymentMethods, ShippingMethods) ->
$scope.subscription = new Subscription()
$scope.errors = null
$scope.save = null
$scope.customers = Customers.all
$scope.schedules = Schedules.all
$scope.paymentMethods = PaymentMethods.all
$scope.shippingMethods = ShippingMethods.all
$scope.distributor_id = $scope.subscription.shop_id # variant selector requires distributor_id
$scope.view = if $scope.subscription.id? then 'review' else 'details'
$scope.nextCallbacks = {}
$scope.backCallbacks = {}
$scope.creditCards = []
$scope.setView = (view) -> $scope.view = view
$scope.stepTitleFor = (step) -> t("admin.subscriptions.steps.#{step}")
$scope.registerNextCallback = (view, callback) => $scope.nextCallbacks[view] = callback
$scope.registerBackCallback = (view, callback) => $scope.backCallbacks[view] = callback
$scope.next = -> $scope.nextCallbacks[$scope.view]()
$scope.back = -> $scope.backCallbacks[$scope.view]()
$scope.shipAddressFromBilling = =>
angular.extend($scope.subscription.ship_address, $scope.subscription.bill_address)
$scope.$watch 'subscription_form', ->
form = new SubscriptionForm($scope.subscription_form, $scope.subscription)
$scope.errors = form.errors
$scope.save = form.save

View File

@@ -1,24 +0,0 @@
angular.module("admin.subscriptions").controller "SubscriptionLineItemsController", ($scope, InfoDialog) ->
$scope.newItem = { variant_id: 0, quantity: 1 }
$scope.addSubscriptionLineItem = ->
match = $scope.match()
if match
if match._destroy
angular.extend(match, $scope.newItem)
delete match._destroy
else
InfoDialog.open 'error', t('admin.subscriptions.product_already_in_order')
else
$scope.subscription_form.$setDirty()
$scope.subscription.buildItem($scope.newItem)
$scope.removeSubscriptionLineItem = (item) ->
$scope.subscription_form.$setDirty()
$scope.subscription.removeItem(item)
$scope.match = ->
matching = $scope.subscription.subscription_line_items.filter (sli) ->
sli.variant_id == $scope.newItem.variant_id
return matching[0] if matching.length > 0
null

View File

@@ -1,20 +0,0 @@
angular.module("admin.subscriptions").controller "SubscriptionsController", ($scope, Subscriptions, Columns, RequestMonitor, shops, ShippingMethods, PaymentMethods) ->
$scope.columns = Columns.columns
$scope.shops = shops
$scope.shop_id = if shops.length == 1 then shops[0].id else null
$scope.shippingMethodsByID = ShippingMethods.byID
$scope.paymentMethodsByID = PaymentMethods.byID
$scope.RequestMonitor = RequestMonitor
$scope.query = ''
$scope.$watch "shop_id", ->
if $scope.shop_id?
$scope.subscriptions = Subscriptions.index("q[shop_id_eq]": $scope.shop_id, "q[canceled_at_null]": true)
$scope.itemCount = (subscription) ->
subscription.subscription_line_items.reduce (sum, sli) ->
return sum + sli.quantity
, 0
$scope.filtersApplied = ->
$scope.query != ''

View File

@@ -1,9 +0,0 @@
# Used to display a message before redirecting to a link
angular.module("admin.subscriptions").directive "confirmOrderEdit", (ConfirmDialog, $window) ->
restrict: "A"
link: (scope, element, attrs) ->
element.bind "click", (event) ->
unless scope.proxyOrder.order_id?
event.preventDefault()
ConfirmDialog.open('error', t('admin.subscriptions.orders.confirm_edit'), {confirm: t('admin.subscriptions.yes_i_am_sure')}).then ->
$window.open(attrs.href)

View File

@@ -1,28 +0,0 @@
angular.module("admin.subscriptions").directive 'newSubscriptionDialog', ($compile, $window, $templateCache, DialogDefaults, shops) ->
restrict: 'A'
scope: true
link: (scope, element, attr) ->
scope.submitted = false
scope.shops = shops
scope.shop_id = null
scope.newSubscription = ->
scope.new_subscription_form.$setPristine()
scope.submitted = true
if scope.shop_id?
$window.location.href = "/admin/subscriptions/new?subscription[shop_id]=#{scope.shop_id}"
return
# Compile modal template
template = $compile($templateCache.get('admin/new_subscription_dialog.html'))(scope)
# Set Dialog options
template.dialog(DialogDefaults)
# Link opening of dialog to click event on element
element.bind 'click', (e) ->
if shops.length == 1
scope.shop_id = shops[0].id
scope.newSubscription()
else
template.dialog('open')

View File

@@ -1,2 +0,0 @@
angular.module("admin.subscriptions").factory 'CustomerResource', ($resource) ->
$resource '/admin/customers/:id.json'

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