brick 1.0.246 → 1.0.248
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/brick/compatibility.rb +1 -1
- data/lib/brick/extensions.rb +69 -43
- data/lib/brick/rails/engine.rb +70 -72
- data/lib/brick/rails/form_builder.rb +18 -16
- data/lib/brick/rails/form_tags.rb +55 -24
- data/lib/brick/rails.rb +34 -34
- data/lib/brick/reflect_tables.rb +18 -12
- data/lib/brick/util.rb +3 -3
- data/lib/brick/version_number.rb +1 -1
- data/lib/brick.rb +9 -9
- data/lib/generators/brick/airtable_api_caller.rb +21 -7
- data/lib/generators/brick/airtable_migrations_generator.rb +3 -2
- data/lib/generators/brick/airtable_seeds_generator.rb +1 -1
- data/lib/generators/brick/install_generator.rb +1 -1
- data/lib/generators/brick/migrations_builder.rb +39 -15
- data/lib/generators/brick/seeds_builder.rb +77 -35
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ea1b54ee47db7637a4122bccb3fdcb613550aae57632bc6ce590851307085da2
|
|
4
|
+
data.tar.gz: 1f80b6c273b32df62b8b00f1251c9eea3322ecfd8cc308472cce4dbfecb85866
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: abb49248dc4466a54f892210db594acd481fe0292a21077fdc32e566855aabeca634b8ad5f9a4bef1d52c05e2aa798a4d24002f046e80bd285c19042db637d7e
|
|
7
|
+
data.tar.gz: a40eb65cfbd88e69e9b6dff165fbc4e83251b002cd445da9ad6a229841138311197fca25e22733c19e3ece186ecfbca882a35b7d64984ceaa3782571c65b181d
|
data/lib/brick/compatibility.rb
CHANGED
|
@@ -119,7 +119,7 @@ if Object.const_defined?('ActionPack') && !ActionPack.respond_to?(:version)
|
|
|
119
119
|
end
|
|
120
120
|
end
|
|
121
121
|
end
|
|
122
|
-
if Object.const_defined?('Bundler') && Bundler.locked_gems&.dependencies
|
|
122
|
+
if Object.const_defined?('Bundler') && Bundler.locked_gems&.dependencies&.key?('action_view')
|
|
123
123
|
require 'action_view' # Needed for Rails <= 4.0
|
|
124
124
|
module ::ActionView
|
|
125
125
|
if Object.const_defined?('ActionView') && !ActionView.respond_to?(:version)
|
data/lib/brick/extensions.rb
CHANGED
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
|
|
39
39
|
# Upon creation of a new object, when going to the index page, highlight this new object and scroll it into view (likely to the very bottom of everything, although might be sorted differently)
|
|
40
40
|
|
|
41
|
+
# If there is a module defined with the same name as a schema found in a Postgres, MSSQL, or Oracle database then missing models that should exist underneath that module are not auto-generated.
|
|
42
|
+
|
|
41
43
|
# ==========================================================
|
|
42
44
|
# Dynamically create model or controller classes when needed
|
|
43
45
|
# ==========================================================
|
|
@@ -105,13 +107,41 @@ module ActiveRecord
|
|
|
105
107
|
col_names = columns_hash.keys
|
|
106
108
|
# If it's a composite primary key then allow all the values through
|
|
107
109
|
# TODO: Should disallow any autoincrement / SERIAL columns
|
|
108
|
-
if skip_id && (pk_as_array = _pk_as_array).length == 1
|
|
109
|
-
|
|
110
|
+
if skip_id && (pk_as_array = _pk_as_array).length == 1 &&
|
|
111
|
+
[:string, :text].exclude?(columns_hash[pk_as_array.first]&.type)
|
|
112
|
+
col_names -= pk_as_array
|
|
110
113
|
end
|
|
111
114
|
hoa, hma, rtans = _activestorage_actiontext_fields
|
|
112
115
|
col_names.map(&:to_sym) + hoa + hma.map { |as| { as => [] } } + rtans.values
|
|
113
116
|
end
|
|
114
117
|
|
|
118
|
+
def _brick_set_wheres(params, join_array = nil)
|
|
119
|
+
is_distinct = nil
|
|
120
|
+
wheres = {}
|
|
121
|
+
params.each do |k, v|
|
|
122
|
+
k = k.to_s # Rails < 4.2 comes in as a symbol
|
|
123
|
+
next unless k.start_with?('__')
|
|
124
|
+
|
|
125
|
+
k = k[2..-1] # Take off leading "__"
|
|
126
|
+
if (where_col = (ks = k.split('.')).last)[-1] == '!'
|
|
127
|
+
where_col = where_col[0..-2]
|
|
128
|
+
end
|
|
129
|
+
case ks.length
|
|
130
|
+
when 1
|
|
131
|
+
next unless self.column_names.any?(where_col) || self._brick_get_fks.include?(where_col)
|
|
132
|
+
when 2
|
|
133
|
+
assoc_name = ks.first.to_sym
|
|
134
|
+
# Make sure it's a good association name and that the model has that column name
|
|
135
|
+
next unless self.reflect_on_association(assoc_name)&.klass&.column_names&.any?(where_col)
|
|
136
|
+
|
|
137
|
+
join_array&.[]=(assoc_name, nil) # Store this relation name in our special collection for .joins()
|
|
138
|
+
is_distinct = true
|
|
139
|
+
end
|
|
140
|
+
wheres[k] = v.is_a?(String) ? v.split(',') : v
|
|
141
|
+
end
|
|
142
|
+
[wheres, is_distinct]
|
|
143
|
+
end
|
|
144
|
+
|
|
115
145
|
# Return three lists of fields for this model --
|
|
116
146
|
# has_one_attached, has_many_attached, and has_rich_text
|
|
117
147
|
def _activestorage_actiontext_fields
|
|
@@ -185,7 +215,7 @@ module ActiveRecord
|
|
|
185
215
|
end
|
|
186
216
|
|
|
187
217
|
def is_postgres
|
|
188
|
-
@is_postgres ||= connection.adapter_name
|
|
218
|
+
@is_postgres ||= ['PostgreSQL', 'PostGIS'].include?(connection.adapter_name)
|
|
189
219
|
end
|
|
190
220
|
def is_mysql
|
|
191
221
|
@is_mysql ||= ['Mysql2', 'Trilogy'].include?(connection.adapter_name)
|
|
@@ -219,10 +249,17 @@ module ActiveRecord
|
|
|
219
249
|
else
|
|
220
250
|
# If there's no DSL yet specified, just try to find the first usable column on this model
|
|
221
251
|
dsl = if table_exists?
|
|
222
|
-
skip_columns = _brick_get_fks + (::Brick.config.metadata_columns || [])
|
|
223
|
-
|
|
252
|
+
skip_columns = _brick_get_fks + (::Brick.config.metadata_columns || [])
|
|
253
|
+
column_list = columns.dup
|
|
254
|
+
pk_idx = column_list.index { |c| c.name == primary_key }
|
|
255
|
+
if pk_idx
|
|
256
|
+
pk_column = column_list.delete_at(pk_idx)
|
|
257
|
+
# if the PK column is a string, put it at the end so it will get chosen as a last resort
|
|
258
|
+
column_list << pk_column if [:string, :text].include?(columns_hash[primary_key]&.type)
|
|
259
|
+
end
|
|
260
|
+
if (descrip_col = column_list.find { |c| c.type == :string && skip_columns.exclude?(c.name) })
|
|
224
261
|
"[#{descrip_col.name}]"
|
|
225
|
-
elsif (descrip_col =
|
|
262
|
+
elsif (descrip_col = column_list.find { |c| [:boolean, :binary, :xml].exclude?(c.type) && skip_columns.exclude?(c.name) })
|
|
226
263
|
"[#{descrip_col.name}]"
|
|
227
264
|
else
|
|
228
265
|
"#{name} ##{_pk_as_array.map { |pk_part| "[#{pk_part}]" }.join(', ')}"
|
|
@@ -689,32 +726,10 @@ module ActiveRecord
|
|
|
689
726
|
# model early in case the user wants to do an ORDER BY based on any of that.
|
|
690
727
|
model._brick_calculate_bts_hms(translations, join_array) if is_add_bts || is_add_hms
|
|
691
728
|
|
|
692
|
-
is_distinct = nil
|
|
693
|
-
wheres = {}
|
|
694
729
|
params = params.to_unsafe_h unless params.is_a?(Hash)
|
|
695
730
|
params.merge!(args[1]) if args[1]
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
next unless k.start_with?('__')
|
|
699
|
-
|
|
700
|
-
k = k[2..-1] # Take off leading "__"
|
|
701
|
-
if (where_col = (ks = k.split('.')).last)[-1] == '!'
|
|
702
|
-
where_col = where_col[0..-2]
|
|
703
|
-
end
|
|
704
|
-
case ks.length
|
|
705
|
-
when 1
|
|
706
|
-
next unless klass.column_names.any?(where_col) || klass._brick_get_fks.include?(where_col)
|
|
707
|
-
when 2
|
|
708
|
-
assoc_name = ks.first.to_sym
|
|
709
|
-
# Make sure it's a good association name and that the model has that column name
|
|
710
|
-
next unless klass.reflect_on_association(assoc_name)&.klass&.column_names&.any?(where_col)
|
|
711
|
-
|
|
712
|
-
join_array[assoc_name] = nil # Store this relation name in our special collection for .joins()
|
|
713
|
-
is_distinct = true
|
|
714
|
-
distinct!
|
|
715
|
-
end
|
|
716
|
-
wheres[k] = v.is_a?(String) ? v.split(',') : v
|
|
717
|
-
end
|
|
731
|
+
wheres, is_distinct = klass._brick_set_wheres(params, join_array)
|
|
732
|
+
distinct! if is_distinct
|
|
718
733
|
|
|
719
734
|
# %%% Skip the metadata columns
|
|
720
735
|
if selects.empty? # Default to all columns
|
|
@@ -1756,7 +1771,7 @@ class Object
|
|
|
1756
1771
|
end
|
|
1757
1772
|
full_name = if relation || schema_name.blank?
|
|
1758
1773
|
if singular_table_name != table_name.singularize && # %%% Try this with http://localhost:3000/brick/spree/property_translations
|
|
1759
|
-
(schema_module = ::Brick.config.table_name_prefixes.find { |k, v| table_name.start_with?(k) }&.last&.constantize)
|
|
1774
|
+
(schema_module = ::Brick.config.table_name_prefixes.find { |k, v| table_name.length > k&.length && table_name.start_with?(k) }&.last&.constantize)
|
|
1760
1775
|
"#{schema_module&.name}::#{inheritable_name || model_name}"
|
|
1761
1776
|
else
|
|
1762
1777
|
inheritable_name || model_name
|
|
@@ -1775,7 +1790,7 @@ class Object
|
|
|
1775
1790
|
::Brick.config.exclude_tables.include?(matching)
|
|
1776
1791
|
|
|
1777
1792
|
# Are they trying to use a pluralised class name such as "Employees" instead of "Employee"?
|
|
1778
|
-
if table_name == singular_table_name && !ActiveSupport::Inflector.inflections.uncountable.include?(table_name)
|
|
1793
|
+
if table_name == singular_table_name && model_name.pluralize == model_name && !ActiveSupport::Inflector.inflections.uncountable.include?(table_name)
|
|
1779
1794
|
# unless ::Brick.config.sti_namespace_prefixes&.key?("::#{singular_table_name.camelize}::")
|
|
1780
1795
|
# puts "Warning: Class name for a model that references table \"#{matching
|
|
1781
1796
|
# }\" should be \"#{ActiveSupport::Inflector.singularize(inheritable_name || model_name)}\"."
|
|
@@ -2193,7 +2208,7 @@ class Object
|
|
|
2193
2208
|
end
|
|
2194
2209
|
table_name = model&.table_name || ActiveSupport::Inflector.underscore(plural_class_name)
|
|
2195
2210
|
pk = model&._brick_primary_key(relations.fetch(table_name, nil))
|
|
2196
|
-
is_postgres = ActiveRecord::Base.connection.adapter_name
|
|
2211
|
+
is_postgres = ['PostgreSQL', 'PostGIS'].include?(ActiveRecord::Base.connection.adapter_name)
|
|
2197
2212
|
is_mysql = ['Mysql2', 'Trilogy'].include?(ActiveRecord::Base.connection.adapter_name)
|
|
2198
2213
|
|
|
2199
2214
|
namespace = nil if namespace == ::Object
|
|
@@ -2475,10 +2490,19 @@ class Object
|
|
|
2475
2490
|
|
|
2476
2491
|
real_model = model.find_real_model(params)
|
|
2477
2492
|
|
|
2493
|
+
# %%% Allow params to define which columns to use for order_by
|
|
2494
|
+
# Overriding the default by providing a querystring param?
|
|
2495
|
+
order_by = params['_brick_order']&.split(',')&.map(&:to_sym) || Object.send(:default_ordering, table_name, pk)
|
|
2496
|
+
|
|
2478
2497
|
if request.format == :csv # Asking for a template?
|
|
2479
2498
|
require 'csv'
|
|
2480
2499
|
exported_csv = CSV.generate(force_quotes: false) do |csv_out|
|
|
2481
|
-
|
|
2500
|
+
export_args = [true, real_model.brick_import_template, false]
|
|
2501
|
+
if real_model.method(:df_export).parameters.length > 3
|
|
2502
|
+
wheres, _is_distinct = real_model._brick_set_wheres(params)
|
|
2503
|
+
export_args += [wheres, order_by]
|
|
2504
|
+
end
|
|
2505
|
+
real_model.df_export(*export_args).each do |row|
|
|
2482
2506
|
row.each do |d|
|
|
2483
2507
|
row.each_with_index do |d, idx|
|
|
2484
2508
|
# "false" disallows HTML encoding the descriptions of binary content
|
|
@@ -2499,11 +2523,6 @@ class Object
|
|
|
2499
2523
|
end
|
|
2500
2524
|
|
|
2501
2525
|
# Normal (not swagger or CSV) request
|
|
2502
|
-
|
|
2503
|
-
# %%% Allow params to define which columns to use for order_by
|
|
2504
|
-
# Overriding the default by providing a querystring param?
|
|
2505
|
-
order_by = params['_brick_order']&.split(',')&.map(&:to_sym) || Object.send(:default_ordering, table_name, pk)
|
|
2506
|
-
|
|
2507
2526
|
ar_relation = ActiveRecord.version < Gem::Version.new('4') ? real_model.preload : real_model.all
|
|
2508
2527
|
params['_brick_is_api'] = true if (is_api = request.format == :js || current_api_root)
|
|
2509
2528
|
@_brick_params = ar_relation._brick_querying((selects ||= []), params: params, order_by: order_by,
|
|
@@ -2696,7 +2715,14 @@ class Object
|
|
|
2696
2715
|
render json: { result: es_result }
|
|
2697
2716
|
else
|
|
2698
2717
|
real_model, real_singular_table_name = model.real_singular(params)
|
|
2699
|
-
|
|
2718
|
+
# If there are any foreign keys that are strings and we've received a blank value, set that to nil
|
|
2719
|
+
internal_params = (ac_params = send(params_name_sym))&.send(:parameters)
|
|
2720
|
+
real_model.reflect_on_all_associations.each do |a|
|
|
2721
|
+
if a.belongs_to? && internal_params.key?(fk_name = a.foreign_key.to_s) && [:string, :text].include?((fk_col = real_model.columns_hash[fk_name])&.type)
|
|
2722
|
+
internal_params[fk_name] = nil if internal_params[fk_name].blank?
|
|
2723
|
+
end
|
|
2724
|
+
end
|
|
2725
|
+
created_obj = model.send(:new, ac_params)
|
|
2700
2726
|
if created_obj.respond_to?(inh_col = model.inheritance_column) && created_obj.send(inh_col) == ''
|
|
2701
2727
|
created_obj.send("#{inh_col}=", model.name)
|
|
2702
2728
|
end
|
|
@@ -2846,14 +2872,14 @@ class Object
|
|
|
2846
2872
|
code << " def #{params_name}\n"
|
|
2847
2873
|
require_txt = model.base_class.name.underscore.tr('/', '_')
|
|
2848
2874
|
is_for_expects = ::ActiveSupport.version >= ::Gem::Version.new('8.0a')
|
|
2849
|
-
|
|
2875
|
+
permits = model._brick_find_permits(model, model._brick_all_fields(true), is_for_expects)
|
|
2850
2876
|
if is_for_expects
|
|
2851
|
-
code << " params.expect(#{require_txt}: #{
|
|
2877
|
+
code << " params.expect(#{require_txt}: #{permits})\n"
|
|
2852
2878
|
self.define_method(params_name) do
|
|
2853
2879
|
params.expect({ model.base_class.name.underscore.tr('/', '_').to_sym => permits })
|
|
2854
2880
|
end
|
|
2855
2881
|
else
|
|
2856
|
-
code << " params.require(:#{require_txt}).permit(#{
|
|
2882
|
+
code << " params.require(:#{require_txt}).permit(#{permits.map(&:inspect).join(', ')})\n"
|
|
2857
2883
|
self.define_method(params_name) do
|
|
2858
2884
|
params.require(model.base_class.name.underscore.tr('/', '_').to_sym).permit(permits)
|
|
2859
2885
|
end
|
data/lib/brick/rails/engine.rb
CHANGED
|
@@ -828,13 +828,13 @@ window.addEventListener(\"popstate\", linkSchemas);
|
|
|
828
828
|
end
|
|
829
829
|
css = +"
|
|
830
830
|
<%
|
|
831
|
-
if @_request.respond_to?(:content_security_policy) && (csp = @_request.content_security_policy)&.directives&.present?
|
|
831
|
+
if @_request.respond_to?(:content_security_policy) && (csp = @_request.content_security_policy)&.directives&.present? %><%
|
|
832
832
|
@_request.env['_is_brick'] = true
|
|
833
833
|
if @_request.respond_to?(:content_security_policy_nonce_directives)
|
|
834
834
|
@_request.content_security_policy_nonce_directives = %w[ script-src ]
|
|
835
835
|
@_request.env['_brick_nonce'] = \" nonce=\\\"#\{@_request.content_security_policy_nonce}\\\"\".html_safe
|
|
836
836
|
%><meta name=\"csp-nonce\" content=\"<%= @_request.content_security_policy_nonce %>\"><%
|
|
837
|
-
end
|
|
837
|
+
end %><%
|
|
838
838
|
if !@_request.respond_to?(:_brick_content_security_policy)
|
|
839
839
|
if csp.instance_variables.exclude?(:@_brick_style_shas)
|
|
840
840
|
csp.instance_variable_set(:@_brick_style_shas, [
|
|
@@ -950,7 +950,10 @@ if (window.brickFontFamily) {
|
|
|
950
950
|
when 'index'
|
|
951
951
|
if Object.const_defined?('DutyFree')
|
|
952
952
|
template_link = "
|
|
953
|
-
<%=
|
|
953
|
+
<%= csv_path = #{@_brick_model._brick_index}_path(format: :csv)
|
|
954
|
+
where_params = params.to_unsafe_h.each_with_object([]) { |v, s| s << \"#\{v.first}=#\{v[1]}\" if v.first.start_with?('__') }.join('&')
|
|
955
|
+
csv_path << \"?#\{where_params}\" unless where_params.blank?
|
|
956
|
+
link_to 'CSV', csv_path %> <a href=\"#\" id=\"sheetsLink\">Sheets</a>
|
|
954
957
|
<div id=\"dropper\" contenteditable=\"true\"></div>
|
|
955
958
|
<input type=\"button\" id=\"btnImport\" value=\"Import\">
|
|
956
959
|
|
|
@@ -1039,7 +1042,7 @@ if (window.brickFontFamily) {
|
|
|
1039
1042
|
}
|
|
1040
1043
|
</script>
|
|
1041
1044
|
<script src=\"https://apis.google.com/js/api.js\"></script>
|
|
1042
|
-
<script async defer src=\"https://accounts.google.com/gsi/client\" id=\"gapiScript\"
|
|
1045
|
+
<script async defer src=\"https://accounts.google.com/gsi/client\" id=\"gapiScript\"></script>
|
|
1043
1046
|
<script<%= @_request.env['_brick_nonce'] %>>
|
|
1044
1047
|
document.getElementById(\"gapiScript\").addEventListener(\"onload\",
|
|
1045
1048
|
function () { // gapiLoaded
|
|
@@ -1072,14 +1075,16 @@ if (window.brickFontFamily) {
|
|
|
1072
1075
|
</head>
|
|
1073
1076
|
<body>
|
|
1074
1077
|
<div id=\"titleBox\"><div id=\"titleSticky\">
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
end
|
|
1078
|
+
<%= if request.respond_to?(:flash)
|
|
1079
|
+
out = +''
|
|
1080
|
+
if (alert)
|
|
1081
|
+
out << \"<p class=\\\"flashAlert\\\">#\{alert}</p>\"
|
|
1082
|
+
end
|
|
1083
|
+
if (notice)
|
|
1084
|
+
out << \"<p class=\\\"flashNotice\\\">#\{notice}</p>\"
|
|
1085
|
+
end
|
|
1086
|
+
out.html_safe
|
|
1087
|
+
end %>#{"
|
|
1083
1088
|
#{schema_options}" if schema_options}
|
|
1084
1089
|
<select id=\"tbl\">#{table_options}</select>
|
|
1085
1090
|
<table id=\"resourceName\"><tr>
|
|
@@ -1111,22 +1116,22 @@ end
|
|
|
1111
1116
|
if description.present? %><span class=\"__brick\"><%=
|
|
1112
1117
|
description %></span><br><%
|
|
1113
1118
|
end
|
|
1114
|
-
# FILTER PARAMETERS
|
|
1119
|
+
# FILTER PARAMETERS %><%
|
|
1115
1120
|
if @_brick_params&.present? %>
|
|
1116
|
-
<% if @_brick_params.length == 1 # %%% Does not yet work with composite keys
|
|
1121
|
+
<% if @_brick_params.length == 1 # %%% Does not yet work with composite keys %><%
|
|
1117
1122
|
k, id = @_brick_params.first
|
|
1118
1123
|
id = id.first if id.is_a?(Array) && id.length == 1
|
|
1119
|
-
origin = (key_parts = k.split('.')).length == 1 ? model : model.reflect_on_association(key_parts.first).klass
|
|
1124
|
+
origin = (key_parts = k.split('.')).length == 1 ? model : model.reflect_on_association(key_parts.first).klass %><%
|
|
1120
1125
|
if (destination_fk = Brick.relations[origin.table_name][:fks].values.find { |fk| fk[:fk] == key_parts.last }) &&
|
|
1121
|
-
(objs = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id))
|
|
1126
|
+
(objs = (destination = origin.reflect_on_association(destination_fk[:assoc_name])&.klass)&.find(id)) %><%
|
|
1122
1127
|
objs = [objs] unless objs.is_a?(Array) %>
|
|
1123
1128
|
<h3 class=\"__brick\">for <% objs.each do |obj| %><%=
|
|
1124
1129
|
link_to \"#{"#\{obj.brick_descrip\} (#\{destination.name\})\""}, send(\"#\{destination._brick_index(:singular)\}_path\".to_sym, id)
|
|
1125
1130
|
%><% end %></h3><%
|
|
1126
|
-
end
|
|
1131
|
+
end %><%
|
|
1127
1132
|
end %>
|
|
1128
1133
|
<span class=\"__brick\">(<%= link_to \"See all #\{model.base_class.name.split('::').last.pluralize}\", #{@_brick_model._brick_index}_path %>)</span>
|
|
1129
|
-
<% end
|
|
1134
|
+
<% end %><%
|
|
1130
1135
|
# COLUMN EXCLUSIONS
|
|
1131
1136
|
if @_brick_excl&.present? %>
|
|
1132
1137
|
<div id=\"exclusions\">Excluded columns:
|
|
@@ -1141,9 +1146,10 @@ end
|
|
|
1141
1146
|
});
|
|
1142
1147
|
});
|
|
1143
1148
|
</script>
|
|
1144
|
-
<% end
|
|
1149
|
+
<% end %><%
|
|
1145
1150
|
# SEARCH BOX
|
|
1146
|
-
if @_brick_es && @_brick_es&.index('r') # Must have at least Elasticsearch Read access
|
|
1151
|
+
if @_brick_es && @_brick_es&.index('r') # Must have at least Elasticsearch Read access
|
|
1152
|
+
%>
|
|
1147
1153
|
<input type=\"text\" id=\"esSearch\" class=\"dimmed\">
|
|
1148
1154
|
<script<%= @_request.env['_brick_nonce'] %>>
|
|
1149
1155
|
var esSearch = document.getElementById(\"esSearch\");
|
|
@@ -1208,7 +1214,7 @@ end
|
|
|
1208
1214
|
</div></div>
|
|
1209
1215
|
#{::Brick::Rails.erd_markup(@_brick_model, prefix) if @_brick_model}
|
|
1210
1216
|
|
|
1211
|
-
|
|
1217
|
+
<%=# Consider getting the name from the association -- hm.first.name -- if a more \"friendly\" alias should be used for a screwy table name
|
|
1212
1218
|
# If the resource is missing, has the user simply created an inappropriately pluralised name for a table?
|
|
1213
1219
|
@#{res_name} ||= if (dym_list = instance_variables.reject do |entry|
|
|
1214
1220
|
entry.to_s.start_with?('@_') ||
|
|
@@ -1340,21 +1346,21 @@ end
|
|
|
1340
1346
|
' class=\"orphan\"' unless ::Brick.relations.key?(r[1])
|
|
1341
1347
|
else
|
|
1342
1348
|
' class=\"dimmed\"'
|
|
1343
|
-
end&.html_safe
|
|
1349
|
+
end&.html_safe %>><%=# Table
|
|
1344
1350
|
if (rowcount = rel&.fetch(:rowcount, nil))
|
|
1345
1351
|
rowcount = (rowcount > 0 ? \" (#\{rowcount})\" : nil)
|
|
1346
1352
|
end
|
|
1347
1353
|
\"#\{r[1]}#\{rowcount}\" %></td>
|
|
1348
1354
|
<td<%= lines = r[2]&.map { |line| \"#\{line.first}:#\{line.last}\" }
|
|
1349
|
-
' class=\"dimmed\"'.html_safe unless r[2]
|
|
1355
|
+
' class=\"dimmed\"'.html_safe unless r[2] %>><%=# Migration
|
|
1350
1356
|
lines&.join('<br>')&.html_safe %></td>
|
|
1351
|
-
<td<%= ' class=\"dimmed\"'.html_safe unless r[3]
|
|
1357
|
+
<td<%= ' class=\"dimmed\"'.html_safe unless r[3] %>><%=# Model
|
|
1352
1358
|
r[3] %></td>
|
|
1353
|
-
<td<%= ' class=\"dimmed\"'.html_safe unless r[4]
|
|
1359
|
+
<td<%= ' class=\"dimmed\"'.html_safe unless r[4] %>><%=# Route
|
|
1354
1360
|
%></td>
|
|
1355
|
-
<td<%= ' class=\"dimmed\"'.html_safe unless r[5]
|
|
1361
|
+
<td<%= ' class=\"dimmed\"'.html_safe unless r[5] %>><%=# Controller
|
|
1356
1362
|
%></td>
|
|
1357
|
-
<td<%= ' class=\"dimmed\"'.html_safe unless r[6]
|
|
1363
|
+
<td<%= ' class=\"dimmed\"'.html_safe unless r[6] %>><%=# Views
|
|
1358
1364
|
%></td>
|
|
1359
1365
|
</tr>
|
|
1360
1366
|
<% end %>
|
|
@@ -1369,14 +1375,14 @@ end
|
|
|
1369
1375
|
#{schema_options}" if schema_options}
|
|
1370
1376
|
<select id=\"tbl\">#{table_options}</select>
|
|
1371
1377
|
<h1>Orphans<%= \" for #\{}\" if false %></h1>
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1378
|
+
<%= @orphans.each_with_object(+'') do |o, s|
|
|
1379
|
+
if (klass = ::Brick.relations[o[0]]&.fetch(:class_name, nil)&.constantize)
|
|
1380
|
+
s << \" via = \\\" (via #\{o[4]})\\\" unless \"#\{o[2].split('.').last.underscore.singularize}_id\" == o[4]
|
|
1375
1381
|
link_to(\"#\{o[0]} #\{o[1]} refers#\{via} to non-existent #\{o[2]} #\{o[3]}#\{\" (in table \\\"#\{o[5]}\\\")\" if o[5]}\",
|
|
1376
|
-
send(\"#\{klass._brick_index(:singular)\}_path\".to_sym, o[1]))
|
|
1377
|
-
<br
|
|
1378
|
-
|
|
1379
|
-
end %>
|
|
1382
|
+
send(\"#\{klass._brick_index(:singular)\}_path\".to_sym, o[1]))
|
|
1383
|
+
s << \"\\n <br>\\n\"
|
|
1384
|
+
end
|
|
1385
|
+
end.html_safe %>
|
|
1380
1386
|
#{script}"
|
|
1381
1387
|
end
|
|
1382
1388
|
|
|
@@ -1416,25 +1422,27 @@ end
|
|
|
1416
1422
|
c23.141-70.188,89.141-120.906,167.063-120.906c97.25,0,176,78.813,176,176C511.828,227.078,404.391,119.641,271.844,119.641z\" />
|
|
1417
1423
|
</svg>
|
|
1418
1424
|
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
end
|
|
1425
|
+
<%= if request.respond_to?(:flash)
|
|
1426
|
+
out = +''
|
|
1427
|
+
if (alert)
|
|
1428
|
+
out << \"<p class=\\\"flashAlert\\\">#\{alert}</p>\"
|
|
1429
|
+
end
|
|
1430
|
+
if (notice)
|
|
1431
|
+
out << \"<p class=\\\"flashNotice\\\">#\{notice}</p>\"
|
|
1432
|
+
end
|
|
1433
|
+
out.html_safe
|
|
1434
|
+
end %>#{"
|
|
1427
1435
|
#{schema_options}" if schema_options}
|
|
1428
1436
|
<select id=\"tbl\">#{table_options}</select>
|
|
1429
1437
|
<table id=\"resourceName\"><tr><td><h1><%= page_title %></h1></td>
|
|
1430
|
-
|
|
1438
|
+
<%= rel = Brick.relations[#{model_name}.table_name]
|
|
1431
1439
|
if (in_app = rel.fetch(:existing, nil)&.fetch(:show, nil))
|
|
1432
1440
|
begin
|
|
1433
|
-
in_app = send(\"#\{in_app}_path\", #{pk.is_a?(String) ? "obj.#{pk}" : '[' + pk.map { |pk_part| "obj.#{pk_part}" }.join(', ') + ']' }) if in_app.is_a?(Symbol)
|
|
1434
|
-
<td
|
|
1435
|
-
|
|
1441
|
+
in_app = send(\"#\{in_app}_path\", #{pk.is_a?(String) ? "obj.#{pk}" : '[' + pk.map { |pk_part| "obj.#{pk_part}" }.join(', ') + ']' }) if in_app.is_a?(Symbol)
|
|
1442
|
+
\"\\n <td>#\{link_to(::Brick::Rails::IN_APP.html_safe, in_app)}</td>\\n\".html_safe
|
|
1443
|
+
rescue ActionController::UrlGenerationError
|
|
1436
1444
|
end
|
|
1437
|
-
end
|
|
1445
|
+
end %><%
|
|
1438
1446
|
|
|
1439
1447
|
if Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) %>
|
|
1440
1448
|
<td><%= link_to_brick(
|
|
@@ -1445,19 +1453,19 @@ end %>#{"
|
|
|
1445
1453
|
end,
|
|
1446
1454
|
title: \"#\{page_title} in Avo\" }
|
|
1447
1455
|
) %></td>
|
|
1448
|
-
<% end
|
|
1456
|
+
<% end %><%=
|
|
1449
1457
|
|
|
1450
1458
|
if Object.const_defined?('ActiveAdmin')
|
|
1451
|
-
ActiveAdmin.application.namespaces.names.
|
|
1452
|
-
<td
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1459
|
+
ActiveAdmin.application.namespaces.names.each_with_object(+'') do |ns, s|
|
|
1460
|
+
s << \"\\n<td>#\{link_to_brick(
|
|
1461
|
+
::Brick::Rails::AA_PNG.html_safe,
|
|
1462
|
+
{ show_proc: Proc.new do |aa_model, relation|
|
|
1463
|
+
path_helper = \"#\{ns}_#\{relation.fetch(:auto_prefixed_schema, nil)}#\{aa_model.model_name.singular_route_key}_path\".to_sym
|
|
1464
|
+
send(path_helper, obj) if respond_to?(path_helper)
|
|
1465
|
+
end,
|
|
1466
|
+
title: \"#\{page_title} in ActiveAdmin\" }
|
|
1467
|
+
)}</td>\\n\"
|
|
1468
|
+
end
|
|
1461
1469
|
end %>
|
|
1462
1470
|
</tr></table>
|
|
1463
1471
|
<%
|
|
@@ -1466,21 +1474,11 @@ if (description = rel&.fetch(:description, nil)) %>
|
|
|
1466
1474
|
end
|
|
1467
1475
|
%><%= link_to \"(See all #\{model_name.pluralize})\", see_all_path, { class: '__brick' } %>
|
|
1468
1476
|
#{::Brick::Rails.erd_markup(@_brick_model, prefix) if @_brick_model}
|
|
1469
|
-
<% if obj
|
|
1470
|
-
# path_options = [obj.#{pk}]
|
|
1471
|
-
# path_options << { '_brick_schema': } if
|
|
1472
|
-
options = {}
|
|
1473
|
-
options[:url] = if obj.new_record?
|
|
1474
|
-
link_to_brick(obj.class, path_only: true) # Properly supports STI, but only works for :new
|
|
1475
|
-
else
|
|
1476
|
-
path_helper = obj.new_record? ? #{model_name}._brick_index : #{model_name}._brick_index(:singular)
|
|
1477
|
-
options[:url] = send(\"#\{path_helper}_path\".to_sym, obj) if ::Brick.config.path_prefix || (path_helper != obj.class.table_name)
|
|
1478
|
-
end
|
|
1479
|
-
%>
|
|
1477
|
+
<% if obj %>
|
|
1480
1478
|
<br><br>
|
|
1481
1479
|
|
|
1482
|
-
|
|
1483
|
-
|
|
1480
|
+
<%=# Write out the mega-form
|
|
1481
|
+
brick_form_with(model: obj, bts: bts, pk: #{pk.inspect}) %>
|
|
1484
1482
|
|
|
1485
1483
|
#{unless args.first == 'new'
|
|
1486
1484
|
# Was: confirm_are_you_sure = ActionView.version < ::Gem::Version.new('7.0') ? "data: { confirm: \"Delete #\{model_name} -- Are you sure?\" }" : "form: { data: { turbo_confirm: \"Delete #\{model_name} -- Are you sure?\" } }"
|
|
@@ -1713,7 +1711,7 @@ flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
|
|
|
1713
1711
|
end
|
|
1714
1712
|
if representation == :grid
|
|
1715
1713
|
inline << "<script<%= @_request.env['_brick_nonce'] %>>
|
|
1716
|
-
|
|
1714
|
+
<%# Make column headers sort when clicked
|
|
1717
1715
|
# %%% Create a smart javascript routine which can do this client-side %>
|
|
1718
1716
|
[... document.getElementsByTagName(\"TH\")].forEach(function (th) {
|
|
1719
1717
|
th.addEventListener(\"click\", function (e) {
|
|
@@ -9,18 +9,19 @@ module Brick::Rails::FormBuilder
|
|
|
9
9
|
def brick_field(method, html_options = {}, val = nil, col = nil,
|
|
10
10
|
bt = nil, bt_class = nil, bt_name = nil, bt_pair = nil)
|
|
11
11
|
model = self.object.class
|
|
12
|
-
col ||= model.columns_hash[method]
|
|
12
|
+
col ||= model.columns_hash[method.to_s]
|
|
13
13
|
out = +'<table><tr><td>'
|
|
14
14
|
html_options[:class] = 'dimmed' unless val
|
|
15
15
|
is_revert = true
|
|
16
16
|
template = instance_variable_get(:@template)
|
|
17
|
+
method_sym = method.to_sym
|
|
17
18
|
if bt
|
|
18
19
|
bt_class ||= bt[1].first.first
|
|
19
20
|
bt_name ||= bt[1].map { |x| x.first.name }.join('/')
|
|
20
21
|
bt_pair ||= bt[1].first
|
|
21
22
|
|
|
22
23
|
html_options[:prompt] = "Select #{bt_name}"
|
|
23
|
-
out << self.select(
|
|
24
|
+
out << self.select(method_sym, bt[3], { value: val || '^^^brick_NULL^^^' }, html_options)
|
|
24
25
|
bt_obj = nil
|
|
25
26
|
begin
|
|
26
27
|
bt_obj = bt_class&.find_by(bt_pair[1] => val)
|
|
@@ -38,8 +39,8 @@ module Brick::Rails::FormBuilder
|
|
|
38
39
|
"<span class=\"orphan\">Orphaned ID: #{val}</span>".html_safe
|
|
39
40
|
end
|
|
40
41
|
out << bt_link if bt_link
|
|
41
|
-
elsif model._brick_monetized_attributes&.include?(method)
|
|
42
|
-
out << self.text_field(
|
|
42
|
+
elsif model._brick_monetized_attributes&.include?(method.to_s)
|
|
43
|
+
out << self.text_field(method_sym, html_options.merge({ value: Money.new(val.to_i).format }))
|
|
43
44
|
else
|
|
44
45
|
col_type = if model.json_column?(col) || val.is_a?(Array)
|
|
45
46
|
:json
|
|
@@ -61,40 +62,40 @@ module Brick::Rails::FormBuilder
|
|
|
61
62
|
out << "<img src=\"#{url}\" title=\"#{val}\">"
|
|
62
63
|
elsif model.respond_to?(:enumerized_attributes) && (opts = (attr = model.enumerized_attributes[method])&.options).present?
|
|
63
64
|
enum_html_options = attr.kind_of?(Enumerize::Multiple) ? html_options.merge({ multiple: true, size: opts.length + 1 }) : html_options
|
|
64
|
-
out << self.select(
|
|
65
|
+
out << self.select(method_sym, [["(No #{method} chosen)", '^^^brick_NULL^^^']] + opts, { value: val || '^^^brick_NULL^^^' }, enum_html_options)
|
|
65
66
|
else
|
|
66
67
|
spit_out_text_field = true
|
|
67
68
|
end
|
|
68
69
|
elsif col_type == :enum
|
|
69
70
|
if col.respond_to?(:limit) && col.limit.present?
|
|
70
|
-
out << self.select(
|
|
71
|
+
out << self.select(method_sym, [["(No #{method} chosen)", '^^^brick_NULL^^^']] + col.limit, { value: val.to_s || '^^^brick_NULL^^^' }, html_options)
|
|
71
72
|
else
|
|
72
73
|
spit_out_text_field = true
|
|
73
74
|
end
|
|
74
75
|
else
|
|
75
76
|
template.instance_variable_set(:@_text_fields_present, true)
|
|
76
|
-
out << self.hidden_field(
|
|
77
|
+
out << self.hidden_field(method_sym, html_options)
|
|
77
78
|
out << "<trix-editor input=\"#{self.field_id(method)}\"></trix-editor>"
|
|
78
79
|
end
|
|
79
80
|
if spit_out_text_field
|
|
80
81
|
# %%% Need to update the max-width with javascript when page width is adjusted?
|
|
81
82
|
html_options.merge!(style: 'min-width: 154px;field-sizing: content;') # max-width: auto;
|
|
82
|
-
out << self.text_field(
|
|
83
|
+
out << self.text_field(method_sym, html_options)
|
|
83
84
|
end
|
|
84
85
|
when :boolean
|
|
85
|
-
out << self.check_box(
|
|
86
|
+
out << self.check_box(method_sym)
|
|
86
87
|
when :integer, :decimal, :float
|
|
87
|
-
if model.respond_to?(:attribute_types) && (enum_type = model.attribute_types[method]).is_a?(ActiveRecord::Enum::EnumType)
|
|
88
|
+
if model.respond_to?(:attribute_types) && (enum_type = model.attribute_types[method.to_s]).is_a?(ActiveRecord::Enum::EnumType)
|
|
88
89
|
opts = enum_type.send(:mapping)&.each_with_object([]) { |v, s| s << [v.first, v.first] } || []
|
|
89
|
-
out << self.select(
|
|
90
|
+
out << self.select(method_sym, [["(No #{method} chosen)", '^^^brick_NULL^^^']] + opts, { value: val || '^^^brick_NULL^^^' }, options)
|
|
90
91
|
else
|
|
91
92
|
digit_pattern = col_type == :integer ? '(?:-|)\d*' : '(?:-|)\d*(?:\.\d*|)'
|
|
92
|
-
# Used to do this for float / decimal: self.number_field
|
|
93
|
-
out << self.text_field(
|
|
93
|
+
# Used to do this for float / decimal: self.number_field method_sym
|
|
94
|
+
out << self.text_field(method_sym, { pattern: digit_pattern, class: 'check-validity' })
|
|
94
95
|
end
|
|
95
96
|
when *DT_PICKERS.keys
|
|
96
97
|
template.instance_variable_set(:@_date_fields_present, true)
|
|
97
|
-
out << self.text_field(
|
|
98
|
+
out << self.text_field(method_sym, { class: DT_PICKERS[col_type] })
|
|
98
99
|
when :uuid
|
|
99
100
|
is_revert = false
|
|
100
101
|
# Postgres naturally uses the +uuid_generate_v4()+ function from the uuid-ossp extension
|
|
@@ -146,7 +147,7 @@ module Brick::Rails::FormBuilder
|
|
|
146
147
|
end
|
|
147
148
|
out << self.hidden_field("_brick_attached_#{method}", value: existing.join(',')) unless existing.blank?
|
|
148
149
|
# Render a "Choose File(s)" input element
|
|
149
|
-
args = [
|
|
150
|
+
args = [method_sym]
|
|
150
151
|
args << { multiple: true } if col&.type == :files
|
|
151
152
|
out << self.file_field(*args)
|
|
152
153
|
when :primary_key
|
|
@@ -163,7 +164,7 @@ module Brick::Rails::FormBuilder
|
|
|
163
164
|
end
|
|
164
165
|
# Because there are so danged many quotes in JSON, escape them specially by converting to backticks.
|
|
165
166
|
# (and previous to this, escape backticks with our own goofy code of ^^br_btick__ )
|
|
166
|
-
out << (json_field = self.hidden_field(
|
|
167
|
+
out << (json_field = self.hidden_field(method_sym, { class: 'jsonpicker', value: val_str&.gsub('`', '^^br_btick__')&.tr('\"', '`')&.html_safe }))
|
|
167
168
|
out << "<div id=\"_br_json_#{self.field_id(method)}\"></div>"
|
|
168
169
|
else
|
|
169
170
|
is_revert = false
|
|
@@ -177,6 +178,7 @@ module Brick::Rails::FormBuilder
|
|
|
177
178
|
end
|
|
178
179
|
out << "</td></tr></table>
|
|
179
180
|
"
|
|
181
|
+
@_brick&.fetch(:fields_rendered, nil)&.<< method.to_s # Track that we've rendered this one
|
|
180
182
|
out.html_safe
|
|
181
183
|
end # brick_field
|
|
182
184
|
end
|