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
1355 changed files with 13333 additions and 63734 deletions

View File

@@ -1,45 +1,13 @@
version: "2"
plugins:
engines:
rubocop:
enabled: true
channel: "rubocop-0-57"
config:
file: ".rubocop_styleguide.yml"
scss-lint:
enabled: true
checks:
ImportantRule:
enabled: false
VendorPrefix:
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: false
file-lines:
enabled: false
method-complexity:
enabled: false
method-count:
enabled: false
method-lines:
enabled: false
nested-control-flow:
enabled: false
return-statements:
enabled: false
similar-code:
enabled: false
identical-code:
enabled: false
exclude_patterns:
- "spec/**/*"
- "vendor/**/*"
- "app/assets/javascripts/shared/*"
- "app/assets/javascripts/jquery-migrate-1.0.0.js"
ratings:
paths:
- app/**
- lib/**
- "**.rb"
exclude_paths:
- spec/**/*
- vendor/**/*

View File

@@ -1,66 +0,0 @@
<!-- Provide a general summary of the issue in the Title above.
If your issue is not a bug, please use the Feature template instead:
https://github.com/openfoodfoundation/openfoodnetwork/wiki/Feature-template
-->
## 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
<!-- Assign a label and explain the impact.
bug-s1: a critical feature is broken: checkout, payments, signup, login
bug-s2: a non-critical feature is broken, no workaround
bug-s3: a feature is broken but there is a workaround
bug-s4: it's annoying, but you can use it
bug-s5: we can live with it, only a few users impacted
https://github.com/openfoodfoundation/openfoodnetwork/wiki/Bug-severity
-->
## Your Environment
<!-- Include 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,47 +0,0 @@
#### What? Why?
Closes #[the issue number this PR is related to]
<!-- Explain why this change is 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. -->
#### Release notes
<!-- Write a line or two to be included in the release notes.
Everything is worth mentioning, because you did it for a reason. -->
<!-- Please assign one category to your PR and delete the others.
The categories are based on https://keepachangelog.com/en/1.0.0/. -->
Changelog Category: Added | Changed | Deprecated | Removed | Fixed | Security
#### How is this related to the Spree upgrade?
<!-- Any known conflicts with the Spree Upgrade?
Explain them or remove this section. -->
#### Discourse thread
<!-- Is there a discussion about this in Discourse?
Add the link or remove this section. -->
#### Dependencies
<!-- Does this PR depend on another one?
Add the link or remove this section. -->
#### Documentation updates
<!-- Are their any wiki pages that need updating after merging this PR?
List them here or remove this section. -->

5
.gitignore vendored
View File

@@ -1,6 +1,5 @@
.bundle
.rbenv-version
.byebug_history
.swp
*.swo
*.swp
@@ -32,6 +31,8 @@ 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
NERD_tree*
@@ -39,5 +40,3 @@ coverage
libpeerconnection.log
/config/application.yml
node_modules
vendor/bundle/
coverage

View File

@@ -1 +0,0 @@
5.12.0

4
.rspec_parallel Normal file
View File

@@ -0,0 +1,4 @@
--format Fuubar
--format ParallelTests::RSpec::SummaryLogger --out tmp/spec_summary.log
--format ParallelTests::RSpec::RuntimeLogger --out tmp/parallel_runtime_rspec.log
--tag ~performance

View File

@@ -1,20 +1,173 @@
# This is our main Rubocop configuration for developers. It is used when you run:
#
# bundle exec rubocop
#
# The configuration is split into three files. Look into those files for more details.
#
inherit_from:
# The automatically generated todo list to ignore all current violations.
- .rubocop_todo.yml
# Our Open Food Network style guide. It's used by Code Climate. If you want to see all violations,
# then use only that configuration (like Code Climate):
#
# bundle exec rubocop -c .rubocop_styleguide.yml
#
- .rubocop_styleguide.yml
AllCops:
TargetRubyVersion: 2.1
TargetRailsVersion: 3.2
Include:
- '**/Rakefile'
- '**/config.ru'
Exclude:
- 'db/**/*'
- 'config/**/*'
- 'script/**/*'
- !ruby/regexp /old_and_unused\.rb$/
# A manually compiled todo list to ignore metrics violations on a file-by-file basis.
- .rubocop_manual_todo.yml
# OFN SETTINGS
# Cop settings that have been agreed upon by the OFN community
Rails:
Enabled: true
Style/Documentation:
Enabled: false
Style/StringLiterals:
Enabled: false
# TEMPORARY/CONTESTED SETTINGS
# These are still to be decided upon, but recommended for inclusion by
# oeoeaio after scrutinising offenses the codebase
# Don't think this is a big issue, mostly picking up RPSEC scope definitions
# with lamdas and RSpec '.to change{}' blocks
Lint/AmbiguousBlockAssociation:
Enabled: false
# Heaps of offences (> 100) in specs, mostly in situations where two or more
# instances of a model are required, but only one is referenced. Difficult to
# fix without making the spec look messy or rewriting it.
# Should definitely fix at some point.
Lint/UselessAssignment:
Exclude:
- spec/**/*
# AFAIK, there is no good alternative to dynamic matchers until we upgrade
# to Rails 4 and can use #find_by. If there is a better approach, let's do it.
Rails/DynamicFindBy:
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:
Enabled: false
# Relaxed.Ruby.Style SETTINGS
# These styles are a starting point for the conversation around conventions
# They should be removed or tweaked and moved above as decisions are made
# NOTE: Cops which did not fail at the time of writing were removed
Layout/DotPosition:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styledotposition
Layout/SpaceBeforeBlockBraces:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylespacebeforeblockbraces
Layout/SpaceInsideParens:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylespaceinsideparens
Style/Alias:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylealias
Style/BlockDelimiters:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleblockdelimiters
Style/CommentAnnotation:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylecommentannotation
Style/DoubleNegation:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styledoublenegation
Style/FormatString:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleformatstring
Style/IfUnlessModifier:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleifunlessmodifier
Style/Lambda:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylelambda
Style/MultilineBlockChain:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylemultilineblockchain
Style/NegatedIf:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylenegatedif
Style/NegatedWhile:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylenegatedwhile
Style/ParallelAssignment:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleparallelassignment
Style/PercentLiteralDelimiters:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylepercentliteraldelimiters
Style/Semicolon:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylesemicolon
Style/SingleLineMethods:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylesinglelinemethods
Style/TrailingCommaInArguments:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styletrailingcommainarguments
Style/TrailingCommaInLiteral:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styletrailingcommainliteral
Style/WordArray:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylewordarray
Lint/AmbiguousRegexpLiteral:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#lintambiguousregexpliteral
Lint/AssignmentInCondition:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#lintassignmentincondition
Metrics/AbcSize:
Enabled: false
Metrics/BlockNesting:
Enabled: false
Metrics/ClassLength:
Enabled: false
Metrics/ModuleLength:
Enabled: false
Metrics/CyclomaticComplexity:
Enabled: false
Metrics/LineLength:
Enabled: false
Metrics/MethodLength:
Enabled: false
Metrics/ParameterLists:
Enabled: false
Metrics/PerceivedComplexity:
Enabled: false

View File

