bullet_train-fields 1.3.21 → 1.3.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7a0d3f08265c7e50f763434c57c88f284be710d7d63ce0cc8fbaff886311db9
4
- data.tar.gz: b035e5ff82398aa88f30b757516b6c03ac31d01256b88c24c938dec2638c0ffb
3
+ metadata.gz: c547b13d9d1ff85a1cf3eea7e65f028285a26b65c8df77cddd30244fffd4934d
4
+ data.tar.gz: 5070d18444d36f773334b04460e506c5196f8d30f9832a782f6b3221368b0c35
5
5
  SHA512:
6
- metadata.gz: 85e68bcc552bd519e3f6b0d6792109a3e3d2602b943aa29e0806f4b6ef777a6eb371fae067e9e8d8f0feff2cf1cf67353dcf34751900aa6d9965d493f838b862
7
- data.tar.gz: a539896e8d1deabf39906b9e385521975a4816a6a4b3afbbdc058489c4ebf0793a2074f5e4a56ab5e94e3f37d400cccd8324ee25e0c2c6c80b15ab74771cc676
6
+ metadata.gz: 3fbe6e3df3014fe0ae7e5d61ae88643d7c5d7ea4c819f4617b1fb1ee4e735b0b9c38ce111eacff30b14414eb8dd5ca2f4f562929571f9ad8aadaf31e43b7507d
7
+ data.tar.gz: d4edcea75f716cab08849f03414381c6a29b03a5350df76bf5af4717fc0a01862f0cd6b7278e39e9850f7990dfdf44d28ba85a249d7018b0956d6439c03e285c
@@ -0,0 +1,127 @@
1
+ module Fields::AddressFieldHelper
2
+ def populate_country_options
3
+ ([Addresses::Country.find_by(name: "United States"), Addresses::Country.find_by(name: "Canada")] + Addresses::Country.all).map { |country| [country.name, country.id] }.uniq
4
+ end
5
+
6
+ def populate_region_options(address_form)
7
+ return [] if address_form.object.country_id.nil?
8
+ Addresses::Region.where(country_id: address_form.object.country_id).map { |region| [region.name, region.id] }
9
+ end
10
+
11
+ def admin_division_label_for(address_form)
12
+ # using country_id because it's fastest, even if this case statement is hard to read
13
+ admin_divisions_key = case address_form.object.country_id
14
+ when 233, 31, 142, 239, 101
15
+ :states
16
+ when 39
17
+ :provinces_territories
18
+ when 109
19
+ :prefectures
20
+ when 107, 45, 116, 182, 207, 219, 230, 156, 204
21
+ :provinces
22
+ when 14
23
+ :states_territories
24
+ when 59
25
+ :regions
26
+ when 82, 15
27
+ :federal_states
28
+ when 75
29
+ :departments
30
+ when 105
31
+ :counties
32
+ when 214
33
+ :cantons
34
+ else
35
+ :default
36
+ end
37
+ path = [:addresses, :fields, :admin_divisions, admin_divisions_key]
38
+ t(path.compact.join("."))
39
+ end
40
+
41
+ def postal_code_label_for(address_form)
42
+ key = if address_form.object.country_id == 233
43
+ :zip_code
44
+ else
45
+ :postal_code
46
+ end
47
+ path = [:addresses, :fields, key, :label]
48
+ t(path.compact.join("."))
49
+ end
50
+
51
+ def address_formatted(address, one_line: false)
52
+ return "" if address.all_blank?
53
+
54
+ formatted = [
55
+ address.address_one,
56
+ address.address_two,
57
+ address_city_line_formatted(address),
58
+ address.country&.name&.upcase
59
+ ].reject(&:blank?)
60
+
61
+ if one_line
62
+ formatted.join(", ") # simplistic
63
+ else
64
+ simple_format(formatted.join("\n"))
65
+ end
66
+ end
67
+
68
+ def address_city_line_formatted(address)
69
+ country_iso2 = address.country&.iso2 # can be nil or empty
70
+ city = address.city
71
+ region = address.region&.name
72
+ postal_code = address.postal_code
73
+
74
+ # adapted from https://github.com/cainlevy/snail/blob/master/lib/snail.rb
75
+ # using iso2 property here because it's a port of what's used in snail gem
76
+ # will be cleaned up below if parts missing
77
+ formatted = case country_iso2
78
+ when "CN", "IN"
79
+ "#{city}, #{region} #{postal_code}"
80
+ when "BR"
81
+ "#{postal_code} #{city}#{"-" unless city.nil? || city.empty? || region.nil? || region.empty?}#{region}"
82
+ when "MX", "SK"
83
+ "#{postal_code} #{city}, #{region}"
84
+ when "IT"
85
+ "#{postal_code} #{city} #{region}"
86
+ when "BY"
87
+ "#{postal_code} #{city}#{"-" unless city.nil? || city.empty? || region.nil? || region.empty?}#{region}"
88
+ when "US", "CA", "AU", nil, ""
89
+ "#{city} #{region} #{postal_code}"
90
+ when "IL", "DK", "FI", "FR", "DE", "GR", "NO", "ES", "SE", "TR", "CY", "PT", "MK", "BA"
91
+ "#{postal_code} #{city}"
92
+ when "KW", "SY", "OM", "EE", "LU", "BE", "IS", "CH", "AT", "MD", "ME", "RS", "BG", "GE", "PL", "AM", "HR", "RO", "AZ"
93
+ "#{postal_code} #{city}"
94
+ when "NL"
95
+ "#{postal_code} #{city}"
96
+ when "IE"
97
+ "#{city}, #{region}\n#{postal_code}"
98
+ when "GB", "RU", "UA", "JO", "LB", "IR", "SA", "NZ"
99
+ "#{city} #{postal_code}" # Locally these may be on separate lines. The USPS prefers the city line above the country line, though.
100
+ when "EC"
101
+ "#{postal_code} #{city}"
102
+ when "HK", "IQ", "YE", "QA", "AL"
103
+ city.to_s
104
+ when "AE"
105
+ "#{postal_code}\n#{city}"
106
+ when "JP"
107
+ "#{city}, #{region}\n#{postal_code}"
108
+ when "EG", "ZA", "IM", "KZ", "HU"
109
+ "#{city}\n#{postal_code}"
110
+ when "LV"
111
+ "#{city}, LV-#{postal_code}".gsub(/LV-\s*$/, "") # undo if no postal code
112
+ when "LT"
113
+ "LT-#{postal_code} #{city}".gsub(/^LT-\s*/, "") # undo if no postal code
114
+ when "SI"
115
+ "SI-#{postal_code} #{city}".gsub(/^SI-\s*/, "") # undo if no postal code
116
+ when "CZ"
117
+ "#{postal_code} #{region}\n#{city}"
118
+ else
119
+ "#{city} #{region} #{postal_code}"
120
+ end
121
+
122
+ # clean up separators when missing pieces
123
+ formatted.strip # remove extra spaces and newlines before and after
124
+ .gsub(/^,\s*/, "") # remove extra comma from start
125
+ .gsub(/\s*,$/, "") # remove extra comma from end
126
+ end
127
+ end
@@ -0,0 +1,30 @@
1
+ module RefreshFieldsHelper
2
+ def accept_query_string_override_for(form, method)
3
+ field_name = form.field_name(method)
4
+
5
+ new_value = new_value_from_query_string(field_name)
6
+ return if new_value.nil?
7
+
8
+ form.object[method] = new_value
9
+ end
10
+
11
+ private
12
+
13
+ def new_value_from_query_string(field_name)
14
+ params.dig(*params_dig_path_for_field_name(field_name))
15
+ end
16
+
17
+ def params_dig_path_for_field_name(field_name)
18
+ dig_path = []
19
+
20
+ nested_keys = Rack::Utils.parse_nested_query(field_name)
21
+
22
+ while !nested_keys.nil? && nested_keys.keys.size
23
+ key = nested_keys.keys.first
24
+ dig_path << key.to_sym
25
+ nested_keys = nested_keys[key]
26
+ end
27
+
28
+ dig_path
29
+ end
30
+ end
@@ -0,0 +1,24 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ export default class extends Controller {
4
+ static values = {
5
+ dependentsSelector: String
6
+ }
7
+
8
+ updateDependents(event) {
9
+ if (!this.hasDependents) { return false }
10
+
11
+ this.dependents.forEach((dependent) => {
12
+ dependent.dispatchEvent(new CustomEvent(`${this.identifier}:updated`, { detail: { event: event }, bubbles: true, cancelable: false }))
13
+ })
14
+ }
15
+
16
+ get hasDependents() {
17
+ return (this.dependents.length > 0)
18
+ }
19
+
20
+ get dependents() {
21
+ if (!this.dependentsSelectorValue) { return [] }
22
+ return document.querySelectorAll(this.dependentsSelectorValue)
23
+ }
24
+ }
@@ -11,6 +11,8 @@ import FileItemController from './fields/file_item_controller'
11
11
  import PasswordController from './fields/password_controller'
