mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge pull request #5976 from luisramos0/address_form
Fix address state selector and "use billing address" checkbox in order customer details page
This commit is contained in:
@@ -1,27 +1,17 @@
|
||||
var update_state = function(region) {
|
||||
var country = $('span#' + region + 'country .select2').select2('val');
|
||||
|
||||
var state_select = $('span#' + region + 'state select.select2');
|
||||
var state_input = $('span#' + region + 'state input.state_name');
|
||||
|
||||
$.get(Spree.routes.states_search + "?country_id=" + country, function(data) {
|
||||
var states = data["states"]
|
||||
if (states.length > 0) {
|
||||
state_select.html('');
|
||||
var states_with_blank = [{name: '', id: ''}].concat(states);
|
||||
$.each(states_with_blank, function(pos,state) {
|
||||
var opt = $(document.createElement('option'))
|
||||
.attr('value', state.id)
|
||||
.html(state.name);
|
||||
state_select.append(opt);
|
||||
});
|
||||
state_select.prop("disabled", false).show();
|
||||
state_select.select2();
|
||||
state_input.hide().prop("disabled", true);
|
||||
|
||||
} else {
|
||||
state_input.prop("disabled", false).show();
|
||||
state_select.select2('destroy').hide();
|
||||
}
|
||||
$.get(Spree.routes.states_search + "?country_id=" + country, function(states) {
|
||||
state_select.html('');
|
||||
var states_with_blank = [{name: '', id: ''}].concat(states);
|
||||
$.each(states_with_blank, function(pos,state) {
|
||||
var opt = $(document.createElement('option'))
|
||||
.attr('value', state.id)
|
||||
.html(state.name);
|
||||
state_select.append(opt);
|
||||
});
|
||||
state_select.prop("disabled", false).show();
|
||||
state_select.select2();
|
||||
})
|
||||
};
|
||||
|
||||
17
app/assets/javascripts/admin/spree/orders/use_billing.js
Normal file
17
app/assets/javascripts/admin/spree/orders/use_billing.js
Normal file
@@ -0,0 +1,17 @@
|
||||
$(document).ready(function() {
|
||||
var order_use_billing_input = $('input#order_use_billing');
|
||||
|
||||
var order_use_billing = function () {
|
||||
if (!order_use_billing_input.is(':checked')) {
|
||||
$('#shipping').show();
|
||||
} else {
|
||||
$('#shipping').hide();
|
||||
}
|
||||
};
|
||||
|
||||
order_use_billing_input.click(function() {
|
||||
order_use_billing();
|
||||
});
|
||||
|
||||
order_use_billing();
|
||||
});
|
||||
44
app/controllers/api/states_controller.rb
Normal file
44
app/controllers/api/states_controller.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
class StatesController < Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check
|
||||
|
||||
def index
|
||||
render json: states, each_serializer: Api::StateSerializer, status: :ok
|
||||
end
|
||||
|
||||
def show
|
||||
@state = scope.find(params[:id])
|
||||
render json: @state, serializer: Api::StateSerializer, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def scope
|
||||
if params[:country_id]
|
||||
@country = Spree::Country.find(params[:country_id])
|
||||
@country.states
|
||||
else
|
||||
Spree::State.all
|
||||
end
|
||||
end
|
||||
|
||||
def states
|
||||
states = scope.ransack(params[:q]).result.
|
||||
includes(:country).order('name ASC')
|
||||
|
||||
if pagination?
|
||||
states = states.page(params[:page]).per(params[:per_page])
|
||||
end
|
||||
|
||||
states
|
||||
end
|
||||
|
||||
def pagination?
|
||||
params[:page] || params[:per_page]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,3 @@
|
||||
class Api::StateSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :abbr
|
||||
attributes :id, :name, :abbr, :country_id
|
||||
end
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
- if use_billing
|
||||
.field{style: "position: absolute;margin-top: -15px;right: 0;"}
|
||||
%span
|
||||
= check_box_tag 'order[use_billing]', '1', (!(@order.bill_address.empty? && @order.ship_address.empty?) && @order.bill_address.same_as?(@order.ship_address))
|
||||
= label_tag 'order[use_billing]', Spree.t(:use_billing_address)
|
||||
|
||||
- is_shipping_address = name == Spree.t(:shipping_address)
|
||||
- s_or_b = is_shipping_address ? 's' : 'b'
|
||||
|
||||
- display_style = (use_billing && (!(@order.bill_address.empty? && @order.ship_address.empty?) && @order.bill_address == @order.ship_address)) ? 'none' : 'block'
|
||||
|
||||
%div{id: "#{is_shipping_address ? 'shipping' : 'billing'}", style: "display: #{display_style}"}
|
||||
%div{class: "field"}
|
||||
= f.label :firstname, Spree.t(:first_name) + ':'
|
||||
= f.text_field :firstname, class: 'fullwidth'
|
||||
%div{class: "field"}
|
||||
= f.label :lastname, Spree.t(:last_name) + ':'
|
||||
= f.text_field :lastname, class: 'fullwidth'
|
||||
- if Spree::Config[:company]
|
||||
%div{class: "field"}
|
||||
= f.label :company, Spree.t(:company) + ':'
|
||||
= f.text_field :company, class: 'fullwidth'
|
||||
%div{class: "field"}
|
||||
= f.label :address1, Spree.t(:street_address) + ':'
|
||||
= f.text_field :address1, class: 'fullwidth'
|
||||
%div{class: "field"}
|
||||
= f.label :address2, Spree.t(:street_address_2) + ':'
|
||||
= f.text_field :address2, class: 'fullwidth'
|
||||
%div{class: "field"}
|
||||
= f.label :city, Spree.t(:city) + ':'
|
||||
= f.text_field :city, class: 'fullwidth'
|
||||
%div{class: "field"}
|
||||
= f.label :zipcode, Spree.t(:zip) + ':'
|
||||
= f.text_field :zipcode, class: 'fullwidth'
|
||||
%div{class: "field"}
|
||||
= f.label :country_id, Spree.t(:country) + ':'
|
||||
%span{id: "#{s_or_b}country"}
|
||||
= f.collection_select :country_id, available_countries, :id, :name, {}, {class: 'select2 fullwidth', onchange: "update_state('#{s_or_b}')"}
|
||||
%div{class: "field"}
|
||||
= f.label :state_id, Spree.t(:state) + ':'
|
||||
%span{id: "#{s_or_b}state"}
|
||||
= f.collection_select :state_id, f.object.country.states.sort, :id, :name, {include_blank: true}, {class: 'select2 fullwidth', disabled: f.object.country.states.empty?}
|
||||
%div{class: "field"}
|
||||
= f.label :phone, Spree.t(:phone) + ':'
|
||||
= f.phone_field :phone, class: 'fullwidth'
|
||||
@@ -11,13 +11,13 @@
|
||||
%fieldset.no-border-bottom
|
||||
%legend{:align => "center"}= Spree.t(:billing_address)
|
||||
= f.fields_for :bill_address do |ba_form|
|
||||
= render :partial => 'spree/admin/shared/address_form', :locals => { :f => ba_form, :name => Spree.t(:billing_address), :use_billing => false }
|
||||
= render :partial => 'address_form', :locals => { :f => ba_form, :name => Spree.t(:billing_address), :use_billing => false }
|
||||
|
||||
.omega.six.columns{"data-hook" => "ship_address_wrapper"}
|
||||
%fieldset.no-border-bottom
|
||||
%legend{:align => "center"}= Spree.t(:shipping_address)
|
||||
= f.fields_for :ship_address do |sa_form|
|
||||
= render :partial => 'spree/admin/shared/address_form', :locals => { :f => sa_form, :name => Spree.t(:shipping_address), :use_billing => true }
|
||||
= render :partial => 'address_form', :locals => { :f => sa_form, :name => Spree.t(:shipping_address), :use_billing => true }
|
||||
|
||||
.clear
|
||||
|
||||
@@ -26,3 +26,4 @@
|
||||
|
||||
- content_for :head do
|
||||
= javascript_include_tag 'admin/spree/orders/address_states.js'
|
||||
= javascript_include_tag 'admin/spree/orders/use_billing.js'
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
<% if use_billing %>
|
||||
<div class="field" style="position: absolute;margin-top: -15px;right: 0;">
|
||||
<span data-hook="use_billing">
|
||||
<%= check_box_tag 'order[use_billing]', '1', (!(@order.bill_address.empty? && @order.ship_address.empty?) && @order.bill_address.same_as?(@order.ship_address)) %>
|
||||
<%= label_tag 'order[use_billing]', Spree.t(:use_billing_address) %>
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% is_shipping_address = name == Spree.t(:shipping_address) %>
|
||||
<% shipping_or_billing = is_shipping_address ? 'shipping' : 'billing' %>
|
||||
<% s_or_b = is_shipping_address ? 's' : 'b' %>
|
||||
|
||||
<div id="<%= is_shipping_address ? 'shipping' : 'billing' %>" style="display: <%= (use_billing && (!(@order.bill_address.empty? && @order.ship_address.empty?) && @order.bill_address.eql?(@order.ship_address))) ? 'none' : 'block' %>" data-hook="address_fields">
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :firstname, Spree.t(:first_name) + ':' %>
|
||||
<%= f.text_field :firstname, :class => 'fullwidth' %>
|
||||
</div>
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :lastname, Spree.t(:last_name) + ':' %>
|
||||
<%= f.text_field :lastname, :class => 'fullwidth' %>
|
||||
</div>
|
||||
<% if Spree::Config[:company] %>
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :company, Spree.t(:company) + ':' %>
|
||||
<%= f.text_field :company, :class => 'fullwidth' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :address1, Spree.t(:street_address) + ':' %>
|
||||
<%= f.text_field :address1, :class => 'fullwidth' %>
|
||||
</div>
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :address2, Spree.t(:street_address_2) + ':' %>
|
||||
<%= f.text_field :address2, :class => 'fullwidth' %>
|
||||
</div>
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :city, Spree.t(:city) + ':' %>
|
||||
<%= f.text_field :city, :class => 'fullwidth' %>
|
||||
</div>
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :zipcode, Spree.t(:zip) + ':' %>
|
||||
<%= f.text_field :zipcode, :class => 'fullwidth' %>
|
||||
</div>
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :country_id, Spree.t(:country) + ':' %>
|
||||
<span id="<%= s_or_b %>country">
|
||||
<%= f.collection_select :country_id, available_countries, :id, :name, {}, {:class => 'select2 fullwidth'} %>
|
||||
</span>
|
||||
</div>
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :state_id, Spree.t(:state) + ':' %>
|
||||
<span id="<%= s_or_b %>state">
|
||||
<%= f.text_field :state_name,
|
||||
:style => "display: #{f.object.country.states.empty? ? 'block' : 'none' };",
|
||||
:disabled => !f.object.country.states.empty?, :class => 'fullwidth state_name' %>
|
||||
<%= f.collection_select :state_id, f.object.country.states.sort, :id, :name, {:include_blank => true}, {:class => 'select2 fullwidth', :style => "display: #{f.object.country.states.empty? ? 'none' : 'block' };", :disabled => f.object.country.states.empty?} %>
|
||||
</span>
|
||||
</div>
|
||||
<div class="field <%= "#{shipping_or_billing}-row" %>">
|
||||
<%= f.label :phone, Spree.t(:phone) + ':' %>
|
||||
<%= f.phone_field :phone, :class => 'fullwidth' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% content_for :head do %>
|
||||
<%= javascript_tag do -%>
|
||||
$(document).ready(function(){
|
||||
$('span#<%= s_or_b %>country .select2').on('change', function() { update_state('<%= s_or_b %>'); });
|
||||
});
|
||||
<% end -%>
|
||||
<% end %>
|
||||
@@ -2,6 +2,7 @@
|
||||
Spree.routes = <%== {
|
||||
:variants_search => spree.admin_search_variants_path(:format => 'json'),
|
||||
:taxons_search => main_app.api_taxons_path(:format => 'json'),
|
||||
:orders_api => main_app.api_orders_path
|
||||
:orders_api => main_app.api_orders_path,
|
||||
:states_search => main_app.api_states_path(:format => 'json')
|
||||
}.to_json %>;
|
||||
</script>
|
||||
|
||||
@@ -62,6 +62,8 @@ Openfoodnetwork::Application.routes.draw do
|
||||
|
||||
post '/product_images/:product_id', to: 'product_images#update_product_image'
|
||||
|
||||
resources :states, :only => [:index, :show]
|
||||
|
||||
resources :taxons, :only => [:index]
|
||||
|
||||
resources :taxonomies do
|
||||
|
||||
77
spec/controllers/api/states_controller_spec.rb
Normal file
77
spec/controllers/api/states_controller_spec.rb
Normal file
@@ -0,0 +1,77 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
module Api
|
||||
describe StatesController do
|
||||
render_views
|
||||
|
||||
let!(:state) { create(:state, name: "Victoria") }
|
||||
let(:attributes) { [:id, :name, :abbr, :country_id] }
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { current_user }
|
||||
end
|
||||
|
||||
it "gets all states" do
|
||||
api_get :index
|
||||
expect(json_response.first.symbolize_keys.keys).to include(*attributes)
|
||||
expect(json_response.map { |state| state[:name] }).to include(state.name)
|
||||
end
|
||||
|
||||
context "pagination" do
|
||||
before do
|
||||
expect(Spree::State).to receive(:all).and_return(@scope = double)
|
||||
allow(@scope).to receive_message_chain(:ransack, :result, :includes, :order).and_return(@scope)
|
||||
end
|
||||
|
||||
it "does not paginate states results when asked not to do so" do
|
||||
expect(@scope).not_to receive(:page)
|
||||
expect(@scope).not_to receive(:per)
|
||||
api_get :index
|
||||
end
|
||||
|
||||
it "paginates when page parameter is passed through" do
|
||||
expect(@scope).to receive(:page).with(1).and_return(@scope)
|
||||
expect(@scope).to receive(:per).with(nil)
|
||||
api_get :index, page: 1
|
||||
end
|
||||
|
||||
it "paginates when per_page parameter is passed through" do
|
||||
expect(@scope).to receive(:page).with(nil).and_return(@scope)
|
||||
expect(@scope).to receive(:per).with(25)
|
||||
api_get :index, per_page: 25
|
||||
end
|
||||
end
|
||||
|
||||
context "with two states" do
|
||||
before { create(:state, name: "New South Wales") }
|
||||
|
||||
it "gets all states for a country" do
|
||||
country = create(:country, states_required: true)
|
||||
state.country = country
|
||||
state.save
|
||||
|
||||
api_get :index, country_id: country.id
|
||||
expect(json_response.first.symbolize_keys.keys).to include(*attributes)
|
||||
expect(json_response.count).to eq 1
|
||||
end
|
||||
|
||||
it "can view all states" do
|
||||
api_get :index
|
||||
expect(json_response.first.symbolize_keys.keys).to include(*attributes)
|
||||
end
|
||||
|
||||
it 'can query the results through a paramter' do
|
||||
api_get :index, q: { name_cont: 'Vic' }
|
||||
expect(json_response.first['name']).to eq("Victoria")
|
||||
end
|
||||
end
|
||||
|
||||
it "can view a state" do
|
||||
api_get :show, id: state.id
|
||||
expect(json_response.symbolize_keys.keys).to include(*attributes)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user