@@ -1,763 +0,0 @@
# A manually compiled todo list to ignore metrics violations on a file-by-file basis.
#
# The file .rubocop_todo.yml is generated automatically and contains a
# configuration to make all files pass. For a lot of cops it just lists
# the offending files. But for metrics cops it sets a different metric.
#
# Since we don't want these lax metrics, we override them in our config
# file .rubocop.yml which results in a lot of offences again. This file
# lists all offending files for each cop to make rubocop pass. We can
# improve the code over time and remove items from the list.
#
# This file was manually created by using the following tools:
#
# rubocop > rubo.log
# # inspect log file to see which cops are failing
# # copy cop configurations and add Exclude parameter
# grep ExampleCop rubo.log | cut -d ":" -f 1 | sort -u >> .rubocop.yml
# # use vim to add `- ` before each line
#
# This process probably doesn't need repeating. Otherwise there is plenty
# of room for improvements and automation.
Metrics/LineLength:
Max: 100
Exclude:
- app/controllers/admin/accounts_and_billing_settings_controller.rb
- app/controllers/admin/bulk_line_items_controller.rb
- app/controllers/admin/business_model_configuration_controller.rb
- app/controllers/admin/cache_settings_controller.rb
- app/controllers/admin/contents_controller.rb
- app/controllers/admin/customers_controller.rb
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/enterprise_groups_controller.rb
- app/controllers/admin/enterprise_relationships_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/inventory_items_controller.rb
- app/controllers/admin/manager_invitations_controller.rb
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/product_import_controller.rb
- app/controllers/admin/proxy_orders_controller.rb
- app/controllers/admin/schedules_controller.rb
- app/controllers/admin/subscription_line_items_controller.rb
- app/controllers/admin/subscriptions_controller.rb
- app/controllers/admin/variant_overrides_controller.rb
- app/controllers/api/enterprise_attachment_controller.rb
- app/controllers/api/product_images_controller.rb
- app/controllers/application_controller.rb
- app/controllers/base_controller.rb
- app/controllers/cart_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/enterprises_controller.rb
- app/controllers/shop_controller.rb
- app/controllers/spree/admin/adjustments_controller_decorator.rb
- app/controllers/spree/admin/base_controller_decorator.rb
- app/controllers/spree/admin/line_items_controller_decorator.rb
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
- app/controllers/spree/admin/products_controller_decorator.rb
- app/controllers/spree/admin/reports_controller_decorator.rb
- app/controllers/spree/admin/shipping_methods_controller_decorator.rb
- app/controllers/spree/api/products_controller_decorator.rb
- app/controllers/spree/credit_cards_controller.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/controllers/spree/paypal_controller_decorator.rb
- app/controllers/stripe/callbacks_controller.rb
- app/controllers/user_confirmations_controller.rb
- app/helpers/admin/account_helper.rb
- app/helpers/admin/business_model_configuration_helper.rb
- app/helpers/admin/injection_helper.rb
- app/helpers/angular_form_builder.rb
- app/helpers/angular_form_helper.rb
- app/helpers/application_helper.rb
- app/helpers/checkout_helper.rb
- app/helpers/enterprises_helper.rb
- app/helpers/footer_links_helper.rb
- app/helpers/injection_helper.rb
- app/helpers/markdown_helper.rb
- app/helpers/order_cycles_helper.rb
- app/helpers/shop_helper.rb
- app/helpers/spree/admin/base_helper_decorator.rb
- app/helpers/spree/admin/navigation_helper_decorator.rb
- app/helpers/spree/admin/orders_helper_decorator.rb
- app/helpers/spree/orders_helper.rb
- app/jobs/finalize_account_invoices.rb
- app/jobs/products_cache_integrity_checker_job.rb
- app/jobs/subscription_confirm_job.rb
- app/jobs/subscription_placement_job.rb
- app/jobs/update_account_invoices.rb
- app/jobs/update_billable_periods.rb
- app/mailers/producer_mailer.rb
- app/mailers/spree/order_mailer_decorator.rb
- app/mailers/subscription_mailer.rb
- app/models/billable_period.rb
- app/models/column_preference.rb
- app/models/content_configuration.rb
- app/models/customer.rb
- app/models/enterprise_fee.rb
- app/models/enterprise.rb
- app/models/enterprise_relationship.rb
- app/models/enterprise_role.rb
- app/models/exchange.rb
- app/models/inventory_item.rb
- app/models/order_cycle.rb
- app/models/product_distribution.rb
- app/models/product_import/entry_processor.rb
- app/models/product_import/entry_validator.rb
- app/models/product_import/product_importer.rb
- app/models/product_import/spreadsheet_data.rb
- app/models/product_import/spreadsheet_entry.rb
- app/models/product_import/unit_converter.rb
- app/models/proxy_order.rb
- app/models/schedule.rb
- app/models/spree/ability_decorator.rb
- app/models/spree/adjustment_decorator.rb
- app/models/spree/calculator/default_tax_decorator.rb
- app/models/spree/calculator/flexi_rate_decorator.rb
- app/models/spree/classification_decorator.rb
- app/models/spree/gateway/stripe_connect.rb
- app/models/spree/line_item_decorator.rb
- app/models/spree/order_decorator.rb
- app/models/spree/payment_decorator.rb
- app/models/spree/payment_method_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/shipment_decorator.rb
- app/models/spree/shipping_method_decorator.rb
- app/models/spree/taxon_decorator.rb
- app/models/spree/user_decorator.rb
- app/models/spree/variant_decorator.rb
- app/models/subscription.rb
- app/models/variant_override.rb
- app/models/variant_override_set.rb
- app/overrides/add_distributor_details_js_to_product.rb
- app/overrides/add_enterprise_fees_to_admin_configurations_menu.rb
- app/overrides/replace_checkout_payment_button.rb
- app/overrides/replace_payment_name_with_description.rb
- app/serializers/api/admin/basic_enterprise_serializer.rb
- app/serializers/api/admin/enterprise_fee_serializer.rb
- app/serializers/api/admin/enterprise_serializer.rb
- app/serializers/api/admin/exchange_serializer.rb
- app/serializers/api/admin/for_order_cycle/enterprise_serializer.rb
- app/serializers/api/admin/index_enterprise_serializer.rb
- app/serializers/api/admin/index_order_cycle_serializer.rb
- app/serializers/api/admin/line_item_serializer.rb
- app/serializers/api/admin/order_cycle_serializer.rb
- app/serializers/api/admin/product_serializer.rb
- app/serializers/api/admin/subscription_serializer.rb
- app/serializers/api/admin/tag_rule_serializer.rb
- app/serializers/api/admin/variant_override_serializer.rb
- app/serializers/api/admin/variant_serializer.rb
- app/services/cart_service.rb
- app/services/embedded_page_service.rb
- app/services/line_item_syncer.rb
- app/services/order_cycle_form.rb
- app/services/order_factory.rb
- app/services/order_syncer.rb
- app/services/subscriptions_count.rb
- app/views/json/_groups.rabl
- app/views/json/partials/_enterprise.rabl
- app/views/json/_producer.rabl
- app/views/spree/api/products/bulk_show.v1.rabl
- app/views/spree/api/variants/bulk_show.v1.rabl
- engines/web/app/helpers/web/cookies_policy_helper.rb
- Gemfile
- lib/discourse/single_sign_on.rb
- lib/open_food_network/accounts_and_billing_settings_validator.rb
- lib/open_food_network/available_payment_method_filter.rb
- lib/open_food_network/bill_calculator.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/business_model_configuration_validator.rb
- lib/open_food_network/customers_report.rb
- lib/open_food_network/distribution_change_validator.rb
- lib/open_food_network/enterprise_fee_applicator.rb
- lib/open_food_network/enterprise_fee_calculator.rb
- lib/open_food_network/enterprise_issue_validator.rb
- lib/open_food_network/group_buy_report.rb
- lib/open_food_network/lettuce_share_report.rb
- lib/open_food_network/locking.rb
- lib/open_food_network/order_and_distributor_report.rb
- lib/open_food_network/order_cycle_form_applicator.rb
- lib/open_food_network/order_cycle_management_report.rb
- lib/open_food_network/order_cycle_permissions.rb
- lib/open_food_network/order_grouper.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/open_food_network/payments_report.rb
- lib/open_food_network/permalink_generator.rb
- lib/open_food_network/permissions.rb
- lib/open_food_network/products_and_inventory_report_base.rb
- lib/open_food_network/products_cache.rb
- lib/open_food_network/proxy_order_syncer.rb
- lib/open_food_network/reports/bulk_coop_allocation_report.rb
- lib/open_food_network/reports/line_items.rb
- lib/open_food_network/sales_tax_report.rb
- lib/open_food_network/users_and_enterprises_report.rb
- lib/open_food_network/variant_and_line_item_naming.rb
- lib/open_food_network/xero_invoices_report.rb
- lib/spree/core/calculated_adjustments_decorator.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
- lib/spree/product_filters.rb
- lib/stripe/profile_storer.rb
- lib/tasks/cache.rake
- lib/tasks/data.rake
- lib/tasks/dev.rake
- lib/tasks/enterprises.rake
- spec/archive/features/consumer/checkout_spec.rb
- spec/controllers/admin/accounts_and_billing_settings_controller_spec.rb
- spec/controllers/admin/bulk_line_items_controller_spec.rb
- spec/controllers/admin/column_preferences_controller_spec.rb
- spec/controllers/admin/customers_controller_spec.rb
- spec/controllers/admin/enterprises_controller_spec.rb
- spec/controllers/admin/inventory_items_controller_spec.rb
- spec/controllers/admin/manager_invitations_controller_spec.rb
- spec/controllers/admin/order_cycles_controller_spec.rb
- spec/controllers/admin/proxy_orders_controller_spec.rb
- spec/controllers/admin/schedules_controller_spec.rb
- spec/controllers/admin/stripe_accounts_controller_spec.rb
- spec/controllers/admin/stripe_connect_settings_controller_spec.rb
- spec/controllers/admin/subscription_line_items_controller_spec.rb
- spec/controllers/admin/subscriptions_controller_spec.rb
- spec/controllers/admin/variant_overrides_controller_spec.rb
- spec/controllers/api/logos_controller_spec.rb
- spec/controllers/api/order_cycles_controller_spec.rb
- spec/controllers/api/orders_controller_spec.rb
- spec/controllers/api/product_images_controller_spec.rb
- spec/controllers/api/promo_images_controller_spec.rb
- spec/controllers/cart_controller_spec.rb
- spec/controllers/checkout_controller_spec.rb
- spec/controllers/enterprises_controller_spec.rb
- spec/controllers/line_items_controller_spec.rb
- spec/controllers/shop_controller_spec.rb
- spec/controllers/shops_controller_spec.rb
- spec/controllers/spree/admin/adjustments_controller_spec.rb
- spec/controllers/spree/admin/base_controller_spec.rb
- spec/controllers/spree/admin/line_items_controller_spec.rb
- spec/controllers/spree/admin/orders_controller_spec.rb
- spec/controllers/spree/admin/orders/customer_details_controller_spec.rb
- spec/controllers/spree/admin/payment_methods_controller_spec.rb
- spec/controllers/spree/admin/payments_controller_spec.rb
- spec/controllers/spree/admin/reports_controller_spec.rb
- spec/controllers/spree/api/products_controller_spec.rb
- spec/controllers/spree/api/variants_controller_spec.rb
- spec/controllers/spree/credit_cards_controller_spec.rb
- spec/controllers/spree/orders_controller_spec.rb
- spec/controllers/spree/users_controller_spec.rb
- spec/controllers/spree/user_sessions_controller_spec.rb
- spec/controllers/stripe/callbacks_controller_spec.rb
- spec/controllers/stripe/webhooks_controller_spec.rb
- spec/controllers/user_confirmations_controller_spec.rb
- spec/controllers/user_registrations_controller_spec.rb
- spec/features/admin/accounts_and_billing_settings_spec.rb
- spec/features/admin/adjustments_spec.rb
- spec/features/admin/bulk_order_management_spec.rb
- spec/features/admin/bulk_product_update_spec.rb
- spec/features/admin/customers_spec.rb
- spec/features/admin/enterprise_fees_spec.rb
- spec/features/admin/enterprise_relationships_spec.rb
- spec/features/admin/enterprise_roles_spec.rb
- spec/features/admin/enterprises/images_spec.rb
- spec/features/admin/enterprises/index_spec.rb
- spec/features/admin/enterprises_spec.rb
- spec/features/admin/enterprise_user_spec.rb
- spec/features/admin/image_settings_spec.rb
- spec/features/admin/multilingual_spec.rb
- spec/features/admin/order_cycles_spec.rb
- spec/features/admin/orders_spec.rb
- spec/features/admin/overview_spec.rb
- spec/features/admin/payment_method_spec.rb
- spec/features/admin/product_import_spec.rb
- spec/features/admin/products_spec.rb
- spec/features/admin/reports_spec.rb
- spec/features/admin/schedules_spec.rb
- spec/features/admin/shipping_methods_spec.rb
- spec/features/admin/subscriptions_spec.rb
- spec/features/admin/tag_rules_spec.rb
- spec/features/admin/variant_overrides_spec.rb
- spec/features/consumer/account/cards_spec.rb
- spec/features/consumer/account/settings_spec.rb
- spec/features/consumer/account_spec.rb
- spec/features/consumer/authentication_spec.rb
- spec/features/consumer/cookies_spec.rb
- spec/features/consumer/groups_spec.rb
- spec/features/consumer/multilingual_spec.rb
- spec/features/consumer/registration_spec.rb
- spec/features/consumer/shopping/cart_spec.rb
- spec/features/consumer/shopping/checkout_auth_spec.rb
- spec/features/consumer/shopping/checkout_spec.rb
- spec/features/consumer/shopping/embedded_groups_spec.rb
- spec/features/consumer/shopping/embedded_shopfronts_spec.rb
- spec/features/consumer/shopping/orders_spec.rb
- spec/features/consumer/shopping/products_spec.rb
- spec/features/consumer/shopping/shopping_spec.rb
- spec/features/consumer/shopping/variant_overrides_spec.rb
- spec/features/consumer/shops_spec.rb
- spec/helpers/admin/business_model_configuration_helper_spec.rb
- spec/helpers/admin/subscriptions_helper_spec.rb
- spec/helpers/checkout_helper_spec.rb
- spec/helpers/enterprises_helper_spec.rb
- spec/helpers/groups_helper_spec.rb
- spec/helpers/injection_helper_spec.rb
- spec/helpers/order_cycles_helper_spec.rb
- spec/helpers/spree/admin/base_helper_spec.rb
- spec/jobs/confirm_order_job_spec.rb
- spec/jobs/finalize_account_invoices_spec.rb
- spec/jobs/refresh_products_cache_job_spec.rb
- spec/jobs/subscription_confirm_job_spec.rb
- spec/jobs/subscription_placement_job_spec.rb
- spec/jobs/update_account_invoices_spec.rb
- spec/jobs/update_billable_periods_spec.rb
- spec/lib/open_food_network/address_finder_spec.rb
- spec/lib/open_food_network/bulk_coop_report_spec.rb
- spec/lib/open_food_network/cached_products_renderer_spec.rb
- spec/lib/open_food_network/customers_report_spec.rb
- spec/lib/open_food_network/distribution_change_validator_spec.rb
- spec/lib/open_food_network/enterprise_fee_applicator_spec.rb
- spec/lib/open_food_network/enterprise_fee_calculator_spec.rb
- spec/lib/open_food_network/enterprise_injection_data_spec.rb
- spec/lib/open_food_network/group_buy_report_spec.rb
- spec/lib/open_food_network/lettuce_share_report_spec.rb
- spec/lib/open_food_network/option_value_namer_spec.rb
- spec/lib/open_food_network/order_and_distributor_report_spec.rb
- spec/lib/open_food_network/order_cycle_form_applicator_spec.rb
- spec/lib/open_food_network/order_cycle_permissions_spec.rb
- spec/lib/open_food_network/order_grouper_spec.rb
- spec/lib/open_food_network/orders_and_fulfillments_report_spec.rb
- spec/lib/open_food_network/packing_report_spec.rb
- spec/lib/open_food_network/permissions_spec.rb
- spec/lib/open_food_network/products_and_inventory_report_spec.rb
- spec/lib/open_food_network/products_cache_spec.rb
- spec/lib/open_food_network/products_renderer_spec.rb
- spec/lib/open_food_network/proxy_order_syncer_spec.rb
- spec/lib/open_food_network/scope_variant_to_hub_spec.rb
- spec/lib/open_food_network/subscription_payment_updater_spec.rb
- spec/lib/open_food_network/subscription_summarizer_spec.rb
- spec/lib/open_food_network/tag_rule_applicator_spec.rb
- spec/lib/open_food_network/users_and_enterprises_report_spec.rb
- spec/lib/open_food_network/xero_invoices_report_spec.rb
- spec/lib/stripe/account_connector_spec.rb
- spec/lib/stripe/webhook_handler_spec.rb
- spec/mailers/order_mailer_spec.rb
- spec/mailers/producer_mailer_spec.rb
- spec/mailers/subscription_mailer_spec.rb
- spec/models/billable_period_spec.rb
- spec/models/column_preference_spec.rb
- spec/models/customer_spec.rb
- spec/models/enterprise_caching_spec.rb
- spec/models/enterprise_fee_spec.rb
- spec/models/enterprise_group_spec.rb
- spec/models/enterprise_relationship_spec.rb
- spec/models/enterprise_spec.rb
- spec/models/exchange_spec.rb
- spec/models/model_set_spec.rb
- spec/models/order_cycle_spec.rb
- spec/models/producer_property_spec.rb
- spec/models/product_distribution_spec.rb
- spec/models/product_importer_spec.rb
- spec/models/proxy_order_spec.rb
- spec/models/spree/ability_spec.rb
- spec/models/spree/adjustment_spec.rb
- spec/models/spree/calculator/flexi_rate_spec.rb
- spec/models/spree/calculator/price_sack_spec.rb
- spec/models/spree/classification_spec.rb
- spec/models/spree/gateway/stripe_connect_spec.rb
- spec/models/spree/image_spec.rb
- spec/models/spree/line_item_spec.rb
- spec/models/spree/order_spec.rb
- spec/models/spree/payment_method_spec.rb
- spec/models/spree/payment_spec.rb
- spec/models/spree/product_spec.rb
- spec/models/spree/property_spec.rb
- spec/models/spree/shipping_method_spec.rb
- spec/models/spree/taxon_spec.rb
- spec/models/spree/tax_rate_spec.rb
- spec/models/spree/user_spec.rb
- spec/models/spree/variant_spec.rb
- spec/models/stripe_account_spec.rb
- spec/models/tag_rule/discount_order_spec.rb
- spec/models/tag_rule/filter_order_cycles_spec.rb
- spec/models/tag_rule/filter_payment_methods_spec.rb
- spec/models/tag_rule/filter_products_spec.rb
- spec/models/tag_rule/filter_shipping_methods_spec.rb
- spec/models/variant_override_spec.rb
- spec/performance/orders_controller_spec.rb
- spec/performance/proxy_order_syncer_spec.rb
- spec/performance/shop_controller_spec.rb
- spec/requests/checkout/failed_checkout_spec.rb
- spec/requests/checkout/paypal_spec.rb
- spec/requests/checkout/stripe_connect_spec.rb
- spec/requests/embedded_shopfronts_headers_spec.rb
- spec/requests/shop_spec.rb
- spec/serializers/admin/customer_serializer_spec.rb
- spec/serializers/admin/exchange_serializer_spec.rb
- spec/serializers/admin/for_order_cycle/enterprise_serializer_spec.rb
- spec/serializers/admin/for_order_cycle/supplied_product_serializer_spec.rb
- spec/serializers/admin/subscription_customer_serializer_spec.rb
- spec/serializers/admin/variant_override_serializer_spec.rb
- spec/serializers/current_order_serializer.rb
- spec/serializers/enterprise_serializer_spec.rb
- spec/serializers/order_serializer_spec.rb
- spec/services/cart_service_spec.rb
- spec/services/embedded_page_service_spec.rb
- spec/services/order_cycle_form_spec.rb
- spec/services/order_factory_spec.rb
- spec/services/order_syncer_spec.rb
- spec/services/subscription_estimator_spec.rb
- spec/services/subscription_form_spec.rb
- spec/services/subscription_validator_spec.rb
- spec/spec_helper.rb
- spec/support/cancan_helper.rb
- spec/support/delayed_job_helper.rb
- spec/support/matchers/delegate_matchers.rb
- spec/support/matchers/select2_matchers.rb
- spec/support/matchers/table_matchers.rb
- spec/support/request/authentication_workflow.rb
- spec/support/request/shop_workflow.rb
- spec/support/request/web_helper.rb
- spec/support/seeds.rb
- spec/support/spree/init.rb
Metrics/AbcSize:
Max: 15
Exclude:
- app/controllers/admin/bulk_line_items_controller.rb
- app/controllers/admin/customers_controller.rb
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/product_import_controller.rb
- app/controllers/admin/schedules_controller.rb
- app/controllers/admin/stripe_accounts_controller.rb
- app/controllers/admin/subscription_line_items_controller.rb
- app/controllers/admin/subscriptions_controller.rb
- app/controllers/api/enterprises_controller.rb
- app/controllers/api/order_cycles_controller.rb
- app/controllers/api/product_images_controller.rb
- app/controllers/base_controller.rb
- app/controllers/cart_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/discourse_sso_controller.rb
- app/controllers/enterprises_controller.rb
- app/controllers/spree/admin/adjustments_controller_decorator.rb
- app/controllers/spree/admin/line_items_controller_decorator.rb
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/admin/overview_controller_decorator.rb
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/products_controller_decorator.rb
- app/controllers/spree/admin/reports_controller_decorator.rb
- app/controllers/spree/admin/search_controller_decorator.rb
- app/controllers/spree/admin/shipping_methods_controller_decorator.rb
- app/controllers/spree/api/products_controller_decorator.rb
- app/controllers/spree/credit_cards_controller.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/controllers/spree/user_sessions_controller_decorator.rb
- app/controllers/stripe/callbacks_controller.rb
- app/controllers/user_confirmations_controller.rb
- app/controllers/user_passwords_controller.rb
- app/controllers/user_registrations_controller.rb
- app/helpers/admin/business_model_configuration_helper.rb
- app/helpers/checkout_helper.rb
- app/helpers/i18n_helper.rb
- app/helpers/order_cycles_helper.rb
- app/helpers/spree/admin/orders_helper_decorator.rb
- app/helpers/spree/orders_helper.rb
- app/jobs/finalize_account_invoices.rb
- app/jobs/subscription_placement_job.rb
- app/jobs/update_account_invoices.rb
- app/jobs/update_billable_periods.rb
- app/mailers/producer_mailer.rb
- app/models/billable_period.rb
- app/models/calculator/flat_percent_per_item.rb
- app/models/column_preference.rb
- app/models/enterprise_group.rb
- app/models/enterprise.rb
- app/models/enterprise_relationship.rb
- app/models/model_set.rb
- app/models/product_import/entry_processor.rb
- app/models/product_import/entry_validator.rb
- app/models/proxy_order.rb
- app/models/spree/ability_decorator.rb
- app/models/spree/adjustment_decorator.rb
- app/models/spree/calculator/default_tax_decorator.rb
- app/models/spree/calculator/flexi_rate_decorator.rb
- app/models/spree/line_item_decorator.rb
- app/models/spree/order_decorator.rb
- app/models/spree/payment_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- app/models/spree/taxon_decorator.rb
- app/serializers/api/admin/enterprise_serializer.rb
- app/serializers/api/enterprise_serializer.rb
- app/serializers/api/product_serializer.rb
- app/serializers/api/variant_serializer.rb
- app/services/cart_service.rb
- app/services/create_order_cycle.rb
- app/services/order_syncer.rb
- app/services/subscription_validator.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bill_calculator.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/customers_report.rb
- lib/open_food_network/enterprise_issue_validator.rb
- lib/open_food_network/group_buy_report.rb
- lib/open_food_network/lettuce_share_report.rb
- lib/open_food_network/option_value_namer.rb
- lib/open_food_network/order_and_distributor_report.rb
- lib/open_food_network/order_cycle_form_applicator.rb
- lib/open_food_network/order_cycle_management_report.rb
- lib/open_food_network/order_cycle_permissions.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/open_food_network/packing_report.rb
- lib/open_food_network/payments_report.rb
- lib/open_food_network/permissions.rb
- lib/open_food_network/products_and_inventory_report.rb
- lib/open_food_network/reports/line_items.rb
- lib/open_food_network/sales_tax_report.rb
- lib/open_food_network/users_and_enterprises_report.rb
- lib/open_food_network/variant_and_line_item_naming.rb
- lib/open_food_network/xero_invoices_report.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
- lib/stripe/account_connector.rb
- lib/tasks/enterprises.rake
- spec/archive/features/consumer/checkout_spec.rb
- spec/controllers/spree/admin/orders_controller_spec.rb
- spec/features/admin/reports_spec.rb
- spec/features/consumer/shopping/checkout_spec.rb
- spec/features/consumer/shopping/variant_overrides_spec.rb
- spec/models/enterprise_spec.rb
- spec/models/product_importer_spec.rb
- spec/support/performance_helper.rb
Metrics/CyclomaticComplexity:
Max: 6
Exclude:
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/helpers/admin/business_model_configuration_helper.rb
- app/helpers/checkout_helper.rb
- app/helpers/i18n_helper.rb
- app/helpers/order_cycles_helper.rb
- app/helpers/spree/admin/orders_helper_decorator.rb
- app/jobs/update_account_invoices.rb
- app/jobs/update_billable_periods.rb
- app/models/enterprise.rb
- app/models/enterprise_relationship.rb
- app/models/product_import/entry_processor.rb
- app/models/product_import/entry_validator.rb
- app/models/spree/ability_decorator.rb
- app/models/spree/adjustment_decorator.rb
- app/models/spree/payment_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- app/models/variant_override_set.rb
- app/services/cart_service.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bill_calculator.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_issue_validator.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/spree/core/controller_helpers/order_decorator.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
- spec/models/product_importer_spec.rb
Metrics/PerceivedComplexity:
Max: 7
Exclude:
- app/controllers/admin/enterprises_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/helpers/admin/business_model_configuration_helper.rb
- app/helpers/checkout_helper.rb
- app/helpers/i18n_helper.rb
- app/helpers/order_cycles_helper.rb
- app/helpers/spree/admin/orders_helper_decorator.rb
- app/jobs/update_account_invoices.rb
- app/models/enterprise_relationship.rb
- app/models/product_import/entry_processor.rb
- app/models/product_import/entry_validator.rb
- app/models/spree/ability_decorator.rb
- app/models/spree/line_item_decorator.rb
- app/models/spree/order_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_issue_validator.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/spree/core/controller_helpers/order_decorator.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
- spec/models/product_importer_spec.rb
Metrics/MethodLength:
Max: 10
Exclude:
- app/controllers/admin/customers_controller.rb
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/manager_invitations_controller.rb
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/stripe_accounts_controller.rb
- app/controllers/admin/subscriptions_controller.rb
- app/controllers/base_controller.rb
- app/controllers/cart_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/shop_controller.rb
- app/controllers/spree/admin/line_items_controller_decorator.rb
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/products_controller_decorator.rb
- app/controllers/spree/admin/reports_controller_decorator.rb
- app/controllers/spree/admin/search_controller_decorator.rb
- app/controllers/spree/admin/shipping_methods_controller_decorator.rb
- app/controllers/spree/credit_cards_controller.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/controllers/spree/user_sessions_controller_decorator.rb
- app/controllers/stripe/callbacks_controller.rb
- app/controllers/user_confirmations_controller.rb
- app/controllers/user_passwords_controller.rb
- app/controllers/user_registrations_controller.rb
- app/helpers/checkout_helper.rb
- app/helpers/order_cycles_helper.rb
- app/helpers/spree/admin/orders_helper_decorator.rb
- app/jobs/finalize_account_invoices.rb
- app/jobs/subscription_placement_job.rb
- app/jobs/update_account_invoices.rb
- app/jobs/update_billable_periods.rb
- app/mailers/producer_mailer.rb
- app/models/billable_period.rb
- app/models/column_preference.rb
- app/models/enterprise.rb
- app/models/enterprise_relationship.rb
- app/models/preference_sections/footer_and_external_links_section.rb
- app/models/preference_sections/main_links_section.rb
- app/models/product_import/entry_processor.rb
- app/models/product_import/entry_validator.rb
- app/models/product_import/product_importer.rb
- app/models/spree/ability_decorator.rb
- app/models/spree/adjustment_decorator.rb
- app/models/spree/calculator/default_tax_decorator.rb
- app/models/spree/calculator/flexi_rate_decorator.rb
- app/models/spree/line_item_decorator.rb
- app/models/spree/order_decorator.rb
- app/models/spree/payment_decorator.rb
- app/models/spree/payment_method_decorator.rb
- app/models/spree/product_set.rb
- app/models/spree/taxon_decorator.rb
- app/serializers/api/admin/order_cycle_serializer.rb
- app/services/cart_service.rb
- app/services/order_cycle_form.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/cached_products_renderer.rb
- lib/open_food_network/column_preference_defaults.rb
- lib/open_food_network/customers_report.rb
- lib/open_food_network/enterprise_fee_calculator.rb
- lib/open_food_network/group_buy_report.rb
- lib/open_food_network/lettuce_share_report.rb
- lib/open_food_network/option_value_namer.rb
- lib/open_food_network/order_and_distributor_report.rb
- lib/open_food_network/order_cycle_form_applicator.rb
- lib/open_food_network/order_cycle_management_report.rb
- lib/open_food_network/order_cycle_permissions.rb
- lib/open_food_network/order_grouper.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/open_food_network/packing_report.rb
- lib/open_food_network/payments_report.rb
- lib/open_food_network/permissions.rb
- lib/open_food_network/products_and_inventory_report.rb
- lib/open_food_network/products_renderer.rb
- lib/open_food_network/rack_request_blocker.rb
- lib/open_food_network/reports/bulk_coop_allocation_report.rb
- lib/open_food_network/reports/bulk_coop_supplier_report.rb
- lib/open_food_network/reports/line_items.rb
- lib/open_food_network/sales_tax_report.rb
- lib/open_food_network/users_and_enterprises_report.rb
- lib/open_food_network/xero_invoices_report.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
- lib/stripe/profile_storer.rb
- spec/archive/features/consumer/checkout_spec.rb
- spec/features/consumer/shopping/checkout_spec.rb
- spec/features/consumer/shopping/variant_overrides_spec.rb
- spec/models/product_importer_spec.rb
- spec/support/request/authentication_workflow.rb
Metrics/ClassLength:
Max: 100
Exclude:
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/subscriptions_controller.rb
- app/controllers/checkout_controller.rb
- app/models/enterprise.rb
- app/models/order_cycle.rb
- app/models/product_import/entry_processor.rb
- app/models/product_import/entry_validator.rb
- app/models/product_import/product_importer.rb
- app/models/spree/ability_decorator.rb
- app/serializers/api/enterprise_serializer.rb
- app/services/cart_service.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_fee_calculator.rb
- lib/open_food_network/order_cycle_form_applicator.rb
- lib/open_food_network/order_cycle_management_report.rb
- lib/open_food_network/order_cycle_permissions.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/open_food_network/packing_report.rb
- lib/open_food_network/payments_report.rb
- lib/open_food_network/permissions.rb
- lib/open_food_network/products_cache.rb
- lib/open_food_network/xero_invoices_report.rb
Metrics/ModuleLength:
Max: 100
Exclude:
- lib/open_food_network/column_preference_defaults.rb
- spec/controllers/admin/enterprises_controller_spec.rb
- spec/controllers/admin/order_cycles_controller_spec.rb
- spec/controllers/api/order_cycles_controller_spec.rb
- spec/controllers/api/orders_controller_spec.rb
- spec/controllers/spree/api/products_controller_spec.rb
- spec/lib/open_food_network/address_finder_spec.rb
- spec/lib/open_food_network/customers_report_spec.rb
- spec/lib/open_food_network/enterprise_fee_calculator_spec.rb
- spec/lib/open_food_network/option_value_namer_spec.rb
- spec/lib/open_food_network/order_cycle_form_applicator_spec.rb
- spec/lib/open_food_network/order_cycle_permissions_spec.rb
- spec/lib/open_food_network/order_grouper_spec.rb
- spec/lib/open_food_network/permissions_spec.rb
- spec/lib/open_food_network/products_and_inventory_report_spec.rb
- spec/lib/open_food_network/products_cache_spec.rb
- spec/lib/open_food_network/proxy_order_syncer_spec.rb
- spec/lib/open_food_network/scope_variant_to_hub_spec.rb
- spec/lib/open_food_network/subscription_payment_updater_spec.rb
- spec/lib/open_food_network/tag_rule_applicator_spec.rb
- spec/lib/open_food_network/users_and_enterprises_report_spec.rb
- spec/models/spree/ability_spec.rb
- spec/models/spree/adjustment_spec.rb
- spec/models/spree/line_item_spec.rb
- spec/models/spree/payment_spec.rb
- spec/models/spree/product_spec.rb
- spec/models/spree/variant_spec.rb
- spec/support/request/web_helper.rb
Metrics/ParameterLists:
Max: 5
Exclude:
- app/helpers/angular_form_builder.rb
- app/models/product_import/entry_processor.rb
- app/models/product_import/entry_validator.rb
- lib/open_food_network/xero_invoices_report.rb
- spec/features/admin/reports_spec.rb
Metrics/BlockNesting:
Max: 3
Exclude:
- app/controllers/checkout_controller.rb

