solidus_address_book 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +23 -0
  3. data/README.md +49 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/javascripts/spree/frontend/solidus_address_book.js.erb +59 -0
  6. data/app/assets/stylesheets/spree/frontend/solidus_address_book.scss +92 -0
  7. data/app/controllers/spree/addresses_controller.rb +84 -0
  8. data/app/controllers/spree/checkout_controller_decorator.rb +65 -0
  9. data/app/helpers/spree/addresses_helper.rb +39 -0
  10. data/app/models/concerns/solidus_address_book/address.rb +18 -0
  11. data/app/models/concerns/solidus_address_book/permitted_attributes_concern.rb +11 -0
  12. data/app/models/permitted_attributes_decorator.rb +1 -0
  13. data/app/models/spree/address_ability.rb +15 -0
  14. data/app/models/spree/address_decorator.rb +83 -0
  15. data/app/models/spree/order_decorator.rb +109 -0
  16. data/app/models/spree/user_decorator.rb +11 -0
  17. data/app/overrides/add_address_book_to_my_account.rb +9 -0
  18. data/app/views/spree/addresses/_form.html.erb +114 -0
  19. data/app/views/spree/addresses/destroy.js.erb +2 -0
  20. data/app/views/spree/addresses/edit.html.erb +29 -0
  21. data/app/views/spree/addresses/new.html.erb +29 -0
  22. data/app/views/spree/checkout/_address.html.erb +75 -0
  23. data/app/views/spree/users/_addresses.html.erb +36 -0
  24. data/config/locales/de.yml +15 -0
  25. data/config/locales/en.yml +28 -0
  26. data/config/locales/pt-BR.yml +3 -0
  27. data/config/locales/ru.yml +13 -0
  28. data/config/routes.rb +9 -0
  29. data/db/migrate/20110302102208_add_user_id_and_deleted_at_to_addresses.rb +13 -0
  30. data/db/migrate/20190619191704_add_label_to_addresses.rb +7 -0
  31. data/lib/generators/solidus_address_book/install_generator.rb +30 -0
  32. data/lib/solidus_address_book.rb +6 -0
  33. data/lib/solidus_address_book/configuration.rb +8 -0
  34. data/lib/solidus_address_book/engine.rb +24 -0
  35. data/lib/solidus_address_book/version.rb +5 -0
  36. metadata +354 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e29b309ed59a46f6c4d92836e0ea7e0bef0d02d0e05f6898a5732d5c91222b83
