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 +4 -4
- data/app/helpers/fields/address_field_helper.rb +127 -0
- data/app/helpers/refresh_fields_helper.rb +30 -0
- data/app/javascript/controllers/dependable_controller.js +24 -0
- data/app/javascript/controllers/index.js +6 -0
- data/app/javascript/controllers/refresh_fields_controller.js +68 -0
- data/lib/bullet_train/fields/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c547b13d9d1ff85a1cf3eea7e65f028285a26b65c8df77cddd30244fffd4934d
|
4
|
+
data.tar.gz: 5070d18444d36f773334b04460e506c5196f8d30f9832a782f6b3221368b0c35
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
+
}
|
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.
|
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-
|
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
|