View File

@@ -1,208 +0,0 @@
# Our Open Food Network style guide.
#
# These are the rules we agreed upon and we work towards. Code Climate uses
# these rules to rate our code and detect new violations. But when you run
# rubocop locally, the default configuration file `.rubocop.yml` loads
# our "todo lists" to ignore all current violations.
AllCops:
TargetRubyVersion: 2.1
TargetRailsVersion: 3.2
Exclude:
- 'db/**/*'
- 'config/**/*'
- 'script/**/*'
- 'vendor/**/*'
- 'node_modules/**/*'
# The parser gem fails to parse this file with out current Ruby version.
- 'spec/factories.rb'
# Excluding: inadequate Naming/FileName rule rejects GemFile name with camelcase
- 'engines/web/Gemfile'
## OFN SETTINGS
#
# Cop settings that have been agreed upon by the OFN community
Rails:
Enabled: true
Style/Documentation:
Enabled: false
Style/StringLiterals:
Enabled: false
Style/HashSyntax:
Enabled: true
EnforcedStyle: ruby19_no_mixed_keys
Style/Send:
Enabled: true
Layout/MultilineMethodCallIndentation:
Enabled: true
EnforcedStyle: indented
Metrics/LineLength:
Max: 100
## TEMPORARY/CONTESTED SETTINGS
#
# These are still to be decided upon, but recommended for inclusion by
# oeoeaio after scrutinising offenses the codebase
# Don't think this is a big issue, mostly picking up RPSEC scope definitions
# with lamdas and RSpec '.to change{}' blocks
Lint/AmbiguousBlockAssociation:
Enabled: false
# Heaps of offences (> 100) in specs, mostly in situations where two or more
# instances of a model are required, but only one is referenced. Difficult to
# fix without making the spec look messy or rewriting it.
# Should definitely fix at some point.
Lint/UselessAssignment:
Exclude:
- spec/**/*
# AFAIK, there is no good alternative to dynamic matchers until we upgrade
# to Rails 4 and can use #find_by. If there is a better approach, let's do it.
Rails/DynamicFindBy:
Enabled: false
# Same as above, #find_by is not available until Rails 4
Rails/FindBy:
Enabled: false
# Same as above, #update! is not available until Rails 4
Rails/ActiveRecordAliases:
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:
Enabled: false
## Relaxed.Ruby.Style SETTINGS
#
# These styles are a starting point for the conversation around conventions
# They should be removed or tweaked and moved above as decisions are made
# NOTE: Cops which did not fail at the time of writing were removed
Layout/DotPosition:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styledotposition
Layout/SpaceBeforeBlockBraces:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylespacebeforeblockbraces
Layout/SpaceInsideParens:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylespaceinsideparens
Style/Alias:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylealias
Style/BlockDelimiters:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleblockdelimiters
Style/CommentAnnotation:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylecommentannotation
Style/DoubleNegation:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styledoublenegation
Style/FormatString:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleformatstring
Style/IfUnlessModifier:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleifunlessmodifier
Style/Lambda:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylelambda
Style/MultilineBlockChain:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylemultilineblockchain
Style/NegatedIf:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylenegatedif
Style/NegatedWhile:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylenegatedwhile
Style/ParallelAssignment:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleparallelassignment
Style/PercentLiteralDelimiters:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylepercentliteraldelimiters
Style/Semicolon:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylesemicolon
Style/SingleLineMethods:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#stylesinglelinemethods
Style/TrailingCommaInArguments:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styletrailingcommainarguments
Style/TrailingCommaInArrayLiteral:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styletrailingcommainliteral
Style/TrailingCommaInHashLiteral:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styletrailingcommainliteral
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
Lint/AssignmentInCondition:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#lintassignmentincondition
Metrics/AbcSize:
Max: 15
Metrics/BlockNesting:
Max: 3
Metrics/ClassLength:
Max: 100
Metrics/ModuleLength:
Max: 100
Metrics/CyclomaticComplexity:
Max: 6
Metrics/MethodLength:
Max: 10
Metrics/ParameterLists:
Max: 5
Metrics/PerceivedComplexity:
Max: 7

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,7 +40,8 @@ before_script:
script:
- 'if [ "$KARMA" = "true" ]; then bundle exec rake karma:run; else echo "Skipping karma run"; fi'
- "bundle exec rake 'knapsack:rspec[--format progress --tag ~performance]'"
#- "KNAPSACK_GENERATE_REPORT=true bundle exec rspec spec"
- "bundle exec rake 'knapsack:rspec[--tag ~performance]'"
after_success:
- >