4
+ data.tar.gz: 3ec20b3bb838b872b00c18c84a4136ca30c0bb5e72974a942d1f2e099b3bf57e
5
+ SHA512:
6
+ metadata.gz: fba1a134b5a2f637cec525ac4704df909ac1998ba302c5c7746684eef59cf8c904c45ffeed5c93c66054fa46594f61956a52e1526b4c9a5db4f0437780201d92
7
+ data.tar.gz: 2eed12772aa1d22393c2b4ebb9d023e679f49c8b29472c84387ee59d79915fda6570155544b5d3d2463d8e4298315b45e6c95c84c54cc7996a79e774ff34e219
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Redistribution and use in source and binary forms, with or without modification,
2
+ are permitted provided that the following conditions are met:
3
+
4
+ * Redistributions of source code must retain the above copyright notice,
5
+ this list of conditions and the following disclaimer.
6
+ * Redistributions in binary form must reproduce the above copyright notice,
7
+ this list of conditions and the following disclaimer in the documentation
8
+ and/or other materials provided with the distribution.
9
+ * Neither the name of the Rails Dog LLC nor the names of its
10
+ contributors may be used to endorse or promote products derived from this
11
+ software without specific prior written permission.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,49 @@
1
+ # SolidusAddressBook
2
+
3
+ [![Build Status](https://travis-ci.org/jtapia/solidus_address_book.svg?branch=master)](https://travis-ci.org/jtapia/solidus_address_book)
4
+
5
+ This extension allows registered users to have multiple shipping & billing addresses and select each of them on checkout.
6
+
7
+ This extension is a solidus version of [spree_address_book extension](https://github.com/spree-contrib/spree_address_book)
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'solidus_address_book', github: 'jtapia/solidus_address_book'
15
+ ```
16
+
17
+ Then run the following:
18
+
19
+ ```console
20
+ $ bundle install
21
+ $ bundle exec rails g solidus_address_book:install
22
+ ```
23
+
24
+ ## Preview
25
+
26
+ ![account-index](https://user-images.githubusercontent.com/957520/59891993-f2d90180-939c-11e9-8812-1e4aea887734.png)
27
+ ![checkout user addresses](https://user-images.githubusercontent.com/957520/59891953-d76df680-939c-11e9-8395-6ff728aff51a.png)
28
+ ![edit address form](https://user-images.githubusercontent.com/957520/59891955-d8068d00-939c-11e9-9b90-1cdf70d75dbe.png)
29
+ ![new address form](https://user-images.githubusercontent.com/957520/59891956-d8068d00-939c-11e9-8e6a-ae079f7afa1a.png)
30
+ ![checkout address options](https://user-images.githubusercontent.com/957520/59892001-fbc9d300-939c-11e9-8571-d18a32a06868.png)
31
+ ![checkout address options](https://user-images.githubusercontent.com/957520/59892002-fbc9d300-939c-11e9-8873-b898743b329a.png)
32
+ ![checkout address options](https://user-images.githubusercontent.com/957520/59892003-fbc9d300-939c-11e9-9101-277b460c3375.png)
33
+ ![checkout address options](https://user-images.githubusercontent.com/957520/59892004-fbc9d300-939c-11e9-88b3-f5a1efecdad0.png)
34
+
35
+ ## Testing
36
+
37
+ Run the following to automatically build a dummy app and run the tests:
38
+
39
+ ```console
40
+ $ bundle exec rake
41
+ ```
42
+
43
+ ## Contributing
44
+
45
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jtapia/solidus_address_book.
46
+
47
+ ## License
48
+
49
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rspec/core/rake_task'
7
+ require 'spree/testing_support/extension_rake'
8
+
9
+ RSpec::Core::RakeTask.new
10
+
11
+ task :default do
12
+ if Dir["spec/dummy"].empty?
13
+ Rake::Task[:test_app].invoke
14
+ Dir.chdir("../../")
15
+ end
16
+ Rake::Task[:spec].invoke
17
+ end
18
+
19
+ desc 'Generates a dummy app for testing'
20
+ task :test_app do
21
+ ENV['LIB_NAME'] = 'solidus_address_book'
22
+ Rake::Task['extension:test_app'].invoke
23
+ end
@@ -0,0 +1,59 @@
1
+ //= require spree/frontend
2
+ //= require spree/frontend/solidus_auth
3
+
4
+ (function($) {
5
+ $(document).ready(function(){
6
+ if ($('.select_address').length > 0) {
7
+ $('input#order_use_billing').unbind('change');
8
+
9
+ hide_address_form('billing');
10
+ hide_address_form('shipping');
11
+
12
+ if ($('input#order_use_billing').is(':checked')) {
13
+ $('#shipping .select_address').hide();
14
+ }
15
+
16
+ $('input#order_use_billing').click(function() {
17
+ if ($(this).is(':checked')) {
18
+ $('#shipping .select_address').hide();
19
+ hide_address_form('shipping');
20
+ } else {
21
+ $('#shipping .select_address').show();
22
+ if ($("input[name='order[ship_address_id]']:checked").val() == '0') {
23
+ show_address_form('shipping');
24
+ } else {
25
+ hide_address_form('shipping');
26
+ }
27
+ }
28
+ });
29
+
30
+ $("input[name='order[bill_address_id]']:radio").change(function(){
31
+ if ($("input[name='order[bill_address_id]']:checked").val() == '0') {
32
+ show_address_form('billing');
33
+ } else {
34
+ hide_address_form('billing');
35
+ }
36
+ });
37
+
38
+ $("input[name='order[ship_address_id]']:radio").change(function(){
39
+ if ($("input[name='order[ship_address_id]']:checked").val() == '0') {
40
+ show_address_form('shipping');
41
+ } else {
42
+ hide_address_form('shipping');
43
+ }
44
+ });
45
+ }
46
+ });
47
+
48
+ function hide_address_form(address_type){
49
+ $('#' + address_type + ' .inner').hide();
50
+ $('#' + address_type + ' .inner input').prop('disabled', true).prop('value', '');
51
+ $('#' + address_type + ' .inner select').prop('disabled', true).prop('value', '');
52
+ }
53
+
54
+ function show_address_form(address_type){
55
+ $('#' + address_type + ' .inner').show();
56
+ $('#' + address_type + ' .inner input').prop('disabled', false).prop('value', '');
57
+ $('#' + address_type + ' .inner select').prop('disabled', false).prop('value', '');
58
+ }
59
+ })(jQuery);
@@ -0,0 +1,92 @@
1
+ p[data-hook='use_billing'] {
2
+ bottom: 30px;
3
+ position: relative;
4
+ margin-bottom: 0;
5
+ margin-top: 0;
6
+
7
+ input[type=checkbox] {
8
+ display: inline-block;
9
+ }
10
+ }
11
+
12
+ .new_address {
13
+ input[type=text],
14
+ input[type=tel],
15
+ select {
16
+ width: 100%;
17
+ }
18
+
19
+ input[type=checkbox] {
20
+ display: inline-block;
21
+ margin-right: 3px;
22
+ }
23
+ }
24
+
25
+ .edit_address {
26
+ input[type=text],
27
+ input[type=tel],
28
+ select {
29
+ width: 100%;
30
+ }
31
+ }
32
+
33
+ div#checkout #checkout_form_address {
34
+ #billing, #shipping {
35
+ input[type=checkbox] {
36
+ display: inline-block;
37
+ margin-right: 3px;
38
+ }
39
+
40
+ .select_address {
41
+ ul {
42
+ list-style-type: none;
43
+ margin: 10px 0;
44
+ padding: 0;
45
+ overflow: hidden;
46
+ width: 100%;
47
+
48
+ li {
49
+ float: left;
50
+ height: auto;
51
+ margin-bottom: 10px;
52
+ width: 25%;
53
+
54
+ label {
55
+ display: block;
56
+ float: none;
57
+ }
58
+
59
+ .address-label {
60
+ font-size: 1em;
61
+ font-weight: bold;
62
+ margin-left: 3px;
63
+ }
64
+
65
+ .address-text {
66
+ display: block;
67
+ margin-top: 10px;
68
+ }
69
+
70
+ .edit-address {
71
+ display: block;
72
+ margin-top: 5px;
73
+ }
74
+ }
75
+
76
+ input[type=radio] {
77
+ margin: 0px 2px;
78
+ width: auto;
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ .account-my-addresses {
86
+ table[data-hook='account_my_addresses_table'] {
87
+ margin-bottom: 10px;
88
+ width: 100%;
89
+ }
90
+ }
91
+
92
+ .hidden { display: none; }
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ class AddressesController < Spree::StoreController
5
+ helper Spree::AddressesHelper
6
+ rescue_from ActiveRecord::RecordNotFound, with: :render_404
7
+ load_and_authorize_resource class: Spree::Address
8
+
9
+ before_action :load_address, only: [:update, :destroy]
10
+ before_action :set_return_path, only: :edit
11
+
12
+ def new
13
+ @address = Spree::Address.default
14
+ end
15
+
16
+ def create
17
+ @address = try_spree_current_user.addresses.build(address_params)
18
+
19
+ if @address.save
20
+ flash[:notice] = t('spree.successfully_created')
21
+ redirect_to account_path
22
+ else
23
+ flash[:error] = @address.errors.full_messages.join(', ')
24
+ render action: 'new'
25
+ end
26
+ end
27
+
28
+ def update
29
+ @address.editable? ? update_address : clone_address
30
+ end
31
+
32
+ def destroy
33
+ if @address.destroy
34
+ flash[:notice] = t('spree.successfully_removed')
35
+ redirect_to request.env['HTTP_REFERER'] || account_path
36
+ else
37
+ flash[:error] = t('spree.unsuccessfully_removed')
38
+ redirect_to :back
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def address_params
45
+ params.require(:address).permit(:label, :address, :firstname, :lastname,
46
+ :address1, :address2, :city, :state_id, :zipcode,
47
+ :country_id, :phone, :user_id)
48
+ end
49
+
50
+ def load_address
51
+ @address ||= Spree::Address.find(id: params[:id])
52
+ end
53
+
54
+ def set_return_path
55
+ session['spree_user_return_to'] = request.env['HTTP_REFERER']
56
+ end
57
+
58
+ def update_address
59
+ if @address.update_attributes(address_params)
60
+ flash[:notice] = t('spree.successfully_updated')
61
+ redirect_back_or_default(account_path)
62
+ else
63
+ render action: 'edit'
64
+ end
65
+ end
66
+
67
+ def clone_address
68
+ address = @address
69
+ new_address = Spree::Address.new(address.attributes.except('id',
70
+ 'created_at',
71
+ 'updated_at',
72
+ 'deleted_at'))
73
+ new_address.assign_attributes(address_params)
74
+ address.destroy
75
+
76
+ if @address = new_address.save
77
+ flash[:notice] = t('spree.successfully_updated')
78
+ redirect_back_or_default(account_path)
79
+ else
80
+ render action: 'edit'
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CheckoutControllerDecorator
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ prepend(InstanceMethods)
8
+ helper Spree::AddressesHelper
9
+
10
+ after_action :normalize_addresses, only: :update
11
+ before_action :set_addresses, only: :update
12
+ before_action :user_addresses, only: :edit, if: -> { params[:state] == 'address' }
13
+ end
14
+
15
+ module InstanceMethods
16
+ protected
17
+
18
+ def set_addresses
19
+ return unless params[:order] && params[:state] == "address"
20
+
21
+ if params[:order][:ship_address_id].to_i > 0
22
+ params[:order].delete(:ship_address_attributes)
23
+
24
+ Spree::Address.find(params[:order][:ship_address_id]).user_id != try_spree_current_user.id && raise("Frontend address forging")
25
+ else
26
+ params[:order].delete(:ship_address_id)
27
+ end
28
+
29
+ if params[:order][:bill_address_id].to_i > 0
30
+ params[:order].delete(:bill_address_attributes)
31
+
32
+ Spree::Address.find(params[:order][:bill_address_id]).user_id != try_spree_current_user.id && raise("Frontend address forging")
33
+ else
34
+ params[:order].delete(:bill_address_id)
35
+ end
36
+ end
37
+
38
+ def normalize_addresses
39
+ return unless params[:state] == 'address' && @order.bill_address_id && @order.ship_address_id
40
+
41
+ # ensure that there is no validation errors and addresses were saved
42
+ return unless @order.bill_address && @order.ship_address
43
+
44
+ bill_address = @order.bill_address
45
+ ship_address = @order.ship_address
46
+
47
+ if @order.bill_address_id != @order.ship_address_id && bill_address.same_as?(ship_address)
48
+ @order.update_attribute(:bill_address_id, ship_address.id)
49
+ bill_address.destroy
50
+ elsif params[:save_user_address]
51
+ bill_address.update_attribute(:user_id, try_spree_current_user&.id)
52
+ end
53
+
54
+ ship_address.update_attribute(:user_id, try_spree_current_user&.id) if params[:save_user_address]
55
+ end
56
+
57
+ private
58
+
59
+ def user_addresses
60
+ @user_addresses ||= try_spree_current_user&.addresses
61
+ end
62
+ end
63
+ end
64
+
65
+ Spree::CheckoutController.include(CheckoutControllerDecorator)
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module AddressesHelper
5
+ def address_field(form, method, address_id = 'b', &handler)
6
+ content_tag :p, id: [address_id, method].join, class: 'form-group' do
7
+ if handler
8
+ handler.call
9
+ else
10
+ is_required = Spree::Address.required_fields.include?(method)
11
+ separator = is_required ? '<span class="required">*</span><br />' : '<br />'
12
+ form.label(method) +
13
+ separator.html_safe +
14
+ form.text_field(method, class: [is_required ? 'required' : nil, 'form-control'].compact)
15
+ end
16
+ end
17
+ end
18
+
19
+ def address_state(form, country, address_id = 'b')
20
+ country ||= Spree::Country.find(Spree::Config[:default_country_id])
21
+ have_states = !country.states.empty?
22
+ state_elements = [
23
+ form.collection_select(:state_id,
24
+ country.states.order(:name),
25
+ :id, :name,
26
+ { include_blank: true },
27
+ { class: have_states ? 'required form-control' : 'hidden',
28
+ disabled: !have_states }) +
29
+ form.text_field(:state_name,
30
+ class: !have_states ? 'required' : 'hidden',
31
+ disabled: have_states)
32
+ ].join.gsub('"', "'").gsub("\n", "")
33
+
34
+ form.label(:state, t(:state)) + '<span class="req">*</span><br />'.html_safe +
35
+ content_tag(:noscript, form.text_field(:state_name, class: 'required')) +
36
+ javascript_tag("document.write(\"#{state_elements.html_safe}\");")
37
+ end
38
+ end
39
+ end