diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..554c663b152 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +# http://EditorConfig.org +# https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true +tab_width = 2 + +[**.rb] +max_line_length = 80 + +[**.js, **.coffee] +max_line_length = 120 + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index 08d1fb20340..460a70fdcc3 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,4 @@ test_app **/coverage */.sass-cache .localeapp +guides diff --git a/.travis.yml b/.travis.yml index 6bc226849b8..6a3bf10a083 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,4 @@ script: - bundle exec rake test_app - bundle exec rake spec rvm: - - 1.9.3 - - 2.0.0 - - 2.1.0 + - 2.1.5 diff --git a/README.md b/README.md index 07712e15d7f..5404f28a58f 100755 --- a/README.md +++ b/README.md @@ -34,9 +34,9 @@ The fastest way to get started is by using the spree command line tool available in the spree gem which will add Spree to an existing Rails application. ```shell -gem install rails -v 4.0.4 +gem install rails -v 4.0.12 gem install spree -rails _4.0.4_ new my_store +rails _4.0.12_ new my_store spree install my_store ``` @@ -293,7 +293,7 @@ bash build.sh Further Documentation ------------ -Spree has a number of really useful guides online at [http://guides.spreecommerce.com](http://guides.spreecommerce.com). +Spree has a number of really useful guides online at [http://guides.spreecommerce.com](http://guides.spreecommerce.com). Contributing ------------ diff --git a/Rakefile b/Rakefile index 2f014273b0b..0e9055ce050 100644 --- a/Rakefile +++ b/Rakefile @@ -13,10 +13,22 @@ Gem::PackageTask.new(spec) do |pkg| pkg.gem_spec = spec end +task :default => :test + +desc "Runs all tests in all Spree engines" +task :test do + Rake::Task['test_app'].invoke + %w(api backend core frontend).each do |gem_name| + Dir.chdir("#{File.dirname(__FILE__)}/#{gem_name}") do + system("rspec --fail-fast") or exit!(1) + end + end +end + desc "Generates a dummy app for testing for every Spree engine" task :test_app do require File.expand_path('../core/lib/generators/spree/install/install_generator', __FILE__) - %w(api backend core frontend).each do |engine| + %w(api backend core frontend sample).each do |engine| ENV['LIB_NAME'] = File.join('spree', engine) ENV['DUMMY_PATH'] = File.expand_path("../#{engine}/spec/dummy", __FILE__) Rake::Task['common:test_app'].execute diff --git a/SPREE_VERSION b/SPREE_VERSION index b1b25a5ffae..258e43cb48f 100644 --- a/SPREE_VERSION +++ b/SPREE_VERSION @@ -1 +1 @@ -2.2.2 +2.2.10.beta diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 86fb04376df..c20a3992b8c 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -1,9 +1 @@ -## Spree 2.2.2 (unreleased) ## - -* refactor the api to use a general importer in core gem. - - * Peter Berkenbosch - -* Allow for linking of users to orders by admins - - * Ryan Bigg +## Spree 2.2.5 (unreleased) ## \ No newline at end of file diff --git a/api/app/controllers/spree/api/base_controller.rb b/api/app/controllers/spree/api/base_controller.rb index aef1fcc7d81..ea98b79cc8d 100644 --- a/api/app/controllers/spree/api/base_controller.rb +++ b/api/app/controllers/spree/api/base_controller.rb @@ -123,22 +123,27 @@ def find_product(id) end def product_scope - variants_associations = [{ option_values: :option_type }, :default_price, :prices, :images] if current_api_user.has_spree_role?("admin") - scope = Product.with_deleted.accessible_by(current_ability, :read) - .includes(:properties, :option_types, variants: variants_associations, master: variants_associations) + scope = Product.with_deleted.accessible_by(current_ability, :read).includes(*product_includes) unless params[:show_deleted] scope = scope.not_deleted end else - scope = Product.accessible_by(current_ability, :read).active - .includes(:properties, :option_types, variants: variants_associations, master: variants_associations) + scope = Product.accessible_by(current_ability, :read).active.includes(*product_includes) end scope end + def variants_associations + [{ option_values: :option_type }, :default_price, :images] + end + + def product_includes + [ :option_types, variants: variants_associations, master: variants_associations ] + end + def order_id params[:order_id] || params[:checkout_id] || params[:order_number] end diff --git a/api/app/controllers/spree/api/checkouts_controller.rb b/api/app/controllers/spree/api/checkouts_controller.rb index 19b36ee0bc4..db73cf0b7d6 100644 --- a/api/app/controllers/spree/api/checkouts_controller.rb +++ b/api/app/controllers/spree/api/checkouts_controller.rb @@ -42,6 +42,51 @@ def load_order raise_insufficient_quantity and return if @order.insufficient_stock_lines.present? end + def object_params + modify_payment_attributes params[:order] || {} + + protected_params = if params[:order] + params.require(:order).permit(permitted_checkout_attributes) + else + {} + end + + map_nested_attributes_keys Order, protected_params + end + + def user_id + params[:order][:user_id] if params[:order] + end + + # For payment step, filter order parameters to produce the expected + # nested attributes for a single payment and its source, discarding + # attributes for payment methods other than the one selected + # + # respond_to check is necessary due to issue described in #2910 + def modify_payment_attributes(object_params) + if @order.has_checkout_step?('payment') && @order.payment? + if object_params[:payments_attributes].is_a?(Hash) + object_params[:payments_attributes] = [object_params[:payments_attributes]] + end + if object_params[:payment_source].present? && source_params = object_params.delete(:payment_source)[object_params[:payments_attributes].first[:payment_method_id].to_s] + object_params[:payments_attributes].first[:source_attributes] = source_params + end + if object_params[:payments_attributes] + object_params[:payments_attributes].first[:amount] = @order.total.to_s + end + end + end + + def nested_params + map_nested_attributes_keys Order, params[:order] || {} + end + + # Should be overriden if you have areas of your checkout that don't match + # up to a step within checkout_steps, such as a registration step + def skip_state_validation? + false + end + def update_order_state @order.state = params[:state] if params[:state] state_callback(:before) @@ -58,6 +103,7 @@ def state_callback(before_or_after = :before) send(method_name) if respond_to?(method_name, true) end + # This is used in cancan def order_id super || params[:id] end diff --git a/api/app/controllers/spree/api/inventory_units_controller.rb b/api/app/controllers/spree/api/inventory_units_controller.rb index b2cd76b7d9a..8a3ad63ed54 100644 --- a/api/app/controllers/spree/api/inventory_units_controller.rb +++ b/api/app/controllers/spree/api/inventory_units_controller.rb @@ -5,6 +5,7 @@ class InventoryUnitsController < Spree::Api::BaseController def show @inventory_unit = inventory_unit + respond_with(@inventory_unit) end def update diff --git a/api/app/controllers/spree/api/option_types_controller.rb b/api/app/controllers/spree/api/option_types_controller.rb index 287678230ad..c7168c3fbde 100644 --- a/api/app/controllers/spree/api/option_types_controller.rb +++ b/api/app/controllers/spree/api/option_types_controller.rb @@ -3,9 +3,9 @@ module Api class OptionTypesController < Spree::Api::BaseController def index if params[:ids] - @option_types = Spree::OptionType.accessible_by(current_ability, :read).where(:id => params[:ids].split(',')) + @option_types = Spree::OptionType.includes(:option_values).accessible_by(current_ability, :read).where(id: params[:ids].split(',')) else - @option_types = Spree::OptionType.accessible_by(current_ability, :read).load.ransack(params[:q]).result + @option_types = Spree::OptionType.includes(:option_values).accessible_by(current_ability, :read).load.ransack(params[:q]).result end respond_with(@option_types) end diff --git a/api/app/controllers/spree/api/option_values_controller.rb b/api/app/controllers/spree/api/option_values_controller.rb index e0d9c668bb3..b24c8b9ac86 100644 --- a/api/app/controllers/spree/api/option_values_controller.rb +++ b/api/app/controllers/spree/api/option_values_controller.rb @@ -51,7 +51,7 @@ def scope end def option_value_params - params.require(:option_value).permit(permitted_option_type_attributes) + params.require(:option_value).permit(permitted_option_value_attributes) end end end diff --git a/api/app/controllers/spree/api/orders_controller.rb b/api/app/controllers/spree/api/orders_controller.rb index 5afd27e32e4..fd5b3d0efc2 100644 --- a/api/app/controllers/spree/api/orders_controller.rb +++ b/api/app/controllers/spree/api/orders_controller.rb @@ -7,6 +7,8 @@ class OrdersController < Spree::Api::BaseController class_attribute :admin_order_attributes self.admin_order_attributes = [:import, :number, :completed_at, :locked_at, :channel] + wrap_parameters false + skip_before_filter :check_for_user_or_api_key, only: :apply_coupon_code skip_before_filter :authenticate_user, only: :apply_coupon_code diff --git a/api/app/controllers/spree/api/payments_controller.rb b/api/app/controllers/spree/api/payments_controller.rb index 89d54b14b19..89b409ecd65 100644 --- a/api/app/controllers/spree/api/payments_controller.rb +++ b/api/app/controllers/spree/api/payments_controller.rb @@ -12,7 +12,7 @@ def index end def new - @payment_methods = Spree::PaymentMethod.where(environment: Rails.env) + @payment_methods = Spree::PaymentMethod.available respond_with(@payment_method) end diff --git a/api/app/controllers/spree/api/products_controller.rb b/api/app/controllers/spree/api/products_controller.rb index 100059c34e7..59068f63457 100644 --- a/api/app/controllers/spree/api/products_controller.rb +++ b/api/app/controllers/spree/api/products_controller.rb @@ -12,6 +12,7 @@ def index @products = @products.distinct.page(params[:page]).per(params[:per_page]) expires_in 15.minutes, :public => true headers['Surrogate-Control'] = "max-age=#{15.minutes}" + respond_with(@products) end def show @@ -19,6 +20,7 @@ def show expires_in 15.minutes, :public => true headers['Surrogate-Control'] = "max-age=#{15.minutes}" headers['Surrogate-Key'] = "product_id=1" + respond_with(@product) end # Takes besides the products attributes either an array of variants or diff --git a/api/app/controllers/spree/api/shipments_controller.rb b/api/app/controllers/spree/api/shipments_controller.rb index bdd4b56e753..568e0d62873 100644 --- a/api/app/controllers/spree/api/shipments_controller.rb +++ b/api/app/controllers/spree/api/shipments_controller.rb @@ -29,27 +29,14 @@ def create @shipment = @order.shipments.create(stock_location_id: params[:stock_location_id]) @order.contents.add(variant, quantity, nil, @shipment) - @shipment.refresh_rates @shipment.save! respond_with(@shipment.reload, default_template: :show) end def update - unlock = params[:shipment].delete(:unlock) - - if unlock == 'yes' - @shipment.adjustment.open - end - - @shipment.update_attributes(shipment_params) - - if unlock == 'yes' - @shipment.adjustment.close - end - - @shipment.reload - respond_with(@shipment, default_template: :show) + @shipment.update_attributes_and_order(shipment_params) + respond_with(@shipment.reload, default_template: :show) end def ready diff --git a/api/app/controllers/spree/api/taxons_controller.rb b/api/app/controllers/spree/api/taxons_controller.rb index 72253489b16..02e03678df8 100644 --- a/api/app/controllers/spree/api/taxons_controller.rb +++ b/api/app/controllers/spree/api/taxons_controller.rb @@ -65,7 +65,7 @@ def products # Products#index does not do the sorting. taxon = Spree::Taxon.find(params[:id]) @products = taxon.products.ransack(params[:q]).result - @products = @products.page(params[:page]).per(500 || params[:per_page]) + @products = @products.page(params[:page]).per(params[:per_page] || 500) render "spree/api/products/index" end diff --git a/api/app/views/spree/api/addresses/show.v1.rabl b/api/app/views/spree/api/addresses/show.v1.rabl index bdb0914182e..c3416013804 100644 --- a/api/app/views/spree/api/addresses/show.v1.rabl +++ b/api/app/views/spree/api/addresses/show.v1.rabl @@ -1,5 +1,5 @@ object @address -cache @address +cache [I18n.locale, root_object] attributes *address_attributes child(:country) do |address| diff --git a/api/app/views/spree/api/adjustments/show.v1.rabl b/api/app/views/spree/api/adjustments/show.v1.rabl index fe3810baed2..e88c3d801d7 100644 --- a/api/app/views/spree/api/adjustments/show.v1.rabl +++ b/api/app/views/spree/api/adjustments/show.v1.rabl @@ -1,4 +1,4 @@ object @adjustment -cache @adjustment +cache [I18n.locale, root_object] attributes *adjustment_attributes -node(:display_amount) { |a| a.display_amount.to_s } \ No newline at end of file +node(:display_amount) { |a| a.display_amount.to_s } diff --git a/api/app/views/spree/api/credit_cards/show.v1.rabl b/api/app/views/spree/api/credit_cards/show.v1.rabl index 7aefc289076..57d734d6abf 100644 --- a/api/app/views/spree/api/credit_cards/show.v1.rabl +++ b/api/app/views/spree/api/credit_cards/show.v1.rabl @@ -1,3 +1,3 @@ object @credit_card -cache @credit_card -attributes *creditcard_attributes \ No newline at end of file +cache [I18n.locale, root_object] +attributes *creditcard_attributes diff --git a/api/app/views/spree/api/line_items/show.v1.rabl b/api/app/views/spree/api/line_items/show.v1.rabl index ac742293b61..e64a9796435 100644 --- a/api/app/views/spree/api/line_items/show.v1.rabl +++ b/api/app/views/spree/api/line_items/show.v1.rabl @@ -1,5 +1,5 @@ object @line_item -cache @line_item +cache [I18n.locale, root_object] attributes *line_item_attributes node(:single_display_amount) { |li| li.single_display_amount.to_s } node(:display_amount) { |li| li.display_amount.to_s } diff --git a/api/app/views/spree/api/orders/order.v1.rabl b/api/app/views/spree/api/orders/order.v1.rabl index c67a2f6d0df..4485ab0d175 100644 --- a/api/app/views/spree/api/orders/order.v1.rabl +++ b/api/app/views/spree/api/orders/order.v1.rabl @@ -1,4 +1,4 @@ -cache @order +cache [I18n.locale, root_object] attributes *order_attributes node(:display_item_total) { |o| o.display_item_total.to_s } node(:total_quantity) { |o| o.line_items.sum(:quantity) } diff --git a/api/app/views/spree/api/products/show.v1.rabl b/api/app/views/spree/api/products/show.v1.rabl index b45f8b66327..223183dca08 100644 --- a/api/app/views/spree/api/products/show.v1.rabl +++ b/api/app/views/spree/api/products/show.v1.rabl @@ -1,5 +1,5 @@ object @product -cache [current_currency, root_object] +cache [I18n.locale, current_currency, root_object] attributes *product_attributes node(:display_price) { |p| p.display_price.to_s } node(:has_variants) { |p| p.has_variants? } diff --git a/api/app/views/spree/api/shipments/show.v1.rabl b/api/app/views/spree/api/shipments/show.v1.rabl index 4320ed6db05..03b72bbc9db 100644 --- a/api/app/views/spree/api/shipments/show.v1.rabl +++ b/api/app/views/spree/api/shipments/show.v1.rabl @@ -1,5 +1,5 @@ object @shipment -cache @shipment +cache [I18n.locale, root_object] attributes *shipment_attributes node(:order_id) { |shipment| shipment.order.number } node(:stock_location_name) { |shipment| shipment.stock_location.name } diff --git a/api/app/views/spree/api/variants/big.v1.rabl b/api/app/views/spree/api/variants/big.v1.rabl index 5422cf329a1..dc5efaba97a 100644 --- a/api/app/views/spree/api/variants/big.v1.rabl +++ b/api/app/views/spree/api/variants/big.v1.rabl @@ -1,7 +1,7 @@ object @variant attributes *variant_attributes -cache ['big_variant', root_object] +cache [I18n.locale, 'big_variant', root_object] extends "spree/api/variants/small" diff --git a/api/app/views/spree/api/variants/show.v1.rabl b/api/app/views/spree/api/variants/show.v1.rabl index 40b286a805f..7e51886a7a9 100644 --- a/api/app/views/spree/api/variants/show.v1.rabl +++ b/api/app/views/spree/api/variants/show.v1.rabl @@ -1,3 +1,3 @@ object @variant -cache ['show', root_object] +cache [I18n.locale, 'show', root_object] extends "spree/api/variants/big" diff --git a/api/app/views/spree/api/variants/small.v1.rabl b/api/app/views/spree/api/variants/small.v1.rabl index e8afa214608..2573603b48f 100644 --- a/api/app/views/spree/api/variants/small.v1.rabl +++ b/api/app/views/spree/api/variants/small.v1.rabl @@ -1,5 +1,5 @@ attributes *variant_attributes -cache ['small_variant', root_object] +cache [I18n.locale, 'small_variant', root_object] node(:display_price) { |p| p.display_price.to_s } node(:options_text) { |v| v.options_text } diff --git a/api/spec/controllers/spree/api/base_controller_spec.rb b/api/spec/controllers/spree/api/base_controller_spec.rb index 5521615ec01..ee68b8f3ff3 100644 --- a/api/spec/controllers/spree/api/base_controller_spec.rb +++ b/api/spec/controllers/spree/api/base_controller_spec.rb @@ -101,4 +101,7 @@ def index end end + it "lets a subclass override the product associations that are eager-loaded" do + controller.respond_to?(:product_includes, true).should be + end end diff --git a/api/spec/controllers/spree/api/option_values_controller_spec.rb b/api/spec/controllers/spree/api/option_values_controller_spec.rb index 2a00e5c405a..511dd02b59b 100644 --- a/api/spec/controllers/spree/api/option_values_controller_spec.rb +++ b/api/spec/controllers/spree/api/option_values_controller_spec.rb @@ -111,6 +111,13 @@ def check_option_values(option_values) option_value.name.should == "Option Value" end + it "permits the correct attributes" do + controller.should_receive(:permitted_option_value_attributes) + api_put :update, :id => option_value.id, :option_value => { + :name => "" + } + end + it "cannot update an option value with invalid attributes" do api_put :update, :id => option_value.id, :option_value => { :name => "" diff --git a/api/spec/controllers/spree/api/orders_controller_spec.rb b/api/spec/controllers/spree/api/orders_controller_spec.rb index ff5eccfb2e4..24c2c8986fd 100755 --- a/api/spec/controllers/spree/api/orders_controller_spec.rb +++ b/api/spec/controllers/spree/api/orders_controller_spec.rb @@ -235,7 +235,7 @@ module Spree expect(Order).to receive(:create!) { order } allow(order).to receive(:contents) { double(associate_user: true, add: line_item) } - expect(line_item).to receive(:update_attributes).with("special" => true) + expect(line_item).to receive(:update_attributes!).with("special" => true) controller.stub(permitted_line_item_attributes: [:id, :variant_id, :quantity, :special]) api_post :create, :order => { @@ -553,6 +553,23 @@ def clean_address(address) expect(updated_at.split("T").last).to have_content(milisecond) end + context "caching enabled" do + before do + ActionController::Base.perform_caching = true + 3.times { Order.create } + end + + it "returns unique orders" do + api_get :index + + orders = json_response["orders"] + expect(orders.count).to be >= 3 + expect(orders.map { |o| o["id"] }.sort).to eq(Order.order(:id).pluck(:id)) + end + + after { ActionController::Base.perform_caching = false } + end + context "with two orders" do before { create(:order) } @@ -667,4 +684,3 @@ def clean_address(address) end end end - diff --git a/api/spec/controllers/spree/api/payments_controller_spec.rb b/api/spec/controllers/spree/api/payments_controller_spec.rb index 068fb1b817a..0636a9278e5 100644 --- a/api/spec/controllers/spree/api/payments_controller_spec.rb +++ b/api/spec/controllers/spree/api/payments_controller_spec.rb @@ -89,6 +89,11 @@ module Spree api_get :index, :order_id => order.to_param assert_unauthorized! end + + it "can view the payments for an order given the order token" do + api_get :index, :order_id => order.to_param, :order_token => order.token + json_response["payments"].first.should have_attributes(attributes) + end end end diff --git a/api/spec/controllers/spree/api/products_controller_spec.rb b/api/spec/controllers/spree/api/products_controller_spec.rb index 4ed1814e235..acba3e88c0d 100644 --- a/api/spec/controllers/spree/api/products_controller_spec.rb +++ b/api/spec/controllers/spree/api/products_controller_spec.rb @@ -67,6 +67,34 @@ module Spree json_response["per_page"].should == Kaminari.config.default_per_page end + context "specifying a rabl template for a custom action" do + before do + Spree::Api::ProductsController.class_eval do + def custom_show + @product = find_product(params[:id]) + respond_with(@product) + end + end + end + + it "uses the specified custom template through the request header" do + request.headers['X-Spree-Template'] = 'show' + api_get :custom_show, :id => product.id + response.should render_template('spree/api/products/show') + end + + it "uses the specified custom template through the template URL parameter" do + api_get :custom_show, :id => product.id, :template => 'show' + response.should render_template('spree/api/products/show') + end + + it "falls back to the default template if the specified template does not exist" do + request.headers['X-Spree-Template'] = 'invoice' + api_get :show, :id => product.id + response.should render_template('spree/api/products/show') + end + end + context "product has more than one price" do before { product.master.prices.create currency: "EUR", amount: 22 } diff --git a/api/spec/features/checkout_spec.rb b/api/spec/features/checkout_spec.rb index b1b2025eb9d..7d24a786321 100644 --- a/api/spec/features/checkout_spec.rb +++ b/api/spec/features/checkout_spec.rb @@ -62,7 +62,7 @@ def add_address(address, billing: true) # It seems we are missing an order-scoped address api endpoint since we need # to use update here. expect { - update_order(order_params: { order: { address_type => address.attributes } }) + update_order(order_params: { order: { address_type => address.attributes.except('id') } }) }.to change { @order.reload.public_send(address_type) }.to address end @@ -125,8 +125,8 @@ def assert_order_expectations create_order(order_params: { order: { - bill_address: bill_address.as_json, - ship_address: ship_address.as_json, + bill_address: bill_address.attributes.except('id').as_json, + ship_address: ship_address.attributes.except('id').as_json, line_items: { 0 => { variant_id: variant_1.id, quantity: 2 }, 1 => { variant_id: variant_2.id, quantity: 2 } @@ -157,8 +157,8 @@ def assert_order_expectations create_order update_order(order_params: { order: { - bill_address: bill_address.as_json, - ship_address: ship_address.as_json, + bill_address: bill_address.attributes.except('id').as_json, + ship_address: ship_address.attributes.except('id').as_json, line_items: { 0 => { variant_id: variant_1.id, quantity: 2 }, 1 => { variant_id: variant_2.id, quantity: 2 } diff --git a/backend/CHANGELOG.md b/backend/CHANGELOG.md index 2e2c06f8b26..ff2cc913ef3 100644 --- a/backend/CHANGELOG.md +++ b/backend/CHANGELOG.md @@ -1 +1 @@ -## Spree 2.2.1 (unreleased) ## +## Spree 2.2.5 (unreleased) ## diff --git a/backend/app/assets/javascripts/spree/backend/images/index.js.coffee b/backend/app/assets/javascripts/spree/backend/images/index.js.coffee index a7fab5d7350..38823e48a90 100644 --- a/backend/app/assets/javascripts/spree/backend/images/index.js.coffee +++ b/backend/app/assets/javascripts/spree/backend/images/index.js.coffee @@ -13,3 +13,4 @@ $ -> ) success: (r) -> ($ '#images').html r + ($ '.select2').select2() diff --git a/backend/app/assets/javascripts/spree/backend/payments/new.js b/backend/app/assets/javascripts/spree/backend/payments/new.js index 48aa63f90b8..f5c0cecb0b9 100644 --- a/backend/app/assets/javascripts/spree/backend/payments/new.js +++ b/backend/app/assets/javascripts/spree/backend/payments/new.js @@ -12,7 +12,9 @@ $(document).ready(function() { $('.payment_methods_radios').click( function() { $('.payment-methods').hide(); + $('.payment-methods input').prop('disabled', true); if (this.checked) { + $('#payment_method_' + this.value + ' input').prop('disabled', false); $('#payment_method_' + this.value).show(); } } @@ -21,9 +23,11 @@ $(document).ready(function() { $('.payment_methods_radios').each( function() { if (this.checked) { + $('#payment_method_' + this.value + ' input').prop('disabled', false); $('#payment_method_' + this.value).show(); } else { $('#payment_method_' + this.value).hide(); + $('#payment_method_' + this.value + ' input').prop('disabled', true); } if ($("#card_new" + this.value).is("*")) { diff --git a/backend/app/assets/javascripts/spree/backend/stock_transfer.js.coffee b/backend/app/assets/javascripts/spree/backend/stock_transfer.js.coffee index 78d9a3e6eaa..0f1a56d4e86 100644 --- a/backend/app/assets/javascripts/spree/backend/stock_transfer.js.coffee +++ b/backend/app/assets/javascripts/spree/backend/stock_transfer.js.coffee @@ -82,33 +82,48 @@ $ -> refresh_variants: -> if @receiving_stock() - @_refresh_transfer_variants() + @_search_transfer_variants() else - @_refresh_transfer_stock_items() + @_search_transfer_stock_items() - _refresh_transfer_variants: -> - if @cached_variants? - @populate_select @cached_variants - else - $.getJSON Spree.url(Spree.routes.variants_api), (data) => - @cached_variants = _.map(data.variants, (variant) -> new TransferVariant(variant)) - @populate_select @cached_variants + _search_transfer_variants: -> + @build_select(Spree.url(Spree.routes.variants_api), 'product_name_or_sku_cont') - _refresh_transfer_stock_items: -> + _search_transfer_stock_items: -> stock_location_id = $('#transfer_source_location_id').val() - $.getJSON Spree.url(Spree.routes.stock_locations_api + "/#{stock_location_id}/stock_items"), (data) => - @populate_select _.map(data.stock_items, (stock_item) -> new TransferStockItem(stock_item)) - - populate_select: (variants) -> - $('#transfer_variant').children('option').remove() - - for variant in variants - $('#transfer_variant').append($('') - .text(variant.name) - .prop('value', variant.id) - .data('variant', variant)) + @build_select(Spree.url(Spree.routes.stock_locations_api + "/#{stock_location_id}/stock_items"), + 'variant_product_name_or_variant_sku_cont') + + format_variant_result: (result) -> + "#{result.name} - #{result.sku}" + + build_select: (url, query) -> + $('#transfer_variant').select2 + minimumInputLength: 3 + ajax: + url: url + datatype: "json" + data: (term, page) -> + query_object = {} + query_object[query] = term + q: query_object + + results: (data, page) -> + result = data["variants"] || data["stock_items"] + # Format stock items as variants + if data["stock_items"]? + result = _(result).map (variant) -> + variant.variant + window.variants = result + results: result + + formatResult: @format_variant_result + formatSelection: (variant) -> + if !!variant.options_text + variant.name + " (#{variant.options_text})" + " - #{variant.sku}" + else + variant.name + " - #{variant.sku}" - $('#transfer_variant').select2() # Add/Remove variant line items class TransferAddVariants @@ -120,7 +135,10 @@ $ -> $('button.transfer_add_variant').click (event) => event.preventDefault() - @add_variant() + if $('#transfer_variant').select2('data')? + @add_variant() + else + alert('Please select a variant first') $('#transfer-variants-table').on 'click', '.transfer_remove_variant', (event) => event.preventDefault() @@ -132,7 +150,7 @@ $ -> false add_variant: -> - variant = $('#transfer_variant option:selected').data('variant') + variant = $('#transfer_variant').select2('data') quantity = parseInt $('#transfer_variant_quantity').val() variant = @find_or_add(variant) @@ -143,7 +161,7 @@ $ -> if existing = _.find(@variants, (v) -> v.id == variant.id) return existing else - variant = $.extend({}, variant) + variant = new TransferVariant($.extend({}, variant)) @variants.push variant return variant diff --git a/backend/app/assets/javascripts/spree/backend/taxon_autocomplete.js.erb b/backend/app/assets/javascripts/spree/backend/taxon_autocomplete.js.erb index 558272dde65..83aaa2a8a03 100644 --- a/backend/app/assets/javascripts/spree/backend/taxon_autocomplete.js.erb +++ b/backend/app/assets/javascripts/spree/backend/taxon_autocomplete.js.erb @@ -20,6 +20,7 @@ $(document).ready(function () { return { per_page: 50, page: page, + without_children: true, q: { name_cont: term }, diff --git a/backend/app/assets/stylesheets/spree/backend/globals/_variables.scss b/backend/app/assets/stylesheets/spree/backend/globals/_variables.scss index 401f5795581..8829e688d3e 100644 --- a/backend/app/assets/stylesheets/spree/backend/globals/_variables.scss +++ b/backend/app/assets/stylesheets/spree/backend/globals/_variables.scss @@ -104,6 +104,8 @@ $color-ste-void-bg: $color-error !default; $color-ste-void-text: $color-1 !default; $color-ste-canceled-bg: $color-error !default; $color-ste-canceled-text: $color-1 !default; +$color-ste-failed-bg: $color-error !default; +$color-ste-failed-text: $color-1 !default; $color-ste-address-bg: $color-error !default; $color-ste-address-text: $color-1 !default; $color-ste-checkout-bg: $color-notice !default; @@ -131,18 +133,18 @@ $color-ste-error-text: $color-1 !default; // Available states $states: completed, complete, sold, pending, awaiting_return, returned, credit_owed, paid, shipped, balance_due, backorder, checkout, cart, address, -delivery, payment, confirm, canceled, ready, void, active, inactive, considered_risky, success, notice, error !default; +delivery, payment, confirm, canceled, failed, ready, void, active, inactive, considered_risky, success, notice, error !default; $states-bg-colors: $color-ste-completed-bg, $color-ste-complete-bg, $color-ste-sold-bg, $color-ste-pending-bg, $color-ste-awaiting_return-bg, -$color-ste-returned-bg, $color-ste-credit_owed-bg, $color-ste-paid-bg, $color-ste-shipped-bg, $color-ste-balance_due-bg, $color-ste-backorder-bg, -$color-ste-checkout-bg, $color-ste-cart-bg, $color-ste-address-bg, $color-ste-delivery-bg, $color-ste-payment-bg, $color-ste-confirm-bg, -$color-ste-canceled-bg, $color-ste-ready-bg, $color-ste-void-bg, $color-ste-active-bg, $color-ste-inactive-bg, $color-ste-considered_risky-bg, +$color-ste-returned-bg, $color-ste-credit_owed-bg, $color-ste-paid-bg, $color-ste-shipped-bg, $color-ste-balance_due-bg, $color-ste-backorder-bg, +$color-ste-checkout-bg, $color-ste-cart-bg, $color-ste-address-bg, $color-ste-delivery-bg, $color-ste-payment-bg, $color-ste-confirm-bg, +$color-ste-canceled-bg, $color-ste-failed-bg, $color-ste-ready-bg, $color-ste-void-bg, $color-ste-active-bg, $color-ste-inactive-bg, $color-ste-considered_risky-bg, $color-ste-success-bg, $color-ste-notice-bg, $color-ste-error-bg !default; -$states-text-colors: $color-ste-completed-text, $color-ste-complete-text, $color-ste-sold-text, $color-ste-pending-text, $color-ste-awaiting_return-text, -$color-ste-returned-text, $color-ste-credit_owed-text, $color-ste-paid-text, $color-ste-shipped-text, $color-ste-balance_due-text, $color-ste-backorder-text, -$color-ste-checkout-text, $color-ste-cart-text, $color-ste-address-text, $color-ste-delivery-text, $color-ste-payment-text, $color-ste-confirm-text, -$color-ste-canceled-text, $color-ste-ready-text, $color-ste-void-text, $color-ste-active-text, $color-ste-inactive-text, $color-ste-considered_risky-text, +$states-text-colors: $color-ste-completed-text, $color-ste-complete-text, $color-ste-sold-text, $color-ste-pending-text, $color-ste-awaiting_return-text, +$color-ste-returned-text, $color-ste-credit_owed-text, $color-ste-paid-text, $color-ste-shipped-text, $color-ste-balance_due-text, $color-ste-backorder-text, +$color-ste-checkout-text, $color-ste-cart-text, $color-ste-address-text, $color-ste-delivery-text, $color-ste-payment-text, $color-ste-confirm-text, +$color-ste-canceled-text, $color-ste-failed-text, $color-ste-ready-text, $color-ste-void-text, $color-ste-active-text, $color-ste-inactive-text, $color-ste-considered_risky-text, $color-ste-success-text, $color-ste-notice-text, $color-ste-error-text !default; // Available actions diff --git a/backend/app/assets/stylesheets/spree/backend/plugins/_jstree.scss b/backend/app/assets/stylesheets/spree/backend/plugins/_jstree.scss index 77f5697e7da..e8ad28a03cd 100644 --- a/backend/app/assets/stylesheets/spree/backend/plugins/_jstree.scss +++ b/backend/app/assets/stylesheets/spree/backend/plugins/_jstree.scss @@ -53,7 +53,7 @@ } #vakata-dragged.jstree-apple .jstree-ok { @extend .fa; - @extend .fa-ok; + @extend .fa-check; color: $color-2; } diff --git a/backend/app/controllers/spree/admin/adjustments_controller.rb b/backend/app/controllers/spree/admin/adjustments_controller.rb index e465295a0bb..5fcc3f9d654 100644 --- a/backend/app/controllers/spree/admin/adjustments_controller.rb +++ b/backend/app/controllers/spree/admin/adjustments_controller.rb @@ -1,47 +1,32 @@ module Spree module Admin class AdjustmentsController < ResourceController - belongs_to 'spree/order', :find_by => :number - destroy.after :reload_order - destroy.after :update_totals + + belongs_to 'spree/order', find_by: :number + create.after :update_totals + destroy.after :update_totals update.after :update_totals - skip_before_filter :load_resource, :only => [:toggle_state, :edit, :update, :destroy] + skip_before_filter :load_resource, only: [:toggle_state, :edit, :update, :destroy] + + before_action :find_adjustment, only: [:destroy, :edit, :update] def index @adjustments = @order.all_adjustments.order("created_at ASC") end - def edit - find_adjustment - super - end - - def update - find_adjustment - super - end - - def destroy - find_adjustment - super - end - private + def find_adjustment # Need to assign to @object here to keep ResourceController happy @adjustment = @object = parent.all_adjustments.find(params[:id]) end - def reload_order - @order.reload - end - def update_totals - @order.updater.update_adjustment_total - @order.persist_totals + @order.reload.update! end + end end end diff --git a/backend/app/controllers/spree/admin/orders_controller.rb b/backend/app/controllers/spree/admin/orders_controller.rb index 03ef7125298..0522688b2f2 100644 --- a/backend/app/controllers/spree/admin/orders_controller.rb +++ b/backend/app/controllers/spree/admin/orders_controller.rb @@ -23,11 +23,11 @@ def index params[:q].delete(:inventory_units_shipment_id_null) if params[:q][:inventory_units_shipment_id_null] == "0" - if !params[:q][:created_at_gt].blank? + if params[:q][:created_at_gt].present? params[:q][:created_at_gt] = Time.zone.parse(params[:q][:created_at_gt]).beginning_of_day rescue "" end - if !params[:q][:created_at_lt].blank? + if params[:q][:created_at_lt].present? params[:q][:created_at_lt] = Time.zone.parse(params[:q][:created_at_lt]).end_of_day rescue "" end diff --git a/backend/app/controllers/spree/admin/products_controller.rb b/backend/app/controllers/spree/admin/products_controller.rb index 876580ddcd5..6ff3bca3716 100644 --- a/backend/app/controllers/spree/admin/products_controller.rb +++ b/backend/app/controllers/spree/admin/products_controller.rb @@ -60,7 +60,7 @@ def clone if @new.save flash[:success] = Spree.t('notice_messages.product_cloned') else - flash[:success] = Spree.t('notice_messages.product_not_cloned') + flash[:error] = Spree.t('notice_messages.product_not_cloned') end redirect_to edit_admin_product_url(@new) diff --git a/backend/app/controllers/spree/admin/properties_controller.rb b/backend/app/controllers/spree/admin/properties_controller.rb index 1b551717e83..fdf01614eb1 100644 --- a/backend/app/controllers/spree/admin/properties_controller.rb +++ b/backend/app/controllers/spree/admin/properties_controller.rb @@ -1,11 +1,24 @@ module Spree module Admin class PropertiesController < ResourceController + def index + respond_with(@collection) + end + + private + + def collection + return @collection if @collection.present? + # params[:q] can be blank upon pagination + params[:q] = {} if params[:q].blank? + + @collection = super + @search = @collection.ransack(params[:q]) + @collection = @search.result. + page(params[:page]). + per(Spree::Config[:properties_per_page]) - # Looks like this action is unused - def filtered - @properties = Property.where('lower(name) LIKE ?', "%#{params[:q].mb_chars.downcase}%").order(:name) - render :template => "spree/admin/properties/filtered", :layout => false + @collection end end end diff --git a/backend/app/helpers/spree/admin/adjustments_helper.rb b/backend/app/helpers/spree/admin/adjustments_helper.rb index b7978cf10ec..40ced24d7fa 100644 --- a/backend/app/helpers/spree/admin/adjustments_helper.rb +++ b/backend/app/helpers/spree/admin/adjustments_helper.rb @@ -4,7 +4,7 @@ module AdjustmentsHelper def adjustment_state(adjustment) state = adjustment.state.to_sym icon = { closed: 'lock', open: 'unlock' } - content_tag(:span, '', class: icon[state]) + content_tag(:span, '', class: "fa fa-#{ icon[state] }") end def display_adjustable(adjustable) diff --git a/backend/app/views/spree/admin/log_entries/_credit_card.html.erb b/backend/app/views/spree/admin/log_entries/_credit_card.html.erb deleted file mode 100644 index 41430a730ad..00000000000 --- a/backend/app/views/spree/admin/log_entries/_credit_card.html.erb +++ /dev/null @@ -1,4 +0,0 @@ -