View File

@@ -1,64 +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][slack-dev] 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
Please follow the [GETTING_STARTED](GETTING_STARTED.md) guide to set up your local dev environment.
Follow the instructions in README.markdown to set up your machine.
This guide assumes that the git remote name of the main repo is `upstream` and that your fork is named `origin`.
Make sure the tests pass:
Create a new branch on your local machine to make your changes against (based on `upstream/master`):
rspec spec
git checkout -b branch-name-here --no-track upstream/master
Make your change. Add tests for your change. Make the tests pass:
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:
rspec spec
bundle exec rspec spec
Push to your fork and [submit a pull request][pr].
## Internationalisation (i18n)
[pr]: https://github.com/openfoodfoundation/openfoodnetwork/compare/
The locale `en` is maintained in the source code, but other locales are managed at [Transifex][ofn-transifex]. Read more about [internationalisation][i18n] in the developer wiki.
At this point you're waiting on us. We may suggest some changes or
improvements or alternatives.
## Making a change
To increase the chance that your pull request is swiftly accepted:
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/
[slack-dev]: https://openfoodnetwork.slack.com/messages/C2GQ45KNU
[ofn-transifex]: https://www.transifex.com/open-food-foundation/open-food-network/
[i18n]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/i18n

View File

@@ -1,124 +0,0 @@
### Getting Started
This is a general guide to setting up an Open Food Network development environment on your local machine.
The following guides are located in the wiki and provide more OS-specific step-by-step instructions:
- [Ubuntu Setup Guide][ubuntu]
- [macOS Sierra Setup Guide][sierra]
- [OSX El Capitan Setup Guide][el-capitan]
### Dependencies
* Rails 3.2.x
* Ruby 2.1.5
* PostgreSQL database
* PhantomJS (for testing)
* See Gemfile for a list of gems required
If you are likely to need to manage multiple version of ruby on your local machine, we recommend version managers such as [rbenv](https://github.com/rbenv/rbenv) or [RVM](https://rvm.io/).
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).
### Get it
If you're planning on contributing code to the project (which we [LOVE](CONTRIBUTING.md)), it is a good idea to begin by forking this repo using the `Fork` button in the top-right corner of this screen. You should then be able to use `git clone` to copy your fork onto your local machine.
git clone https://github.com/YOUR_GITHUB_USERNAME_HERE/openfoodnetwork
Jump into your new local copy of the Open Food Network:
cd openfoodnetwork
And then add an `upstream` remote that points to the main repo:
git remote add upstream https://github.com/openfoodfoundation/openfoodnetwork
Fetch the latest version of `master` from `upstream` (ie. the main repo):
git fetch upstream master
### Get it running
First, you need to create the database user the app will use by manually typing the following in your terminal:
```sh
$ sudo -u postgres psql -c "CREATE USER ofn WITH SUPERUSER CREATEDB PASSWORD 'f00d'"
```
This will create the "ofn" user as superuser and allowing it to create databases. If this command fails, check the [troubleshooting section](#creating-the-database) for an alternative.
Once done, 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.
If you run into any other issues getting your local environment up and running please consult [the wiki][wiki].
If still you get stuck do not hesitate to open an issue reporting the full output of the script.
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
### Testing
Tests, both unit and integration, are based on RSpec. To run the test suite, first prepare the test database:
bundle exec rake db:test:prepare
Then the tests can be run with:
bundle exec rspec spec
Note: If your OS is not explicitly supported in the setup guides then not all tests may pass. However, you may still be able to develop. Get in touch with the [#dev][slack-dev] channel on Slack to troubleshoot issues and determine if they will preclude you from contributing to OFN.
Note: The time zone on your machine should match the one defined in `config/application.yml`.
The project is configured to use [Zeus][zeus] to reduce the pre-test startup time while Rails loads. See the [Zeus GitHub page][zeus] for usage instructions.
Once [npm dependencies are installed][karma], AngularJS tests can be run with:
./script/karma run
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.
### Rubocop
The project is configured to use [rubocop][rubocop] to automatically check for style and syntax errors.
You can run rubocop against your changes using:
rubocop
### Troubleshooting
Below are fixes to potential issues that can happen during the installation process. If these don't solve the problem, or it's not listed, feel free to reach out to the [Developer Community][slack-dev] on slack. We usually respond pretty quickly.
#### Creating the database
If the ```$ sudo -u postgres psql -c "CREATE USER ofn WITH SUPERUSER CREATEDB PASSWORD 'f00d'"``` command doesn't work, you can run the following commands instead:
```
$ createuser --superuser --pwprompt ofn
Enter password for new role: f00d
Enter it again: f00d
$ createdb open_food_network_dev --owner=ofn
$ createdb open_food_network_test --owner=ofn
```
If these commands succeed, you should be able to [continue the setup process](#get-it-running).
[developer-wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki
[sierra]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-macOS-(Sierra)
[el-capitan]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-OS-X-(El-Capitan)
[ubuntu]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-Ubuntu
[wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki
[zeus]: https://github.com/burke/zeus
[rubocop]: https://rubocop.readthedocs.io/en/latest/
[karma]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Karma
[slack-dev]: https://openfoodnetwork.slack.com/messages/C2GQ45KNU

82
Gemfile
View File

@@ -1,45 +1,35 @@
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 'web', path: './engines/web'
gem 'pg'
gem 'spree', github: 'openfoodfoundation/spree', branch: 'step-6a', ref: '41906362d931695e0616194341a68d2c4c85aaaf'
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.2'
# 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'
gem 'bugsnag'
gem 'newrelic_rpm'
gem 'haml'
gem 'sass', "~> 3.3"
gem 'sass-rails', '~> 3.2.3', groups: [:default, :assets]
@@ -48,21 +38,18 @@ gem 'aws-sdk'
gem 'db2fog'
gem 'andand'
gem 'truncate_html'
gem 'representative_view'
gem 'rabl'
# AMS is pinned to 0.8.4 because 0.9.x is a complete re-write, as is 0.10.x
# Once Rails is updated to 5.x we should bump directly to 0.10.x
gem "active_model_serializers", "0.8.4"
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'
@@ -70,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'
@@ -78,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
@@ -88,17 +73,15 @@ group :assets do
gem 'compass-rails'
gem 'coffee-rails', '~> 3.2.1'
gem 'mini_racer'
# We found that the following version of libv8 breaks the compilation of mini_racer.
# Nothing else depends on libv8.
gem 'libv8', '!= 6.7.288.46.1'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
gem 'therubyracer'
gem 'uglifier', '>= 1.0.3'
gem 'turbo-sprockets-rails3'
gem 'foundation-icons-sass-rails'
gem 'momentjs-rails'
gem 'angular-rails-templates', '~> 0.3.0'
gem 'angular-rails-templates', '~> 0.2.0'
end
gem "foundation-rails"
@@ -106,23 +89,25 @@ gem 'foundation_rails_helper', github: 'willrjmarshall/foundation_rails_helper',
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.3.2'
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'
@@ -130,24 +115,19 @@ end
group :test do
gem 'webmock'
gem 'simplecov', require: false
# See spec/spec_helper.rb for instructions
#gem 'perftools.rb'
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

File diff suppressed because it is too large Load Diff

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

1
Procfile Normal file
View File

@@ -0,0 +1 @@
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb

119
README.md
View File

@@ -1,33 +1,111 @@
[![Build Status](https://semaphoreci.com/api/v1/openfoodfoundation/openfoodnetwork-2/branches/master/badge.svg)](https://semaphoreci.com/openfoodfoundation/openfoodnetwork-2)
[![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
The Open Food Network is an online marketplace for local food. It enables a network of independent online food stores that connect farmers and food hubs (including coops, online farmers' markets, independent food businesses etc); with individuals and local businesses. It gives farmers and food hubs an easier and fairer way to distribute their food.
Supported by the Open Food Foundation and a network of global affiliates, we are proudly open source and not-for-profit - we're trying to seriously disrupt the concentration of power in global agri-food systems, and we need as many smart people working together on this as possible.
Supported by the Open Food Foundation, we are proudly open source and not-for-profit - we're trying to seriously disrupt the concentration of power in global agri-food systems, and we need as many smart people working together on this as possible.
We're part of global movement - get involved!
* Fill in this [short survey][survey] to tell us who you are and what you want to do with OFN.
* Join the conversation [on Slack][slack-invite]. Make sure you introduce yourself in the #general channel
* Head to [https://openfoodnetwork.org](https://openfoodnetwork.org) for more information about the global OFN project.
* Check out the [User Guide](https://guide.openfoodnetwork.org/) for a list of features and tutorials.
* Join our [discussion forum](https://community.openfoodnetwork.org).
* Fill in this short survey to tell us who you are and what you want to do with OFN: https://docs.google.com/a/eaterprises.com.au/forms/d/1zxR5vSiU9CigJ9cEaC8-eJLgYid8CR8er7PPH9Mc-30/edit#
* Find out more and join in the conversation - http://openfoodnetwork.org
## Contributing
If you are interested in contributing to the OFN in any capacity, please introducing yourself [on Slack][slack-invite], and have a look through our [Contributor Guide][contributor-guide]
## Getting started
Our [GETTING_STARTED](GETTING_STARTED.md) and [CONTRIBUTING](CONTRIBUTING.md) guides are the best place to start for developers looking to set up a development environment and make contributions to the codebase.
Below are instructions for setting up a development environment for Open Food Network. More information is in the [developer wiki](https://github.com/openfoodfoundation/openfoodnetwork/wiki).
## Provisioning
If you're interested in provisioning a server, see [the project's Ansible playbooks](https://github.com/openfoodfoundation/ofn_deployment).
If you're interested in provisioning a server, see [ofn-install][ofn-install] for the project's Ansible playbooks.
We also have a [Super Admin Guide][super-admin-guide] to help with configuration of new servers.
### Dependencies
* Rails 3.2.x
* Ruby 2.1.5
* PostgreSQL database
* PhantomJS (for testing)
* See Gemfile for a list of gems required
### Get it
The source code is managed with Git (a version control system) and
hosted at GitHub.
You can view the code at:
https://github.com/openfoodfoundation/openfoodnetwork
You can download the source with the command:
git clone https://github.com/openfoodfoundation/openfoodnetwork.git
### 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 .
First, check your dependencies: Ensure that you have Ruby 2.1.5 installed:
ruby --version
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`:
```
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:
bundle exec rake db:test:prepare
Then the tests can be run with:
bundle exec rspec spec
The site is configured to use
[Zeus](https://github.com/burke/zeus) to reduce the pre-test
startup time while Rails loads. See the Zeus github page for
usage instructions.
Once [npm dependencies are
installed](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Karma), AngularJS tests can be run with:
./script/karma run
If you want karma to automatically rerun the tests on file modification, use:
./script/karma start
## Credits
@@ -41,18 +119,9 @@ We also have a [Super Admin Guide][super-admin-guide] to help with configuration
* 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
Copyright (c) 2012 - 2018 Open Food Foundation, released under the AGPL licence.
[survey]: https://docs.google.com/a/eaterprises.com.au/forms/d/1zxR5vSiU9CigJ9cEaC8-eJLgYid8CR8er7PPH9Mc-30/edit#
[slack-invite]: https://openfoodnetwork.org/slack-invite
[contributor-guide]: https://ofn-user-guide.gitbook.io/ofn-contributor-guide/who-are-we
[ofn-install]: https://github.com/openfoodfoundation/ofn-install
[super-admin-guide]: https://ofn-user-guide.gitbook.io/ofn-super-admin-guide
Copyright (c) 2012 - 2015 Open Food Foundation, released under the AGPL 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,13 +36,10 @@
//= require ./orders/orders
//= require ./order_cycles/order_cycles
//= require ./payment_methods/payment_methods
//= require ./payments/payments
//= 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
@@ -51,19 +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/de.js
//= 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/pt.js
//= require moment/sv.js
//= require ../shared/mm-foundation-tpls-0.9.0-20180826174721.min.js
//= require angularjs-file-upload
//= require_tree .

View File

@@ -1,6 +1,5 @@
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $http, $window, BulkProducts, DisplayProperties, dataFetcher, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, SpreeApiAuth, Columns, tax_categories) ->
$scope.loading = true
$scope.loadingAllPages = true
$scope.StatusMessage = StatusMessage
@@ -29,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
@@ -45,26 +44,27 @@ 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 = ->
$scope.loading = true
$scope.loadingAllPages = true
BulkProducts.fetch($scope.currentFilters, ->
$scope.loadingAllPages = false
).then ->
BulkProducts.fetch($scope.currentFilters).then ->
$scope.resetProducts()
$scope.loading = false
$timeout ->
if $scope.showLatestImport
$scope.importDateFilter = $scope.importDates[1].id
$scope.resetProducts = ->
DirtyProducts.clear()
StatusMessage.clear()
# $scope.matchProducer = (product) ->
# for producer in $scope.producers
# if angular.equals(producer.id, product.producer)
# product.producer = producer
# break
$scope.updateOnHand = (product) ->
on_demand_variants = []
if product.variants
@@ -92,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)
@@ -115,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
@@ -196,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

@@ -1,4 +1,4 @@
angular.module("admin.customers").controller "customersCtrl", ($scope, $q, $filter, Customers, TagRuleResource, CurrentShop, RequestMonitor, Columns, SortOptions, pendingChanges, shops, availableCountries) ->
angular.module("admin.customers").controller "customersCtrl", ($scope, $q, $filter, Customers, TagRuleResource, CurrentShop, RequestMonitor, Columns, pendingChanges, shops, availableCountries) ->
$scope.shops = shops
$scope.availableCountries = availableCountries
$scope.RequestMonitor = RequestMonitor
@@ -6,14 +6,13 @@ angular.module("admin.customers").controller "customersCtrl", ($scope, $q, $filt
$scope.customerLimit = 20
$scope.customers = Customers.all
$scope.columns = Columns.columns
$scope.sorting = SortOptions
$scope.confirmRefresh = (event) ->
event.preventDefault() unless pendingChanges.unsavedCount() == 0 || confirm(t("unsaved_changes_warning"))
$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

@@ -1,36 +1,36 @@
angular.module("admin.customers").directive 'editAddressDialog', ($compile, $templateCache, DialogDefaults, Customers, StatusMessage, CountryStates) ->
angular.module("admin.customers").directive 'editAddressDialog', ($compile, $templateCache, $filter, DialogDefaults, Customers, StatusMessage) ->
restrict: 'A'
scope: true
link: (scope, element, attr) ->
template = null
scope.errors = []
scope.$watch 'address.country_id', (newCountryID) ->
return unless newCountryID
scope.states = CountryStates.statesFor(scope.availableCountries, newCountryID)
unless CountryStates.addressStateMatchesCountryStates(scope.states, scope.address.state_id)
scope.address.state_id = ""
scope.$watch 'address.country_id', (newVal) ->
if newVal
scope.states = scope.filter_states(newVal)
scope.updateAddress = ->
scope.edit_address_form.$setPristine()
if scope.edit_address_form.$valid
Customers.update(scope.address, scope.customer, scope.addressType).$promise.then (data) ->
scope.customer = data
scope.errors = []
template.dialog('close')
StatusMessage.display('success', t('admin.customers.index.update_address_success'))
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 = CountryStates.statesFor(scope.availableCountries, 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) ->
$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

@@ -8,8 +8,8 @@ angular.module("admin.enterprise_groups")
{ name: 'users', label: t('users'), icon_class: "icon-user" }
{ name: 'about', label: t('about'), icon_class: "icon-pencil" }
{ name: 'images', label: t('images'), icon_class: "icon-picture" }
{ name: 'contact', label: t('admin_enterprise_groups_contact'), icon_class: "icon-phone" }
{ name: 'web', label: t('admin_enterprise_groups_web'), icon_class: "icon-globe" }
{ name: 'contact', label: t('admin_entreprise_groups_contact'), icon_class: "icon-phone" }
{ name: 'web', label: t('admin_entreprise_groups_web'), icon_class: "icon-globe" }
]
$scope.select(0)

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, Enterprises, 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,57 +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
$scope.removeLogo = ->
return unless confirm(t("admin.enterprises.remove_logo.immediate_removal_warning"))
Enterprises.removeLogo($scope.Enterprise).then (data) ->
$scope.Enterprise = angular.copy(data)
$scope.$emit("enterprise:updated", $scope.Enterprise)
StatusMessage.display("success", t("admin.enterprises.remove_logo.removed_successfully"))
, (response) ->
if response.data.error?
StatusMessage.display("failure", response.data.error)
$scope.removePromoImage = ->
return unless confirm(t("admin.enterprises.remove_promo_image.immediate_removal_warning"))
Enterprises.removePromoImage($scope.Enterprise).then (data) ->
$scope.Enterprise = angular.copy(data)
$scope.$emit("enterprise:updated", $scope.Enterprise)
StatusMessage.display("success", t("admin.enterprises.remove_promo_image.removed_successfully"))
, (response) ->
if response.data.error?
StatusMessage.display("failure", response.data.error)

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,2 +1,4 @@
angular.module("admin.indexUtils").controller "ColumnsCtrl", ($scope, Columns) ->
$scope.columns = Columns.columns
$scope.predicate = ""
$scope.reverse = false

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

@@ -3,18 +3,14 @@ angular.module("admin.indexUtils").factory "PagedFetcher", (dataFetcher) ->
# Given a URL like http://example.com/foo?page=::page::&per_page=20
# And the response includes an attribute pages with the number of pages to fetch
# Fetch each page async, and call the processData callback with the resulting data
fetch: (url, processData, onLastPageComplete) ->
fetch: (url, processData) ->
dataFetcher(@urlForPage(url, 1)).then (data) =>
processData data
if data.pages > 1
for page in [2..data.pages]
lastPromise = dataFetcher(@urlForPage(url, page)).then (data) ->
dataFetcher(@urlForPage(url, page)).then (data) ->
processData data
onLastPageComplete && lastPromise.then onLastPageComplete
return
else
onLastPageComplete && onLastPageComplete()
urlForPage: (url, page) ->
url.replace("::page::", page)

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

@@ -1,8 +0,0 @@
angular.module("admin.indexUtils").factory 'SortOptions', ->
new class SortOptions
predicate: ""
reverse: true
toggle: (predicate) ->
@reverse = (@predicate == predicate) && !@reverse
@predicate = predicate

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

@@ -1,16 +1,15 @@
angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $http, $q, StatusMessage, Columns, SortOptions, Dereferencer, Orders, LineItems, Enterprises, OrderCycles, VariantUnitManager, RequestMonitor) ->
angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $http, $q, StatusMessage, Columns, Dereferencer, Orders, LineItems, Enterprises, OrderCycles, VariantUnitManager, RequestMonitor) ->
$scope.initialized = false
$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 = {}
$scope.sharedResource = false
$scope.columns = Columns.columns
$scope.sorting = SortOptions
$scope.confirmRefresh = ->
LineItems.allSaved() || confirm(t("unsaved_changes_warning"))
@@ -23,27 +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
@@ -63,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"
@@ -154,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,49 +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.resetSelectFilters = ->
$scope.scheduleFilter = 0
$scope.involvingFilter = 0
$scope.query = ''
$scope.resetSelectFilters()
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', t('js.order_cycles.create_failure'))
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', t('js.order_cycles.update_failure'))
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,26 +0,0 @@
angular.module("admin.orders").controller "orderCtrl", ($scope, shops, orderCycles, $compile, $attrs, Orders) ->
$scope.$compile = $compile
$scope.shops = shops
$scope.orderCycles = orderCycles
$scope.distributor_id = parseInt($attrs.ofnDistributorId)
$scope.order_cycle_id = parseInt($attrs.ofnOrderCycleId)
$scope.validOrderCycle = (oc) ->
$scope.orderCycleHasDistributor oc, parseInt($scope.distributor_id)
$scope.distributorHasOrderCycles = (distributor) ->
(oc for oc in $scope.orderCycles when @orderCycleHasDistributor(oc, distributor.id)).length > 0
$scope.orderCycleHasDistributor = (oc, distributor_id) ->
distributor_ids = (d.id for d in oc.distributors)
distributor_ids.indexOf(distributor_id) != -1
$scope.distributionChosen = ->
$scope.distributor_id && $scope.order_cycle_id
for oc in $scope.orderCycles
oc.name_and_status = "#{oc.name} (#{oc.status})"
for shop in $scope.shops
shop.disabled = !$scope.distributorHasOrderCycles(shop)

View File

@@ -1,47 +1,26 @@
angular.module("admin.orders").controller "ordersCtrl", ($scope, RequestMonitor, Orders, SortOptions) ->
$scope.RequestMonitor = RequestMonitor
$scope.pagination = Orders.pagination
$scope.orders = Orders.all
$scope.sortOptions = SortOptions
$scope.per_page_options = [
{id: 15, name: t('js.admin.orders.index.per_page', results: 15)},
{id: 50, name: t('js.admin.orders.index.per_page', results: 50)},
{id: 100, name: t('js.admin.orders.index.per_page', results: 100)}
]
angular.module("admin.orders").controller "ordersCtrl", ($scope, $compile, $attrs, shops, orderCycles) ->
$scope.$compile = $compile
$scope.shops = shops
$scope.orderCycles = orderCycles
$scope.initialise = ->
$scope.per_page = 15
$scope.q = {
completed_at_not_null: true
}
$scope.fetchResults()
$scope.distributor_id = parseInt($attrs.ofnDistributorId)
$scope.order_cycle_id = parseInt($attrs.ofnOrderCycleId)
$scope.fetchResults = (page=1) ->
Orders.index({
'q[completed_at_lt]': $scope['q']['completed_at_lt'],
'q[completed_at_gt]': $scope['q']['completed_at_gt'],
'q[state_eq]': $scope['q']['state_eq'],
'q[number_cont]': $scope['q']['number_cont'],
'q[email_cont]': $scope['q']['email_cont'],
'q[bill_address_firstname_start]': $scope['q']['bill_address_firstname_start'],
'q[bill_address_lastname_start]': $scope['q']['bill_address_lastname_start'],
'q[completed_at_not_null]': $scope['q']['completed_at_not_null'],
'q[inventory_units_shipment_id_null]': $scope['q']['inventory_units_shipment_id_null'],
'q[distributor_id_in]': $scope['q']['distributor_id_in'],
'q[order_cycle_id_in]': $scope['q']['order_cycle_id_in'],
'q[order_cycle_id_in]': $scope['q']['order_cycle_id_in'],
'q[s]': $scope.sorting || 'completed_at desc',
per_page: $scope.per_page,
page: page
})
$scope.validOrderCycle = (oc) ->
$scope.orderCycleHasDistributor oc, parseInt($scope.distributor_id)
$scope.$watch 'sortOptions', (sort) ->
if sort && sort.predicate != ""
$scope.sorting = sort.predicate + ' desc' if sort.reverse
$scope.sorting = sort.predicate + ' asc' if !sort.reverse
$scope.fetchResults()
, true
$scope.distributorHasOrderCycles = (distributor) ->
(oc for oc in orderCycles when @orderCycleHasDistributor(oc, distributor.id)).length > 0
$scope.changePage = (newPage) ->
$scope.page = newPage
$scope.fetchResults(newPage)
$scope.orderCycleHasDistributor = (oc, distributor_id) ->
distributor_ids = (d.id for d in oc.distributors)
distributor_ids.indexOf(distributor_id) != -1
$scope.distributionChosen = ->
$scope.distributor_id && $scope.order_cycle_id
for oc in $scope.orderCycles
oc.name_and_status = "#{oc.name} (#{oc.status})"
for shop in $scope.shops
shop.disabled = !$scope.distributorHasOrderCycles(shop)

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,10 +0,0 @@
angular.module("admin.payments").controller "PaymentCtrl", ($scope, Payment, StatusMessage) ->
$scope.form_data = Payment.form_data
$scope.submitted = false
$scope.StatusMessage = StatusMessage
$scope.submitPayment = () ->
return false if $scope.submitted
$scope.submitted = true
StatusMessage.display 'progress', t("spree.admin.payments.source_forms.stripe.submitting_payment")
Payment.purchase()

View File

@@ -1,36 +0,0 @@
angular.module('admin.payments').directive "stripeElements", ($injector, AdminStripeElements) ->
restrict: 'E'
template: "<label for='card-element'>\
<div id='card-element'></div>\
<div id='card-errors' class='error'></div>\
</label>"
link: (scope, elem, attr)->
if $injector.has('stripeObject')
stripe = $injector.get('stripeObject')
card = stripe.elements().create 'card',
hidePostalCode: false
style:
base:
fontFamily: "Roboto, Arial, sans-serif"
fontSize: '16px'
color: '#5c5c5c'
'::placeholder':
color: '#6c6c6c'
card.mount('#card-element')
# Elements validates user input as it is typed. To help your customers
# catch mistakes, you should listen to change events on the card Element
# and display any errors:
card.addEventListener 'change', (event) ->
displayError = document.getElementById('card-errors')
if event.error
displayError.textContent = event.error.message
else
displayError.textContent = ''
return
AdminStripeElements.stripe = stripe
AdminStripeElements.card = card

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 +0,0 @@
angular.module("admin.payments", ['ofn.admin'])

View File

@@ -1,47 +0,0 @@
angular.module('admin.payments').factory 'Payment', (AdminStripeElements, currentOrderNumber, paymentMethods, PaymentMethods, PaymentResource, StatusMessage, $window)->
new class Payment
order: currentOrderNumber
form_data: {}
paymentMethodType: ->
PaymentMethods.byID[@form_data.payment_method].method_type
preprocess: ->
munged_payment = {}
munged_payment["payment"] = {payment_method_id: @form_data.payment_method, amount: @form_data.amount}
munged_payment["order_id"] = @order
# Not tested with Gateway other than Stripe. Could fall back to Rails for this?
# Works ok without extra source_attrs for Cash, Bank Transfer etc.
switch @paymentMethodType()
when 'gateway'
angular.extend munged_payment.payment, {
source_attributes:
number: @form_data.card_number
month: @form_data.card_month
year: @form_data.card_year
verification_value: @form_data.card_verification_value
}
when 'stripe'
angular.extend munged_payment.payment, {
source_attributes:
gateway_payment_profile_id: @form_data.token
cc_type: @form_data.cc_type
last_digits: @form_data.card.last4
month: @form_data.card.exp_month
year: @form_data.card.exp_year
}
munged_payment
purchase: ->
if @paymentMethodType() == 'stripe'
AdminStripeElements.requestToken(@form_data, @submit)
else
@submit()
submit: =>
munged = @preprocess()
PaymentResource.create({order_id: munged.order_id}, munged, (response, headers, status)=>
$window.location.pathname = "/admin/orders/" + munged.order_id + "/payments"
, (response) ->
StatusMessage.display 'error', t("spree.admin.payments.source_forms.stripe.error_saving_payment")
)

View File

@@ -1,38 +0,0 @@
angular.module("admin.payments").factory 'AdminStripeElements', ($rootScope, StatusMessage) ->
new class AdminStripeElements
# These are both set from the AdminStripeElements directive
stripe: null
card: null
# New Stripe Elements method
requestToken: (secrets, submit) ->
return unless @stripe? && @card?
cardData = @makeCardData(secrets)
@stripe.createToken(@card, cardData).then (response) =>
if(response.error)
StatusMessage.display 'error', response.error.message
else
secrets.token = response.token.id
secrets.cc_type = @mapCC(response.token.card.brand)
secrets.card = response.token.card
submit()
# Maps the brand returned by Stripe to that required by activemerchant
mapCC: (ccType) ->
switch ccType
when 'MasterCard' then return 'master'
when 'Visa' then return 'visa'
when 'American Express' then return 'american_express'
when 'Discover' then return 'discover'
when 'JCB' then return 'jcb'
when 'Diners Club' then return 'diners_club'
# It doesn't matter if any of these are nil, all are optional.
makeCardData: (secrets) ->
{'name': secrets.name,
'address1': secrets.address1,
'city': secrets.city,
'zipcode': secrets.zipcode}

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,158 +0,0 @@
angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $http, $filter, ProductImportService, ams_data, $timeout) ->
$scope.entries = {}
$scope.update_counts = {}
$scope.reset_counts = {}
$scope.enterprise_product_counts = ams_data.enterprise_product_counts
$scope.updates = {}
$scope.updated_total = 0
$scope.updated_ids = []
$scope.update_errors = []
$scope.step = 'settings'
$scope.chunks = 0
$scope.completed = 0
$scope.percentage = {
import: "0%",
save: "0%"
}
$scope.countResettable = () ->
angular.forEach $scope.enterprise_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.started = false
$scope.finished = false
$scope.step = 'settings'
$scope.confirmSettings = () ->
$scope.step = 'import'
$scope.start()
$scope.viewResults = () ->
$scope.countResettable()
$scope.step = 'results'
$scope.acceptResults = () ->
$scope.resetProgress()
$scope.step = 'save'
$scope.start()
$scope.finalResults = () ->
$scope.step = 'complete'
$scope.start = () ->
$scope.started = true
total = ams_data.item_count
size = 50
$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) ->
$http(
url: ams_data.import_url
method: 'POST'
data:
'start': start
'end': end
'filepath': ams_data.filepath
'settings': ams_data.importSettings
).success((data, status) ->
angular.merge($scope.entries, angular.fromJson(data['entries']))
$scope.sortUpdates(data['reset_counts'])
$scope.updateProgress()
).error((data, status) ->
$scope.exception = data
console.error(data)
)
$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) ->
$http(
url: ams_data.save_url
method: 'POST'
data:
'start': start
'end': end
'filepath': ams_data.filepath
'settings': ams_data.importSettings
).success((data, status) ->
$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) ->
$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 = () ->
return unless ams_data.importSettings['reset_all_absent']
enterprises_to_reset = []
angular.forEach $scope.reset_counts, (count, enterprise_id) ->
enterprises_to_reset.push(enterprise_id)
if enterprises_to_reset.length && $scope.updated_ids.length
$http(
url: ams_data.reset_url
method: 'POST'
data:
'filepath': ams_data.filepath
'settings': ams_data.importSettings
'reset_absent': true,
'updated_ids': $scope.updated_ids,
'enterprises_to_reset': enterprises_to_reset
).success((data, status) ->
$scope.updates.products_reset = data
).error((data, status) ->
console.error(data)
)
$scope.updateProgress = () ->
$scope.completed++
$scope.percentage[$scope.step] = String(Math.round(($scope.completed / $scope.chunks) * 100)) + '%'
if $scope.completed == $scope.chunks
$timeout($scope.viewResults, 1000) if $scope.step == 'import'
$timeout($scope.finalResults, 1000) if $scope.step == 'save'
$scope.resetAbsent() if $scope.step == 'save'

View File

@@ -1,25 +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 = {
import_into: 'product_list',
reset_all_absent: false
}
$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.$watch 'settings', (updated) ->
ProductImportService.updateSettings(updated)
, true
$scope.toggleResetAbsent = ->
checked = $scope.settings['reset_all_absent']
confirmed = confirm t('js.product_import.confirmation') if checked
if confirmed or !checked
ProductImportService.updateResetAbsent($scope.enterpriseId, $scope.reset_counts[$scope.enterpriseId], checked)
if confirmed or !$scope.resetAbsent
ProductImportService.updateResetAbsent($scope.supplierId, $scope.resetCount, $scope.resetAbsent)
else
$scope.settings['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 'entriesFilterEnterprise', ->
(entries, enterprise) ->
if enterprise == 'all'
return entries
filtered = {}
angular.forEach entries, (entry, line_number) ->
if enterprise == entry.attributes['enterprise']
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,21 +1,15 @@
angular.module("admin.productImport").factory "ProductImportService", ($rootScope) ->
angular.module("ofn.admin").factory "ProductImportService", ($rootScope) ->
new class ProductImportService
enterprises: {}
suppliers: {}
resetTotal: 0
settings: {}
updateResetAbsent: (enterpriseId, resetCount, resetAbsent) ->
updateResetAbsent: (supplierId, resetCount, resetAbsent) ->
if resetAbsent
@enterprises[enterpriseId] = resetCount
@suppliers[supplierId] = resetCount
@resetTotal += resetCount
else
@enterprises[enterpriseId] = null
@suppliers[supplierId] = null
@resetTotal -= resetCount
$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

@@ -8,10 +8,4 @@ angular.module("admin.resources").factory 'EnterpriseResource', ($resource) ->
isArray: true
'update':
method: 'PUT'
'removeLogo':
url: '/api/enterprises/:id/logo.json'
method: 'DELETE'
'removePromoImage':
url: '/api/enterprises/:id/promo_image.json'
method: 'DELETE'
})

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,8 +1,8 @@
angular.module("admin.resources").factory 'OrderResource', ($resource) ->
$resource('/admin/orders/:id/:action.json', {}, {
'index':
url: '/api/orders.json'
method: 'GET'
isArray: true
'update':
method: 'PUT'
})

View File

@@ -1,5 +0,0 @@
angular.module("admin.resources").factory 'PaymentResource', ($resource) ->
$resource('/admin/orders/:order_id/payments.json', {order_id: "@order_id"}, {
'create':
method: 'POST'
})

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

@@ -38,17 +38,3 @@ angular.module("admin.resources").factory 'Enterprises', ($q, EnterpriseResource
resetAttribute: (enterprise, attribute) ->
enterprise[attribute] = @pristineByID[enterprise.id][attribute]
performActionOnEnterpriseResource = (resourceAction) ->
(enterprise) ->
deferred = $q.defer()
resourceAction({id: enterprise.permalink}, ((data) =>
@pristineByID[enterprise.id] = angular.copy(data)
deferred.resolve(data)
), ((response) ->
deferred.reject(response)
))
deferred.promise
removeLogo: performActionOnEnterpriseResource(EnterpriseResource.removeLogo)
removePromoImage: performActionOnEnterpriseResource(EnterpriseResource.removePromoImage)

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: ->
['name', 'orders_open_at','orders_close_at']
resetAttribute: (order_cycle, attribute) ->
order_cycle[attribute] = @pristineByID[order_cycle.id][attribute]

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