From a66582a8fbc088f7aeaf6a8b58937f18e668bb98 Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Thu, 4 Feb 2016 10:42:26 +1100 Subject: [PATCH] WIP: Using directive for EnterpriseFee index select elements, to properly bind data to the model --- .../enterprise_fees_controller.js.coffee | 13 +++++-------- ...calculator_preferences_match_type.js.coffee | 12 ++++-------- .../admin/enterprise_fees/enterprise_fees.js | 2 +- .../directives/ofn-select.js.coffee | 13 +++++++++++++ app/helpers/admin/injection_helper.rb | 4 ++-- app/helpers/angular_form_builder.rb | 12 ++++++++---- app/helpers/angular_form_helper.rb | 3 +-- app/helpers/enterprise_fees_helper.rb | 8 ++++++++ .../api/admin/calculator_serializer.rb | 11 +++++++++++ .../admin/enterprise_fees/_data.html.haml | 3 +++ .../admin/enterprise_fees/index.html.haml | 18 ++++++++++++++---- spec/features/admin/enterprise_fees_spec.rb | 12 ++++++------ 12 files changed, 76 insertions(+), 35 deletions(-) create mode 100644 app/assets/javascripts/admin/index_utils/directives/ofn-select.js.coffee create mode 100644 app/serializers/api/admin/calculator_serializer.rb create mode 100644 app/views/admin/enterprise_fees/_data.html.haml diff --git a/app/assets/javascripts/admin/enterprise_fees/controllers/enterprise_fees_controller.js.coffee b/app/assets/javascripts/admin/enterprise_fees/controllers/enterprise_fees_controller.js.coffee index 3dd860fb56..fee2140dcc 100644 --- a/app/assets/javascripts/admin/enterprise_fees/controllers/enterprise_fees_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprise_fees/controllers/enterprise_fees_controller.js.coffee @@ -1,4 +1,8 @@ -angular.module('admin.enterpriseFees').controller 'enterpriseFeesCtrl', ($scope, $http, $window) -> +angular.module('admin.enterpriseFees').controller 'enterpriseFeesCtrl', ($scope, $http, $window, enterprises, tax_categories, calculators) -> + $scope.enterprises = enterprises + $scope.tax_categories = tax_categories + $scope.calculators = calculators + $scope.enterpriseFeesUrl = -> url = '/admin/enterprise_fees.json?include_calculators=1' match = $window.location.search.match(/enterprise_id=(\d+)/) @@ -8,10 +12,3 @@ angular.module('admin.enterpriseFees').controller 'enterpriseFeesCtrl', ($scope, $http.get($scope.enterpriseFeesUrl()).success (data) -> $scope.enterprise_fees = data - # TODO: Angular 1.1.0 will have a means to reset a form to its pristine state, which - # would avoid the need to save off original calculator types for comparison. - for i of $scope.enterprise_fees - $scope.enterprise_fees[i].orig_calculator_type = $scope.enterprise_fees[i].calculator_type - return - - return diff --git a/app/assets/javascripts/admin/enterprise_fees/directives/ensure_calculator_preferences_match_type.js.coffee b/app/assets/javascripts/admin/enterprise_fees/directives/ensure_calculator_preferences_match_type.js.coffee index 5b128b4d34..4376ce59ef 100644 --- a/app/assets/javascripts/admin/enterprise_fees/directives/ensure_calculator_preferences_match_type.js.coffee +++ b/app/assets/javascripts/admin/enterprise_fees/directives/ensure_calculator_preferences_match_type.js.coffee @@ -2,16 +2,12 @@ angular.module("admin.enterpriseFees").directive 'spreeEnsureCalculatorPreferenc # Hide calculator preference fields when calculator type changed # Fixes 'Enterprise fee is not found' error when changing calculator type # See spree/core/app/assets/javascripts/admin/calculator.js - # Note: For some reason, DOM --> model bindings aren't working here, so - # we use element.val() instead of querying the model itself. (scope, element, attrs) -> - scope.$watch ((scope) -> - #return scope.enterprise_fee.calculator_type; - element.val() - ), (value) -> + orig_calculator_type = scope.enterprise_fee.calculator_type + + scope.$watch "enterprise_fee.calculator_type", (value) -> settings = element.parent().parent().find('div.calculator-settings') - # scope.enterprise_fee.calculator_type == scope.enterprise_fee.orig_calculator_type - if element.val() == scope.enterprise_fee.orig_calculator_type + if value == orig_calculator_type settings.show() settings.find('input').prop 'disabled', false else diff --git a/app/assets/javascripts/admin/enterprise_fees/enterprise_fees.js b/app/assets/javascripts/admin/enterprise_fees/enterprise_fees.js index a256834946..9c4e2ed4a5 100644 --- a/app/assets/javascripts/admin/enterprise_fees/enterprise_fees.js +++ b/app/assets/javascripts/admin/enterprise_fees/enterprise_fees.js @@ -1 +1 @@ -angular.module("admin.enterpriseFees", []) +angular.module("admin.enterpriseFees", ['admin.indexUtils']) diff --git a/app/assets/javascripts/admin/index_utils/directives/ofn-select.js.coffee b/app/assets/javascripts/admin/index_utils/directives/ofn-select.js.coffee new file mode 100644 index 0000000000..9a653d24f8 --- /dev/null +++ b/app/assets/javascripts/admin/index_utils/directives/ofn-select.js.coffee @@ -0,0 +1,13 @@ +# Mainly useful for adding a blank option that works with AngularJS +# Angular doesn't seem to understand the blank option generated by rails +# using the include_blank flag on select helper. +angular.module("admin.indexUtils").directive "ofnSelect", -> + restrict: 'E' + scope: + data: "=" + replace: true + template: (element, attrs) -> + valueAttr = attrs.valueAttr || 'id' + textAttr = attrs.textAttr || 'name' + blank = if attrs.includeBlank? then "" else "" + return "" diff --git a/app/helpers/admin/injection_helper.rb b/app/helpers/admin/injection_helper.rb index 343e15ef29..ba65e37860 100644 --- a/app/helpers/admin/injection_helper.rb +++ b/app/helpers/admin/injection_helper.rb @@ -56,8 +56,8 @@ module Admin admin_inject_json_ams_array "ofn.admin", "products", @products, Api::Admin::ProductSerializer end - def admin_inject_tax_categories - admin_inject_json_ams_array "ofn.admin", "tax_categories", @tax_categories, Api::Admin::TaxCategorySerializer + def admin_inject_tax_categories(opts={module: 'ofn.admin'}) + admin_inject_json_ams_array opts[:module], "tax_categories", @tax_categories, Api::Admin::TaxCategorySerializer end def admin_inject_taxons diff --git a/app/helpers/angular_form_builder.rb b/app/helpers/angular_form_builder.rb index 56fcab79fa..4dff1f92e1 100644 --- a/app/helpers/angular_form_builder.rb +++ b/app/helpers/angular_form_builder.rb @@ -11,26 +11,26 @@ class AngularFormBuilder < ActionView::Helpers::FormBuilder # @fields_for_record_name --> :collection # @object.send(@fields_for_record_name).first.class.to_s.underscore --> enterprise_fee - value = "{{ #{@object.send(@fields_for_record_name).first.class.to_s.underscore}.#{method} }}" + value = "{{ #{angular_model(method)} }}" options.reverse_merge!({'id' => angular_id(method)}) @template.text_field_tag angular_name(method), value, options end def ng_hidden_field(method, options = {}) - value = "{{ #{@object.send(@fields_for_record_name).first.class.to_s.underscore}.#{method} }}" + value = "{{ #{angular_model(method)} }}" @template.hidden_field_tag angular_name(method), value, :id => angular_id(method) end def ng_select(method, choices, angular_field, options = {}) - options.reverse_merge!({'id' => angular_id(method)}) + options.reverse_merge!({'id' => angular_id(method), 'ng-model' => "#{angular_model(method)}"}) @template.select_tag angular_name(method), @template.ng_options_for_select(choices, angular_field), options end def ng_collection_select(method, collection, value_method, text_method, angular_field, options = {}) - options.reverse_merge!({'id' => angular_id(method)}) + options.reverse_merge!({'id' => angular_id(method), 'ng-model' => "#{angular_model(method)}"}) @template.select_tag angular_name(method), @template.ng_options_from_collection_for_select(collection, value_method, text_method, angular_field), options end @@ -43,4 +43,8 @@ class AngularFormBuilder < ActionView::Helpers::FormBuilder def angular_id(method) "#{@object_name}_#{@fields_for_record_name}_attributes_{{ $index }}_#{method}" end + + def angular_model(method) + "#{@object.send(@fields_for_record_name).first.class.to_s.underscore}.#{method}" + end end diff --git a/app/helpers/angular_form_helper.rb b/app/helpers/angular_form_helper.rb index a7fd6e0e28..0687f62188 100644 --- a/app/helpers/angular_form_helper.rb +++ b/app/helpers/angular_form_helper.rb @@ -5,8 +5,7 @@ module AngularFormHelper container.map do |element| html_attributes = option_html_attributes(element) text, value = option_text_and_value(element).map { |item| item.to_s } - selected_attribute = %Q( ng-selected="#{angular_field} == '#{value}'") if angular_field - %() + %() end.join("\n").html_safe end diff --git a/app/helpers/enterprise_fees_helper.rb b/app/helpers/enterprise_fees_helper.rb index b7ec2b9018..82d24ce1a6 100644 --- a/app/helpers/enterprise_fees_helper.rb +++ b/app/helpers/enterprise_fees_helper.rb @@ -1,4 +1,12 @@ module EnterpriseFeesHelper + def angular_name(method) + "enterprise_fee_set[collection_attributes][{{ $index }}][#{method}]" + end + + def angular_id(method) + "enterprise_fee_set_collection_attributes_{{ $index }}_#{method}" + end + def enterprise_fee_type_options EnterpriseFee::FEE_TYPES.map { |f| [f.capitalize, f] } end diff --git a/app/serializers/api/admin/calculator_serializer.rb b/app/serializers/api/admin/calculator_serializer.rb new file mode 100644 index 0000000000..a6287edbb1 --- /dev/null +++ b/app/serializers/api/admin/calculator_serializer.rb @@ -0,0 +1,11 @@ +class Api::Admin::CalculatorSerializer < ActiveModel::Serializer + attributes :name, :description + + def name + object.name + end + + def description + object.description + end +end diff --git a/app/views/admin/enterprise_fees/_data.html.haml b/app/views/admin/enterprise_fees/_data.html.haml new file mode 100644 index 0000000000..0b12530bff --- /dev/null +++ b/app/views/admin/enterprise_fees/_data.html.haml @@ -0,0 +1,3 @@ += admin_inject_json_ams_array "admin.enterpriseFees", "enterprises", @enterprises, Api::Admin::IdNameSerializer += admin_inject_tax_categories(module: "admin.enterpriseFees") += admin_inject_json_ams_array "admin.enterpriseFees", "calculators", @calculators, Api::Admin::CalculatorSerializer diff --git a/app/views/admin/enterprise_fees/index.html.haml b/app/views/admin/enterprise_fees/index.html.haml index 60d818ed34..e9ab4d8650 100644 --- a/app/views/admin/enterprise_fees/index.html.haml +++ b/app/views/admin/enterprise_fees/index.html.haml @@ -3,6 +3,7 @@ = ng_form_for @enterprise_fee_set, :url => main_app.bulk_update_admin_enterprise_fees_path, :html => {'ng-app' => 'admin.enterpriseFees', 'ng-controller' => 'enterpriseFeesCtrl'} do |enterprise_fee_set_form| = hidden_field_tag 'enterprise_id', @enterprise.id if @enterprise + = render "admin/enterprise_fees/data" = render :partial => 'spree/shared/error_messages', :locals => { :target => @enterprise_fee_set } %input.search{'ng-model' => 'query', 'placeholder' => 'Search'} @@ -19,14 +20,23 @@ %th.actions %tbody = enterprise_fee_set_form.ng_fields_for :collection do |f| - %tr{'ng-repeat' => 'enterprise_fee in enterprise_fees | filter:query'} + %tr{'ng-repeat' => 'enterprise_fee in enterprise_fees | filter:query' } %td = f.ng_hidden_field :id - = f.ng_collection_select :enterprise_id, @enterprises, :id, :name, 'enterprise_fee.enterprise_id', include_blank: true + %ofn-select{ :id => angular_id(:enterprise_id), data: 'enterprises', include_blank: true, ng: { model: 'enterprise_fee.enterprise_id' } } + %input{ type: "hidden", name: angular_name(:enterprise_id), ng: { value: "enterprise_fee.enterprise_id" } } + -# = f.ng_collection_select :enterprise_id, @enterprises, :id, :name, 'enterprise_fee.enterprise_id', include_blank: false %td= f.ng_select :fee_type, enterprise_fee_type_options, 'enterprise_fee.fee_type' %td= f.ng_text_field :name, { placeholder: 'e.g. packing fee' } - %td= f.ng_collection_select :tax_category_id, @tax_categories, :id, :name, 'enterprise_fee.tax_category_id', include_blank: true - %td= f.ng_collection_select :calculator_type, @calculators, :name, :description, 'enterprise_fee.calculator_type', {'class' => 'calculator_type', 'ng-model' => 'calculatorType', 'spree-ensure-calculator-preferences-match-type' => "1"} + %td + = f.ng_hidden_field :inherits_tax_category + %ofn-select{ :id => angular_id(:tax_category_id), data: 'tax_categories', include_blank: true, ng: { model: 'enterprise_fee.tax_category_id' } } + %input{ type: "hidden", name: angular_name(:tax_category_id), ng: { value: "enterprise_fee.tax_category_id" } } + -# = f.ng_collection_select :tax_category_id, @tax_categories, :id, :name, 'enterprise_fee.tax_category_id', include_blank: " " + %td + %ofn-select.calculator_type{ :id => angular_id(:calculator_type), ng: { model: 'enterprise_fee.calculator_type' }, value_attr: 'name', text_attr: 'description', data: 'calculators', 'spree-ensure-calculator-preferences-match-type' => true } + %input{ type: "hidden", name: angular_name(:calculator_type), ng: { value: "enterprise_fee.calculator_type" } } + -# = f.ng_collection_select :calculator_type, @calculators, :name, :description, 'enterprise_fee.calculator_type', {'class' => 'calculator_type', 'spree-ensure-calculator-preferences-match-type' => "1"} %td{'ng-bind-html-unsafe-compiled' => 'enterprise_fee.calculator_settings'} %td.actions{'spree-delete-resource' => "1"} diff --git a/spec/features/admin/enterprise_fees_spec.rb b/spec/features/admin/enterprise_fees_spec.rb index d462a3d809..c90691b3ac 100644 --- a/spec/features/admin/enterprise_fees_spec.rb +++ b/spec/features/admin/enterprise_fees_spec.rb @@ -17,11 +17,11 @@ feature %q{ click_link 'Configuration' click_link 'Enterprise Fees' - page.should have_selector "#enterprise_fee_set_collection_attributes_0_enterprise_id" - page.should have_selector "option[selected]", text: 'Packing' + page.should have_select "enterprise_fee_set_collection_attributes_0_enterprise_id" + page.should have_select "enterprise_fee_set_collection_attributes_0_fee_type", selected: 'Packing' page.should have_selector "input[value='$0.50 / kg']" - page.should have_selector "option[selected]", text: 'GST' - page.should have_selector "option[selected]", text: 'Flat Rate (per item)' + page.should have_select "enterprise_fee_set_collection_attributes_0_tax_category_id", selected: 'GST' + page.should have_select "enterprise_fee_set_collection_attributes_0_calculator_type", selected: 'Flat Rate (per item)' page.should have_selector "input[value='#{amount}']" end @@ -73,8 +73,8 @@ feature %q{ click_button 'Update' # Then I should see the updated fields for my fee - page.should have_selector "option[selected]", text: 'Foo' - page.should have_selector "option[selected]", text: 'Admin' + page.should have_select "enterprise_fee_set_collection_attributes_0_enterprise_id", selected: 'Foo' + page.should have_select "enterprise_fee_set_collection_attributes_0_fee_type", selected: 'Admin' page.should have_selector "input[value='Greetings!']" page.should have_select 'enterprise_fee_set_collection_attributes_0_tax_category_id', selected: '' page.should have_selector "option[selected]", text: 'Flat Percent'