From d1019fcc5ed6d4f7cb67524e5899f230dd60a259 Mon Sep 17 00:00:00 2001 From: luisramos0 Date: Tue, 12 Jun 2018 15:40:56 +0100 Subject: [PATCH 1/2] changed the country and state selectors to angular on enterprises admin (new and edit screens) so that states are dynamically updated when country is changed --- .../controllers/country_controller.js.coffee | 25 +++++++++++++++++++ .../api/admin/enterprise_serializer.rb | 1 + .../admin/enterprises/_form_data.html.haml | 1 + .../admin/enterprises/_new_form.html.haml | 20 ++++++++------- .../admin/enterprises/form/_address.html.haml | 9 ++++--- app/views/admin/enterprises/new.html.haml | 4 +++ spec/features/admin/enterprises_spec.rb | 4 ++- 7 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 app/assets/javascripts/admin/enterprises/controllers/country_controller.js.coffee diff --git a/app/assets/javascripts/admin/enterprises/controllers/country_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/country_controller.js.coffee new file mode 100644 index 0000000000..0f11642afb --- /dev/null +++ b/app/assets/javascripts/admin/enterprises/controllers/country_controller.js.coffee @@ -0,0 +1,25 @@ +angular.module("admin.enterprises").controller 'countryCtrl', ($scope, availableCountries) -> + + $scope.countries = availableCountries + + $scope.countriesById = $scope.countries.reduce (obj, country) -> + obj[country.id] = country + obj + , {} + + $scope.countryOnChange = (stateSelectElemId) -> + $scope.clearState() unless $scope.addressStateMatchesCountry() + $scope.refreshStateSelector(stateSelectElemId) + + $scope.clearState = -> + $scope.enterprise_address_attributes_state = {} + + $scope.addressStateMatchesCountry = -> + $scope.countriesById[$scope.enterprise_address_attributes_country.id].states.some (state) -> state.id == $scope.enterprise_address_attributes_state?.id + + $scope.refreshStateSelector = (stateSelectElemId) -> + # workaround select2 (using jQuery and setTimeout) to force a refresh of the selected value + setTimeout -> + selectedState = jQuery('#' + stateSelectElemId) + jQuery('#' + stateSelectElemId).select2("val", selectedState) + , 500 \ No newline at end of file diff --git a/app/serializers/api/admin/enterprise_serializer.rb b/app/serializers/api/admin/enterprise_serializer.rb index 2429ce21a9..7597011fde 100644 --- a/app/serializers/api/admin/enterprise_serializer.rb +++ b/app/serializers/api/admin/enterprise_serializer.rb @@ -5,6 +5,7 @@ class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer attributes :preferred_product_selection_from_inventory_only attributes :owner, :contact, :users, :tag_groups, :default_tag_group attributes :require_login, :allow_guest_orders, :allow_order_changes + attributes :address has_one :owner, serializer: Api::Admin::UserSerializer has_many :users, serializer: Api::Admin::UserSerializer diff --git a/app/views/admin/enterprises/_form_data.html.haml b/app/views/admin/enterprises/_form_data.html.haml index ee3d17d4aa..14f83b79bf 100644 --- a/app/views/admin/enterprises/_form_data.html.haml +++ b/app/views/admin/enterprises/_form_data.html.haml @@ -3,3 +3,4 @@ = admin_inject_payment_methods = admin_inject_shipping_methods = admin_inject_enterprise_permissions += admin_inject_available_countries(module: 'admin.enterprises') diff --git a/app/views/admin/enterprises/_new_form.html.haml b/app/views/admin/enterprises/_new_form.html.haml index 9d25fbff7a..353b89a126 100644 --- a/app/views/admin/enterprises/_new_form.html.haml +++ b/app/views/admin/enterprises/_new_form.html.haml @@ -87,15 +87,17 @@ = af.text_field :city, { placeholder: t(:city_placeholder)} .five.columns.omega = af.text_field :zipcode, { placeholder: t(:postcode_placeholder)} - .row - .three.columns.alpha - = af.label :state_id, t(:state) - \/ - = af.label :country_id, t(:country) - .four.columns - = af.collection_select :state_id, af.object.country.states, :id, :name, {}, :class => "select2 fullwidth" - .five.columns.omega - = af.collection_select :country_id, available_countries, :id, :name, {}, :class => "select2 fullwidth" + %div{ "ng-controller" => "countryCtrl" } + .row + .three.columns.alpha + = af.label :state_id, t(:state) + \/ + = af.label :country_id, t(:country) + .four.columns + = af.collection_select :state_id, {}, :id, :name, {}, :class => "select2 fullwidth", "ng-options" => "s as s.name for s in countriesById[enterprise_address_attributes_country.id].states track by s.id", "ng-model" => "enterprise_address_attributes_state" + .five.columns.omega + = af.collection_select :country_id, {}, :id, :name, {}, :class => "select2 fullwidth", "ng-options" => "c as c.name for c in countries track by c.id", "ng-model" => "enterprise_address_attributes_country", "ng-init" => "enterprise_address_attributes_country = { id: \"#{Spree::Config[:default_country_id]}\" }", "ng-change" => "countryOnChange('s2id_enterprise_address_attributes_state_id')" + .row .twelve.columns.alpha   diff --git a/app/views/admin/enterprises/form/_address.html.haml b/app/views/admin/enterprises/form/_address.html.haml index a1485d485f..2f30ca3599 100644 --- a/app/views/admin/enterprises/form/_address.html.haml +++ b/app/views/admin/enterprises/form/_address.html.haml @@ -31,7 +31,8 @@ \/ = af.label :country_id, t(:country) %span.required * - .four.columns - = af.collection_select :state_id, af.object.country.states, :id, :name, {}, :class => "select2 fullwidth" - .four.columns.omega - = af.collection_select :country_id, available_countries, :id, :name, {}, :class => "select2 fullwidth" + %div{ "ng-controller" => "countryCtrl" } + .four.columns + = af.collection_select :state_id, {}, :id, :name, {}, :class => "select2 fullwidth", "ng-init" => "enterprise_address_attributes_state.id = Enterprise.address.address.state_id", "ng-options" => "s as s.name for s in countriesById[enterprise_address_attributes_country.id || Enterprise.address.address.country_id].states track by s.id", "ng-model" => "enterprise_address_attributes_state" + .four.columns.omega + = af.collection_select :country_id, {}, :id, :name, {}, :class => "select2 fullwidth", "ng-init" => "enterprise_address_attributes_country.id = Enterprise.address.address.country_id", "ng-options" => "c as c.name for c in countries track by c.id", "ng-model" => "enterprise_address_attributes_country", "ng-change" => "countryOnChange('s2id_enterprise_address_attributes_state_id')" \ No newline at end of file diff --git a/app/views/admin/enterprises/new.html.haml b/app/views/admin/enterprises/new.html.haml index 4676d117fb..53a148fc74 100644 --- a/app/views/admin/enterprises/new.html.haml +++ b/app/views/admin/enterprises/new.html.haml @@ -6,6 +6,10 @@ - content_for :page_actions do %li= button_link_to t('.back_link'), main_app.admin_enterprises_path, icon: 'icon-arrow-left' +- content_for :app_wrapper_attrs do + = "ng-app='admin.enterprises'" + += admin_inject_available_countries(module: 'admin.enterprises') -# Form diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb index 6ed07f5bd3..1a35aebffe 100644 --- a/spec/features/admin/enterprises_spec.rb +++ b/spec/features/admin/enterprises_spec.rb @@ -53,7 +53,7 @@ feature %q{ fill_in 'enterprise_address_attributes_address1', :with => '35 Ballantyne St' fill_in 'enterprise_address_attributes_city', :with => 'Thornbury' fill_in 'enterprise_address_attributes_zipcode', :with => '3072' - select2_search 'Australia', :from => 'Country' + # default country (Australia in this test) should be selected by default select2_search 'Victoria', :from => 'State' click_button 'Create' @@ -342,6 +342,8 @@ feature %q{ fill_in 'enterprise_address_attributes_address1', with: 'z' fill_in 'enterprise_address_attributes_city', with: 'z' fill_in 'enterprise_address_attributes_zipcode', with: 'z' + select2_select 'Australia', from: 'enterprise_address_attributes_country_id' + select2_select 'Victoria', from: 'enterprise_address_attributes_state_id' end scenario "without violating rules" do From dabef16606c3d7a268115a0137549af27342be07 Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Thu, 14 Jun 2018 12:35:03 +1000 Subject: [PATCH 2/2] Use ofn-select2 directive for country and state selectors on enterprise forms --- .../controllers/country_controller.js.coffee | 17 +++++------------ .../new_enterprise_controller.js.coffee | 5 +++++ .../api/admin/enterprise_serializer.rb | 2 +- app/views/admin/enterprises/_new_form.html.haml | 4 ++-- .../admin/enterprises/form/_address.html.haml | 4 ++-- app/views/admin/enterprises/new.html.haml | 3 ++- 6 files changed, 17 insertions(+), 18 deletions(-) create mode 100644 app/assets/javascripts/admin/enterprises/controllers/new_enterprise_controller.js.coffee diff --git a/app/assets/javascripts/admin/enterprises/controllers/country_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/country_controller.js.coffee index 0f11642afb..085a992a36 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/country_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/country_controller.js.coffee @@ -1,5 +1,5 @@ +# 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) -> @@ -7,19 +7,12 @@ angular.module("admin.enterprises").controller 'countryCtrl', ($scope, available obj , {} - $scope.countryOnChange = (stateSelectElemId) -> + $scope.$watch 'Enterprise.address.country_id', (newID, oldID) -> $scope.clearState() unless $scope.addressStateMatchesCountry() - $scope.refreshStateSelector(stateSelectElemId) $scope.clearState = -> - $scope.enterprise_address_attributes_state = {} + $scope.Enterprise.address.state_id = null $scope.addressStateMatchesCountry = -> - $scope.countriesById[$scope.enterprise_address_attributes_country.id].states.some (state) -> state.id == $scope.enterprise_address_attributes_state?.id - - $scope.refreshStateSelector = (stateSelectElemId) -> - # workaround select2 (using jQuery and setTimeout) to force a refresh of the selected value - setTimeout -> - selectedState = jQuery('#' + stateSelectElemId) - jQuery('#' + stateSelectElemId).select2("val", selectedState) - , 500 \ No newline at end of file + $scope.countriesById[$scope.Enterprise.address.country_id].states.some (state) -> + state.id == $scope.Enterprise.address.state_id diff --git a/app/assets/javascripts/admin/enterprises/controllers/new_enterprise_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/new_enterprise_controller.js.coffee new file mode 100644 index 0000000000..06677f5184 --- /dev/null +++ b/app/assets/javascripts/admin/enterprises/controllers/new_enterprise_controller.js.coffee @@ -0,0 +1,5 @@ +angular.module("admin.enterprises").controller 'NewEnterpriseController', ($scope, defaultCountryID) -> + $scope.Enterprise = + address: + country_id: defaultCountryID + state_id: null diff --git a/app/serializers/api/admin/enterprise_serializer.rb b/app/serializers/api/admin/enterprise_serializer.rb index 7597011fde..e29954992f 100644 --- a/app/serializers/api/admin/enterprise_serializer.rb +++ b/app/serializers/api/admin/enterprise_serializer.rb @@ -5,10 +5,10 @@ class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer attributes :preferred_product_selection_from_inventory_only attributes :owner, :contact, :users, :tag_groups, :default_tag_group attributes :require_login, :allow_guest_orders, :allow_order_changes - attributes :address has_one :owner, serializer: Api::Admin::UserSerializer has_many :users, serializer: Api::Admin::UserSerializer + has_one :address, serializer: Api::AddressSerializer def tag_groups object.tag_rules.prioritised.reject(&:is_default).each_with_object([]) do |tag_rule, tag_groups| diff --git a/app/views/admin/enterprises/_new_form.html.haml b/app/views/admin/enterprises/_new_form.html.haml index 353b89a126..84102ce63b 100644 --- a/app/views/admin/enterprises/_new_form.html.haml +++ b/app/views/admin/enterprises/_new_form.html.haml @@ -94,9 +94,9 @@ \/ = af.label :country_id, t(:country) .four.columns - = af.collection_select :state_id, {}, :id, :name, {}, :class => "select2 fullwidth", "ng-options" => "s as s.name for s in countriesById[enterprise_address_attributes_country.id].states track by s.id", "ng-model" => "enterprise_address_attributes_state" + %input.ofn-select2.fullwidth#enterprise_address_attributes_state_id{ name: 'enterprise[address_attributes][state_id]', type: 'number', data: 'countriesById[Enterprise.address.country_id].states', placeholder: t('admin.choose'), ng: { model: 'Enterprise.address.state_id' } } .five.columns.omega - = af.collection_select :country_id, {}, :id, :name, {}, :class => "select2 fullwidth", "ng-options" => "c as c.name for c in countries track by c.id", "ng-model" => "enterprise_address_attributes_country", "ng-init" => "enterprise_address_attributes_country = { id: \"#{Spree::Config[:default_country_id]}\" }", "ng-change" => "countryOnChange('s2id_enterprise_address_attributes_state_id')" + %input.ofn-select2.fullwidth#enterprise_address_attributes_country_id{ name: 'enterprise[address_attributes][country_id]', type: 'number', data: 'countries', placeholder: t('admin.choose'), ng: { model: 'Enterprise.address.country_id' } } .row .twelve.columns.alpha diff --git a/app/views/admin/enterprises/form/_address.html.haml b/app/views/admin/enterprises/form/_address.html.haml index 2f30ca3599..cb278df5e0 100644 --- a/app/views/admin/enterprises/form/_address.html.haml +++ b/app/views/admin/enterprises/form/_address.html.haml @@ -33,6 +33,6 @@ %span.required * %div{ "ng-controller" => "countryCtrl" } .four.columns - = af.collection_select :state_id, {}, :id, :name, {}, :class => "select2 fullwidth", "ng-init" => "enterprise_address_attributes_state.id = Enterprise.address.address.state_id", "ng-options" => "s as s.name for s in countriesById[enterprise_address_attributes_country.id || Enterprise.address.address.country_id].states track by s.id", "ng-model" => "enterprise_address_attributes_state" + %input.ofn-select2.fullwidth#enterprise_address_attributes_state_id{ name: 'enterprise[address_attributes][state_id]', type: 'number', data: 'countriesById[Enterprise.address.country_id].states', placeholder: t('admin.choose'), ng: { model: 'Enterprise.address.state_id' } } .four.columns.omega - = af.collection_select :country_id, {}, :id, :name, {}, :class => "select2 fullwidth", "ng-init" => "enterprise_address_attributes_country.id = Enterprise.address.address.country_id", "ng-options" => "c as c.name for c in countries track by c.id", "ng-model" => "enterprise_address_attributes_country", "ng-change" => "countryOnChange('s2id_enterprise_address_attributes_state_id')" \ No newline at end of file + %input.ofn-select2.fullwidth#enterprise_address_attributes_country_id{ name: 'enterprise[address_attributes][country_id]', type: 'number', data: 'countries', placeholder: t('admin.choose'), ng: { model: 'Enterprise.address.country_id' } } diff --git a/app/views/admin/enterprises/new.html.haml b/app/views/admin/enterprises/new.html.haml index 53a148fc74..dd830054f5 100644 --- a/app/views/admin/enterprises/new.html.haml +++ b/app/views/admin/enterprises/new.html.haml @@ -10,10 +10,11 @@ = "ng-app='admin.enterprises'" = admin_inject_available_countries(module: 'admin.enterprises') += admin_inject_json "admin.enterprises", "defaultCountryID", Spree::Config[:default_country_id] -# Form = form_for [main_app, :admin, @enterprise], html: { "nav-check" => '', "nav-callback" => '' } do |f| .row - .twelve.columns.fullwidth_inputs{ ng: { app: "admin.users" } } + .twelve.columns.fullwidth_inputs{ ng: { controller: "NewEnterpriseController" } } = render 'new_form', f: f