12
12
  import PhoneController from './fields/phone_controller'
13
13
  import SuperSelectController from './fields/super_select_controller'
14
+ import DependableController from './dependable_controller'
15
+ import RefreshFieldsController from './refresh_fields_controller'
14
16
 
15
17
  export const controllerDefinitions = [
16
18
  [FieldController, 'fields/field_controller.js'],
@@ -24,6 +26,8 @@ export const controllerDefinitions = [
24
26
  [PasswordController, 'fields/password_controller.js'],
25
27
  [PhoneController, 'fields/phone_controller.js'],
26
28
  [SuperSelectController, 'fields/super_select_controller.js'],
29
+ [DependableController, 'dependable_controller.js'],
30
+ [RefreshFieldsController, 'refresh_fields_controller.js'],
27
31
  ].map(function(d) {
28
32
  const key = d[1]
29
33
  const controller = d[0]
@@ -45,4 +49,6 @@ export {
45
49
  PasswordController,
46
50
  PhoneController,
47
51
  SuperSelectController,
52
+ DependableController,
53
+ RefreshFieldsController,
48
54
  }
@@ -0,0 +1,68 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ export default class extends Controller {
4
+ static targets = [ "field" ]
5
+ static values = {
6
+ valuesStore: { type: Object, default: {} },
7
+ loading: { type: Boolean, default: false }
8
+ }
9
+ static classes = [ "loading" ]
10
+
11
+ updateFrameFromDependentField(event) {
12
+ const field = event?.detail?.event?.detail?.event?.target || // super select nests its original jQuery event, contains <select> target
13
+ event?.detail?.event?.target || // dependable_controller will include the original event in detail
14
+ event?.target // maybe it was fired straight from the field
15
+
16
+ if (!field) { return }
17
+
18
+ this.storeFieldValues()
19
+
20
+ this.loadingValue = true
21
+ this.disableFieldInputWhileRefreshing()
22
+
23
+ const frame = this.element
24
+ frame.src = this.constructNewUrlUpdatingField(field.name, field.value)
25
+ }
26
+
27
+ finishFrameUpdate(event) {
28
+ if (event.target !== this.element) { return }
29
+
30
+ this.restoreFieldValues()
31
+ this.loadingValue = false
32
+ }
33
+
34
+ constructNewUrlUpdatingField(fieldName, fieldValue) {
35
+ const url = new URL(window.location.href)
36
+ url.searchParams.set(fieldName, fieldValue)
37
+
38
+ return url.href
39
+ }
40
+
41
+ disableFieldInputWhileRefreshing() {
42
+ this.fieldTargets.forEach(field => field.disabled = true )
43
+ }
44
+
45
+ loadingValueChanged() {
46
+ if (!this.hasLoadingClass) { return }
47
+ this.element.classList.toggle(...this.loadingClasses, this.loadingValue)
48
+ }
49
+
50
+ storeFieldValues() {
51
+ this.fieldTargets.forEach(field => {
52
+ let storeUpdate = {}
53
+ storeUpdate[field.name] = field.value
54
+ this.valuesStoreValue = Object.assign(this.valuesStoreValue, storeUpdate)
55
+ })
56
+ }
57
+
58
+ restoreFieldValues() {
59
+ this.fieldTargets.forEach(field => {
60
+ const storedValue = this.valuesStoreValue[field.name]
61
+ if (storedValue === undefined) { return }
62
+ field.value = storedValue
63
+ field.dispatchEvent(new Event('change')) // ensures cascading effects, including super-select validating against valid options
64
+ })
65
+
66
+ this.valuesStoreValue = {}
67
+ }
68
+ }
@@ -1,5 +1,5 @@
1
1
  module BulletTrain
2
2
  module Fields
3
- VERSION = "1.3.21"
3
+ VERSION = "1.3.22"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train-fields
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.21
4
+ version: 1.3.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-31 00:00:00.000000000 Z
11
+ date: 2023-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: standard
@@ -99,11 +99,14 @@ files:
99
99
  - app/controllers/concerns/fields/date_support.rb
100
100
  - app/controllers/concerns/fields/options_support.rb
101
101
  - app/controllers/concerns/fields/super_select_support.rb
102
+ - app/helpers/fields/address_field_helper.rb
102
103
  - app/helpers/fields/cloudinary_image_helper.rb
103
104
  - app/helpers/fields/html_editor_helper.rb
104
105
  - app/helpers/fields/phone_field_helper.rb
105
106
  - app/helpers/fields/trix_editor_helper.rb
106
107
  - app/helpers/fields_helper.rb
108
+ - app/helpers/refresh_fields_helper.rb
109
+ - app/javascript/controllers/dependable_controller.js
107
110
  - app/javascript/controllers/fields/button_toggle_controller.js
108
111
  - app/javascript/controllers/fields/cloudinary_image_controller.js
109
112
  - app/javascript/controllers/fields/color_picker_controller.js
@@ -116,6 +119,7 @@ files:
116
119
  - app/javascript/controllers/fields/phone_controller.js
117
120
  - app/javascript/controllers/fields/super_select_controller.js
118
121
  - app/javascript/controllers/index.js
122
+ - app/javascript/controllers/refresh_fields_controller.js
119
123
  - app/javascript/index.js
120
124
  - app/javascript/trix_editor.js
121
125
  - config/routes.rb