brick 1.0.213 → 1.0.214

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02a0436d0c71a40e1aa3858e4fdf20822f32b02864e621964bce288b8b21ad60
4
- data.tar.gz: 8257218e3c1e9c26842753590e627802842c67dec93891aec7139fd2f31d67c0
3
+ metadata.gz: afed5350a655b7eca570609ff4d15f998ecfe746345c4771b7eb910274df14ae
4
+ data.tar.gz: 45d5cccb07240fe0995bf812dc4b0cc34d21edd1bb0ab3cf212cd255c8a0f6a4
5
5
  SHA512:
6
- metadata.gz: 222b736da74b699a1f352ffff9f087f39048fceaf995dc28733823b4d38271c0bc04ecba506fb6fd027a7f39883009baede3d9c70f81a46dc023f692d6c831e4
7
- data.tar.gz: bdee88e65dad07aa66b6ce9458a44ba8d1ad069b937d5bceae65f020162107336b6d7619aee03ed4c56c25a3e38b4c17ce0352677883426802dfe28ac3c8567a
6
+ metadata.gz: ca420002527953167f6ba1112e43d197bea259bf360c89ff92a01c9753c53da1b7060c15cd021c27e6106c4e77e7d3c30f589c89509ae21c2a2fe69d42e6f079
7
+ data.tar.gz: e6b1fd3745b5c69bfaa9486a4158b7a8efc03c7c43aa884a13f630e9b023e40e0893e1862e6e7fee545049efb46c5b3686cd4f05363d19eb3dfcf0d8f6b1cef3
data/lib/brick/config.rb CHANGED
@@ -429,19 +429,6 @@ module Brick
429
429
  end
430
430
  end
431
431
 
432
- def acts_as_list_cols
433
- @mutex.synchronize { @acts_as_list || {} }
434
- end
435
-
436
- # Get something like:
437
- # { 'on_call_list' => { _brick_default: [:last_name, :first_name] } }
438
- # { 'on_call_list' => { _brick_default: :sequence } }
439
- def acts_as_list_cols=(position_cols)
440
- @mutex.synchronize do
441
- @acts_as_list ||= position_cols
442
- end
443
- end
444
-
445
432
  def metadata_columns
446
433
  @mutex.synchronize { @metadata_columns ||= ['created_at', 'updated_at', 'deleted_at'] }
447
434
  end
@@ -71,15 +71,24 @@ module ActiveRecord
71
71
  end
72
72
 
73
73
  def real_model(params)
74
- if params && (sub_model = params.fetch(type_col = inheritance_column, nil))
75
- sub_model = sub_model.first if sub_model.is_a?(Array) # Support the params style that gets returned from #_brick_querying
74
+ if params && ((sub_name = params.fetch(inheritance_column, nil)).present? ||
75
+ (sub_name = params[name.underscore]&.fetch(inheritance_column, nil)))
76
+ sub_name = sub_name.first if sub_name.is_a?(Array) # Support the params style that gets returned from #_brick_querying
76
77
  # Make sure the chosen model is really the same or a subclass of this model
77
- (possible_model = sub_model.constantize) <= self ? possible_model : self
78
+ return self if sub_name.blank?
79
+
80
+ (possible_model = sub_name.constantize) <= self ? possible_model : self
78
81
  else
79
82
  self
80
83
  end
81
84
  end
82
85
 
86
+ # Accommodate STI
87
+ def real_singular(params)
88
+ real_model = real_model(params)
89
+ [real_model, real_model.name.underscore.split('/').last]
90
+ end
91
+
83
92
  def json_column?(col)
84
93
  col.type == :json || ::Brick.config.json_columns[table_name]&.include?(col.name) ||
85
94
  (
@@ -196,33 +205,6 @@ module ActiveRecord
196
205
  def _brick_monetized_attributes
197
206
  @_brick_monetized_attributes ||= respond_to?(:monetized_attributes) ? monetized_attributes.values : {}
198
207
  end
199
-
200
- # def acts_as_list(aal_cols = nil)
201
- # if aal_cols
202
- # aal_cols = [aal_cols] unless aal_cols.is_a?(Array)
203
- # @acts_as_list_cols = aal_cols.each_with_object([]) do |aal_col, s|
204
- # if column_names.include?(aal_col = aal_col.to_s) && !s.include?(aal_col)
205
- # s << aal_col
206
- # end
207
- # end
208
- # else
209
- # if [:integer, :bigint].include?(columns_hash['position']&.type)
210
- # @acts_as_list_cols = ['position']
211
- # else
212
- # return
213
- # end
214
- # end
215
- # # Override save in order to update neighbours when necessary
216
- # alias _brick_save save
217
- # def save
218
- # # @acts_as_list_cols
219
- # # -1
220
- # @acts_as_list_cols.each do |aal_col|
221
- # binding.pry if (aal_change = changes[aal_col])
222
- # end
223
- # _brick_save
224
- # end
225
- # end
226
208
  end
227
209
 
228
210
  def self.brick_parse_dsl(join_array = nil, prefix = [], translations = {}, is_polymorphic = false, dsl = nil, emit_dsl = false)
@@ -1765,7 +1747,9 @@ class Object
1765
1747
  end
1766
1748
  # Accommodate singular or camel-cased table names such as "order_detail" or "OrderDetails"
1767
1749
  code << " self.table_name = '#{self.table_name = matching}'\n" if (inheritable_name || model_name).underscore.pluralize != matching
1768
- if (inh_col = ::Brick.config.sti_type_column.find { |_k, v| v.include?(matching) }&.first)
1750
+
1751
+ if (inh_col = relation.fetch(:sti_col, nil) ||
1752
+ ::Brick.config.sti_type_column.find { |_k, v| v.include?(matching) }&.first)
1769
1753
  new_model_class.inheritance_column = inh_col
1770
1754
  code << " self.inheritance_column = '#{inh_col}'\n"
1771
1755
  end
@@ -1816,11 +1800,6 @@ class Object
1816
1800
  end
1817
1801
  end
1818
1802
 
1819
- if (sti_col = relation.fetch(:sti_col, nil))
1820
- new_model_class.send(:'inheritance_column=', sti_col)
1821
- code << " self.inheritance_column = #{sti_col.inspect}\n"
1822
- end
1823
-
1824
1803
  unless is_sti
1825
1804
  fks = relation[:fks] || {}
1826
1805
  # Do the bulk of the has_many / belongs_to processing, and store details about HMT so they can be done at the very last
@@ -1902,12 +1881,6 @@ class Object
1902
1881
  end
1903
1882
  end
1904
1883
 
1905
- # Apply any acts_as_list things
1906
- if (aal_col = ::Brick.config.acts_as_list_cols.fetch(matching, nil))
1907
- new_model_class.send(:acts_as_list, aal_col.to_sym)
1908
- code << " acts_as_list :#{aal_col}\n"
1909
- end
1910
-
1911
1884
  # Auto-support Ransack if it's present
1912
1885
  if self.respond_to?(:ransackable_attributes)
1913
1886
  def self.ransackable_attributes(auth_object = nil)
@@ -2480,13 +2453,15 @@ class Object
2480
2453
  code << " @#{plural_table_name}._brick_querying(params, brick_col_names: true)\n"
2481
2454
  code << " end\n"
2482
2455
 
2483
- is_pk_string = nil
2456
+ # ----------------------------------------------------------------------------------
2457
+
2484
2458
  if pk.present?
2485
2459
  code << " def show\n"
2486
2460
  code << " #{find_by_name = "find_#{singular_table_name}"}\n"
2487
2461
  code << " end\n"
2488
2462
  self.define_method :show do
2489
2463
  _schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
2464
+ _, singular_table_name = model.real_singular(params)
2490
2465
  instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
2491
2466
  add_csp_hash("'unsafe-inline'")
2492
2467
  end
@@ -2505,7 +2480,8 @@ class Object
2505
2480
  send(params_name_sym)
2506
2481
  rescue
2507
2482
  end
2508
- new_params ||= model.attribute_names.each_with_object({}) do |a, s|
2483
+ real_model, singular_table_name = model.real_singular(params)
2484
+ new_params ||= real_model.attribute_names.each_with_object({}) do |a, s|
2509
2485
  if (val = params["__#{a}"])
2510
2486
  # val = case new_obj.class.column_for_attribute(a).type
2511
2487
  # when :datetime, :date, :time, :timestamp
@@ -2516,7 +2492,7 @@ class Object
2516
2492
  s[a] = val
2517
2493
  end
2518
2494
  end
2519
- if (new_obj = model.new(new_params)).respond_to?(:serializable_hash)
2495
+ if (new_obj = real_model.new(new_params)).respond_to?(:serializable_hash)
2520
2496
  # Convert any Filename objects with nil into an empty string so that #encode can be called on them
2521
2497
  new_obj.serializable_hash.each do |k, v|
2522
2498
  new_obj.send("#{k}=", ::ActiveStorage::Filename.new('')) if v.is_a?(::ActiveStorage::Filename) && !v.instance_variable_get(:@filename)
@@ -2542,12 +2518,20 @@ class Object
2542
2518
  end
2543
2519
  render json: { result: ::Brick.unexclude_column(table_name, col) }
2544
2520
  else
2545
- created_obj = model.send(:create, send(params_name_sym))
2546
- @_lookup_context.instance_variable_set(:@_brick_model, model)
2521
+ real_model = model.real_model(params)
2522
+ singular_table_name = real_model.name.underscore.split('/').last
2523
+ created_obj = model.send(:new, send(params_name_sym))
2524
+ if created_obj.respond_to?(inh_col = model.inheritance_column) && created_obj.send(inh_col) == ''
2525
+ created_obj.send("#{inh_col}=", model.name)
2526
+ end
2527
+ created_obj.save
2528
+ @_lookup_context.instance_variable_set(:@_brick_model, real_model)
2547
2529
  if created_obj.errors.empty?
2530
+ instance_variable_set("@#{singular_table_name}".to_sym, created_obj)
2548
2531
  index
2549
2532
  render :index
2550
2533
  else # Surface errors to the user in a flash message
2534
+ instance_variable_set("@#{singular_table_name}".to_sym, created_obj)
2551
2535
  flash.now.alert = (created_obj.errors.errors.map { |err| "<b>#{err.attribute}</b> #{err.message}" }.join(', '))
2552
2536
  new
2553
2537
  render :new
@@ -2566,6 +2550,7 @@ class Object
2566
2550
  code << " end\n"
2567
2551
  self.define_method :edit do
2568
2552
  _schema, @_is_show_schema_list = ::Brick.set_db_schema(params)
2553
+ _, singular_table_name = model.real_singular(params)
2569
2554
  instance_variable_set("@#{singular_table_name}".to_sym, find_obj)
2570
2555
  add_csp_hash
2571
2556
  end
@@ -2593,6 +2578,7 @@ class Object
2593
2578
  # return
2594
2579
  end
2595
2580
 
2581
+ _, singular_table_name = model.real_singular(params)
2596
2582
  instance_variable_set("@#{singular_table_name}".to_sym, (obj = find_obj))
2597
2583
  upd_params = send(params_name_sym)
2598
2584
  json_overrides = ::Brick.config.json_columns&.fetch(table_name, nil)
@@ -2679,11 +2665,11 @@ class Object
2679
2665
  if is_need_params
2680
2666
  code << " def #{params_name}\n"
2681
2667
  permits_txt = model._brick_find_permits(model, permits = model._brick_all_fields(true))
2682
- code << " params.require(:#{require_name = model.name.underscore.tr('/', '_')
2668
+ code << " params.require(:#{model.base_class.name.underscore.tr('/', '_')
2683
2669
  }).permit(#{permits_txt.map(&:inspect).join(', ')})\n"
2684
2670
  code << " end\n"
2685
2671
  self.define_method(params_name) do
2686
- params.require(require_name.to_sym).permit(permits)
2672
+ params.require(model.base_class.name.underscore.tr('/', '_').to_sym).permit(permits)
2687
2673
  end
2688
2674
  private params_name
2689
2675
  # Get column names for params from relations[model.table_name][:cols].keys
@@ -2978,7 +2964,8 @@ module Brick
2978
2964
  else
2979
2965
  inverse_table = [primary_table] if polymorphic_class
2980
2966
  assoc_bt = bts[cnstr_name] = { is_bt: true, fk: fk[2], assoc_name: bt_assoc_name, inverse_table: inverse_table || primary_table }
2981
- assoc_bt[:optional] = true if is_optional
2967
+ assoc_bt[:optional] = true if is_optional ||
2968
+ (is_optional.nil? && !relations[fk[1]][:cols][fk[2]][3])
2982
2969
  assoc_bt[:polymorphic] = [polymorphic_class] if polymorphic_class
2983
2970
  end
2984
2971
  if is_class
@@ -809,6 +809,7 @@ h1, h3 {
809
809
  background-repeat: no-repeat;
810
810
  background-size: 100% 100%;
811
811
  width: 28px;
812
+ height: 32px;
812
813
  cursor: pointer;
813
814
  }
814
815
  #mermaidErd {
@@ -942,10 +943,10 @@ table.shadow > tbody > tr {
942
943
  table tbody tr:nth-of-type(even) {
943
944
  background-color: #f3f3f3;
944
945
  }
945
- table tbody tr:nth-of-type(even) .col-sticky {
946
+ table tbody tr:nth-of-type(even) .alternating-gray {
946
947
  background-color: #fff;
947
948
  }
948
- table tbody tr:nth-of-type(odd) .col-sticky {
949
+ table tbody tr:nth-of-type(odd) .alternating-gray {
949
950
  background-color: #f3f3f3;
950
951
  }
951
952
 
@@ -991,6 +992,11 @@ a.big-arrow {
991
992
  background-color: red;
992
993
  color: white;
993
994
  }
995
+ .brick-note {
996
+ font-size: 0.7em;
997
+ color: #A0FFA0;
998
+ max-width: 0;
999
+ }
994
1000
 
995
1001
  #revertTemplate {
996
1002
  display: none;
@@ -1336,8 +1342,7 @@ end
1336
1342
  end}
1337
1343
  %>
1338
1344
 
1339
- #{"<hr><%= link_to(\"New #{new_path_name = "new_#{path_obj_name}_path"
1340
- obj_name}\", #{new_path_name}, { class: '__brick' }) if respond_to?(:#{new_path_name}) %>" unless @_brick_model.is_view?}
1345
+ #{"<hr><%= link_to_brick(model, new: true, class: '__brick') %>" unless @_brick_model.is_view?}
1341
1346
  #{script}
1342
1347
  </body>
1343
1348
  </html>
@@ -1437,7 +1442,7 @@ end
1437
1442
  <head>
1438
1443
  #{css}
1439
1444
  <title><%=
1440
- base_model = (model = (obj = @#{obj_name})&.class).base_class
1445
+ base_model = (model = (obj = @#{obj_name}).class).base_class
1441
1446
  see_all_path = send(\"#\{base_model._brick_index}_path\")
1442
1447
  #{(inh_col = @_brick_model.inheritance_column).present? &&
1443
1448
  " if obj.respond_to?(:#{inh_col}) && (model_name = @#{obj_name}.#{inh_col}) &&
@@ -1445,6 +1450,7 @@ end
1445
1450
  see_all_path << \"?#{inh_col}=#\{model_name}\"
1446
1451
  end
1447
1452
  model_name = base_model.name if model_name.is_a?(Numeric)"}
1453
+ model_name = nil if model_name == ''
1448
1454
  page_title = (\"#\{model_name ||= model.name}: #\{obj&.brick_descrip || controller_name}\")
1449
1455
  %></title>
1450
1456
  </head>
@@ -1510,8 +1516,12 @@ end
1510
1516
  # path_options = [obj.#{pk}]
1511
1517
  # path_options << { '_brick_schema': } if
1512
1518
  options = {}
1513
- path_helper = obj.new_record? ? #{model_name}._brick_index : #{model_name}._brick_index(:singular)
1514
- options[:url] = send(\"#\{path_helper}_path\".to_sym, obj) if ::Brick.config.path_prefix || (path_helper != obj.class.table_name)
1519
+ options[:url] = if obj.new_record?
1520
+ link_to_brick(obj.class, path_only: true) # Properly supports STI, but only works for :new
1521
+ else
1522
+ path_helper = obj.new_record? ? #{model_name}._brick_index : #{model_name}._brick_index(:singular)
1523
+ options[:url] = send(\"#\{path_helper}_path\".to_sym, obj) if ::Brick.config.path_prefix || (path_helper != obj.class.table_name)
1524
+ end
1515
1525
  %>
1516
1526
  <br><br>
1517
1527
 
@@ -6,70 +6,20 @@ module Brick::Rails::FormTags
6
6
  # When a relation is not provided, first see if one exists which matches the controller name or
7
7
  # something has turned up in the instance variables.
8
8
  relation ||= (instance_variable_get("@#{controller_name}".to_sym) || _brick_resource_from_iv)
9
+ klass = relation.klass
9
10
 
10
11
  nfc = Brick.config.sidescroll.fetch(relation.table_name, nil)&.fetch(:num_frozen_columns, nil) ||
11
12
  Brick.config.sidescroll.fetch(:num_frozen_columns, nil) ||
12
13
  0
13
14
 
14
- # HTML for brick_grid
15
- out = +"<div id=\"headerTopContainer\"><table id=\"headerTop\"></table>
16
- "
17
- klass = relation.klass
15
+ out = +''
18
16
  rel = ::Brick.relations&.fetch(relation.table_name, nil)
19
- unless show_header == false
20
- out << " <div id=\"headerTopAddNew\">
21
- <div id=\"headerButtonBox\">
22
- "
23
- unless show_row_count == false
24
- out << " <div id=\"rowCount\"></div>
25
- "
26
- end
27
- unless show_erd_button == false
28
- out << " <div id=\"imgErd\" title=\"Show ERD\"></div>
29
- "
30
- end
31
- if rel && show_in_app_button != false && (in_app = rel.fetch(:existing, nil)&.fetch(:index, nil))
32
- begin
33
- in_app = send("#{in_app}_path") if in_app.is_a?(Symbol)
34
- out << " <td title=\"Show in app\">#{link_to(::Brick::Rails::IN_APP.html_safe, in_app)}</td>
35
- "
36
- rescue ActionController::UrlGenerationError # Avoid snags like "No route matches {:action=>"index", :controller=>"categories/products"}, missing required keys: [:category_id]"
37
- end
38
- end
39
- if show_avo_button != false && Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) && klass.name.exclude?('::')
40
- out << "
41
- <td>#{link_to_brick(
42
- ::Brick::Rails::AVO_SVG.html_safe,
43
- { index_proc: Proc.new do |_avo_model, relation|
44
- path_helper = "resources_#{relation.fetch(:auto_prefixed_schema, nil)}#{klass.model_name.route_key}_path".to_sym
45
- ::Avo.railtie_routes_url_helpers.send(path_helper) if ::Avo.railtie_routes_url_helpers.respond_to?(path_helper)
46
- end,
47
- title: "#{klass.name} in Avo" }
48
- )}</td>
49
- "
50
- end
51
-
52
- if show_aa_button != false && Object.const_defined?('ActiveAdmin')
53
- ActiveAdmin.application.namespaces.names.each do |ns|
54
- out << "
55
- <td>#{link_to_brick(
56
- ::Brick::Rails::AA_PNG.html_safe,
57
- { index_proc: Proc.new do |aa_model, relation|
58
- path_helper = "#{ns}_#{relation.fetch(:auto_prefixed_schema, nil)}#{aa_model.model_name.route_key}_path".to_sym
59
- send(path_helper) if respond_to?(path_helper)
60
- end,
61
- title: "#{klass.name} in ActiveAdmin" }
62
- )}</td>
63
- "
64
- end
65
- end
66
- out << " </div>
67
- </div>
68
- "
17
+ if show_header != false
18
+ out << brick_header(rel, klass, show_row_count, show_erd_button, show_in_app_button, show_avo_button, show_aa_button)
69
19
  end
70
20
 
71
- out << "</div>
72
- <table id=\"#{table_name = relation.table_name.split('.').last}\" class=\"shadow\"#{ " x-num-frozen=\"#{nfc}\"" if nfc.positive? }>
21
+ # HTML for brick_grid
22
+ out << "<table id=\"#{table_name = relation.table_name.split('.').last}\" class=\"shadow\"#{ " x-num-frozen=\"#{nfc}\"" if nfc.positive? }>
73
23
  <thead><tr>"
74
24
  pk = klass.primary_key || []
75
25
  pk = [pk] unless pk.is_a?(Array)
@@ -145,13 +95,13 @@ module Brick::Rails::FormTags
145
95
  row_count = 0
146
96
  relation.each do |obj|
147
97
  out << "<tr>\n"
148
- out << "<td class=\"col-sticky\">#{link_to('⇛', send("#{klass._brick_index(:singular)}_path".to_sym,
98
+ out << "<td class=\"col-sticky alternating-gray\">#{link_to('⇛', send("#{klass._brick_index(:singular)}_path".to_sym,
149
99
  pk.map { |pk_part| obj.send(pk_part.to_sym) }), { class: 'big-arrow' })}</td>\n" if pk.present?
150
100
  sequence.each_with_index do |col_name, idx|
151
101
  val = obj.attributes[col_name]
152
102
  bt = bts[col_name] || composite_bt_names[col_name]
153
103
  out << '<td'
154
- (classes ||= []) << 'col-sticky' if idx < nfc
104
+ (classes ||= []) << 'col-sticky alternating-gray' if idx < nfc
155
105
  (classes ||= []) << 'dimmed' unless cols.key?(col_name) || (cust_col = cust_cols[col_name]) ||
156
106
  (col_name.is_a?(Symbol) && bts.key?(col_name)) # HOT
157
107
  (classes ||= []) << 'right' if val.is_a?(Numeric) && !bt
@@ -255,161 +205,14 @@ module Brick::Rails::FormTags
255
205
  out << '</tr>'
256
206
  row_count += 1
257
207
  end
258
- if rel && (total_row_count = rel.fetch(:rowcount, nil))
259
- total_row_count = total_row_count > row_count ? " (out of #{total_row_count})" : nil
260
- end
261
208
  out << " </tbody>
262
209
  </table>
263
- <script>
264
- var rowCount = document.getElementById(\"rowCount\");
265
- if (rowCount) rowCount.innerHTML = \"#{pluralize(row_count, "row")}#{total_row_count} &nbsp;\";
266
- </script>
267
- "
268
-
269
- # Javascript for brick_grid
270
- (@_brick_javascripts ||= {})[:grid_scripts] = "
271
- var #{table_name}HtColumns;
272
-
273
- // Snag first TR for sticky header
274
- var grid = document.getElementById(\"#{table_name}\");
275
- #{table_name}HtColumns = grid && [grid.getElementsByTagName(\"TR\")[0]];
276
- var headerTop = document.getElementById(\"headerTop\");
277
- var headerCols;
278
- if (grid) {
279
- // COLUMN HEADER AND TABLE CELL HIGHLIGHTING
280
- var gridHighHeader = null,
281
- gridHighCell = null;
282
- grid.addEventListener(\"mouseenter\", gridMove);
283
- grid.addEventListener(\"mousemove\", gridMove);
284
- grid.addEventListener(\"mouseleave\", function (evt) {
285
- if (gridHighCell) gridHighCell.classList.remove(\"highlight\");
286
- gridHighCell = null;
287
- if (gridHighHeader) gridHighHeader.classList.remove(\"highlight\");
288
- gridHighHeader = null;
289
- });
290
- function gridMove(evt) {
291
- var lastHighCell = gridHighCell;
292
- gridHighCell = document.elementFromPoint(evt.x, evt.y);
293
- while (gridHighCell && gridHighCell.tagName !== \"TD\" && gridHighCell.tagName !== \"TH\")
294
- gridHighCell = gridHighCell.parentElement;
295
- if (gridHighCell) {
296
- if (lastHighCell !== gridHighCell) {
297
- gridHighCell.classList.add(\"highlight\");
298
- if (lastHighCell) lastHighCell.classList.remove(\"highlight\");
299
- }
300
- var lastHighHeader = gridHighHeader;
301
- if ((gridHighHeader = headerCols[gridHighCell.cellIndex]) && lastHighHeader !== gridHighHeader) {
302
- if (gridHighHeader) gridHighHeader.classList.add(\"highlight\");
303
- if (lastHighHeader) lastHighHeader.classList.remove(\"highlight\");
304
- }
305
- }
306
- }
307
- // // LESS TOUCHY NAVIGATION BACK OR FORWARD IN HISTORY WHEN USING MOUSE WHEEL
308
- // grid.addEventListener(\"wheel\", function (evt) {
309
- // grid.scrollLeft += evt.deltaX;
310
- // document.body.scrollTop += (evt.deltaY * 0.6);
311
- // evt.preventDefault();
312
- // return false;
313
- // });
314
- }
315
- function setHeaderSizes() {
316
- if (grid.clientWidth > window.outerWidth)
317
- document.getElementById(\"titleBox\").style.width = grid.clientWidth;
318
- // console.log(\"start\");
319
- // See if the headerTop is already populated
320
- // %%% Grab the TRs from headerTop, clear it out, do this stuff, add them back
321
- headerTop.innerHTML = \"\"; // %%% Would love to not have to clear it out like this every time! (Currently doing this to support resize events.)
322
- var isEmpty = headerTop.childElementCount === 0;
323
- var numFixed = parseInt(grid.getAttribute(\"x-num-frozen\")) || 0;
324
- var fixedColLefts = [0];
325
-
326
- // Set up proper sizings of sticky column header
327
- var node;
328
- for (var j = 0; j < #{table_name}HtColumns.length; ++j) {
329
- var row = #{table_name}HtColumns[j];
330
- var tr = isEmpty ? document.createElement(\"TR\") : headerTop.childNodes[j];
331
- tr.innerHTML = row.innerHTML.trim();
332
- var curLeft = 0.0;
333
- // Match up widths from the original column headers
334
- for (var i = 0; i < row.childNodes.length; ++i) {
335
- node = row.childNodes[i];
336
- if (node.nodeType === 1) {
337
- var th = tr.childNodes[i];
338
- th.style.minWidth = th.style.maxWidth = getComputedStyle(node).width;
339
- // Add \"left: __px\" style to the fixed-width column THs
340
- if (i <= numFixed) {
341
- th.style.position = \"sticky\";
342
- th.style.backgroundColor = \"#008061\";
343
- th.style.zIndex = \"1\";
344
- th.style.left = curLeft + \"px\";
345
- fixedColLefts.push(curLeft += node.clientWidth);
346
- }
347
- if (#{pk&.present? ? 'i > 0' : 'true'}) {
348
- // Add <span> at the end
349
- var span = document.createElement(\"SPAN\");
350
- span.className = \"exclude\";
351
- span.innerHTML = \"X\";
352
- span.addEventListener(\"click\", function (e) {
353
- e.stopPropagation();
354
- doFetch(\"POST\", {_brick_exclude: this.parentElement.getAttribute(\"x-order\")});
355
- });
356
- th.appendChild(span);
357
- }
358
- }
359
- }
360
- headerCols = tr.childNodes;
361
- if (isEmpty) headerTop.appendChild(tr);
362
- }
363
- // Add \"left: __px\" style to all fixed-width column TDs
364
- [...grid.children[1].children].forEach(function (row) {
365
- for (var j = 1; j <= numFixed; ++j) {
366
- row.children[j].style.left = fixedColLefts[j] + 'px';
367
- }
368
- });
369
- grid.style.marginTop = \"-\" + getComputedStyle(headerTop).height;
370
- // console.log(\"end\");
371
- }
372
-
373
- if (headerTop) {
374
- onImagesLoaded(function() {
375
- setHeaderSizes();
376
- });
377
- window.addEventListener(\"resize\", function(event) {
378
- setHeaderSizes();
379
- }, true);#{
380
- if !klass.is_view? && respond_to?(new_path_name = "new_#{klass._brick_index(:singular)}_path")
381
- "
382
- var headerButtonBox = document.getElementById(\"headerButtonBox\");
383
- if (headerButtonBox) {
384
- var addNew = document.createElement(\"A\");
385
- addNew.id = \"addNew\";
386
- addNew.href = \"#{send(new_path_name)}\";
387
- addNew.title = \"New #{table_name.singularize}\";
388
- addNew.innerHTML = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"#fff\" d=\"M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z\"/></svg>';
389
- headerButtonBox.append(addNew);
390
- }
391
- "
392
- end}
393
- }
394
-
395
- function onImagesLoaded(event) {
396
- var images = document.getElementsByTagName(\"IMG\");
397
- var numLoaded = images.length;
398
- for (var i = 0; i < images.length; ++i) {
399
- if (images[i].complete)
400
- --numLoaded;
401
- else {
402
- images[i].addEventListener(\"load\", function() {
403
- if (--numLoaded <= 0)
404
- event();
405
- });
406
- }
407
- }
408
- if (numLoaded <= 0)
409
- event();
410
- }
411
210
  "
211
+ if rel && (total_row_count = rel.fetch(:rowcount, nil))
212
+ total_row_count = total_row_count > row_count ? " (out of #{total_row_count})" : nil
213
+ end
412
214
 
215
+ set_grid_javascript(klass, pk, show_new_button, row_count, total_row_count)
413
216
  out.html_safe
414
217
  end # brick_grid
415
218
 
@@ -418,7 +221,7 @@ function onImagesLoaded(event) {
418
221
  def brick_form_for(obj, options = {}, model = obj.class, bts = {}, pk = (obj.class.primary_key || []))
419
222
  pk = [pk] unless pk.is_a?(Array)
420
223
  pk.map!(&:to_s)
421
- form_for(obj.becomes(model), options) do |f|
224
+ form_for(obj.becomes(model.base_class), options) do |f|
422
225
  out = +'<table class="shadow">'
423
226
  has_fields = false
424
227
  # If it's a new record, set any default polymorphic types
@@ -525,28 +328,37 @@ function onImagesLoaded(event) {
525
328
 
526
329
  # ------------------------------------------
527
330
  # Our cool N:M checkbox constellation editor
528
- def brick_constellation(relation = nil, options = {}, x_axis: nil, y_axis: nil, bt_descrip: nil, bts: {})
331
+ def brick_constellation(relation = nil, options = {}, x_axis: nil, y_axis: nil, bt_descrip: nil, bts: {},
332
+ show_header: nil, show_erd_button: nil, show_in_app_button: nil, show_new_button: nil, show_avo_button: nil, show_aa_button: nil)
333
+ relation ||= (instance_variable_get("@#{controller_name}".to_sym) || _brick_resource_from_iv)
334
+ klass = relation.klass
529
335
  x_axis, x_list, y_axis, y_list, existing = _n_m_prep(relation, x_axis, y_axis)
530
336
 
337
+ out = +''
338
+ rel = ::Brick.relations&.fetch(relation.table_name, nil)
339
+ if show_header != false
340
+ out << brick_header(rel, klass, false, show_erd_button, show_in_app_button, show_avo_button, show_aa_button)
341
+ end
342
+
531
343
  # HTML for constellation
532
344
  prefix = options[:prefix]
533
- out = +"<form action=\"#{"#{prefix}/" if prefix}brick_constellation\">
345
+ out << "<form action=\"#{"#{prefix}/" if prefix}brick_constellation\">
534
346
  <table id=\"#{table_name = relation.table_name.split('.').last}\" class=\"shadow\">
535
- <thead><tr><td></td>
536
- "
347
+ <thead><tr><td class=\"brick-note\">Checkbox changes are saved immediately</td>"
537
348
  # Header row with X axis values
349
+ # (In order for grid highlighting to function, these TH elements must have no whitespace between them.
350
+ # In this way the Javascript headerCols array will be set properly.
538
351
  x_list.each do |x_item|
539
- out << " <th>#{x_item.first}</th>
540
- "
352
+ out << "<th>#{x_item.first}</th>"
541
353
  end
542
- out << " </tr></thead>
354
+ out << "</tr></thead>
543
355
  <tbody>
544
356
  "
545
- obj_path = "#{relation.klass._brick_index(:singular)}_path".to_sym
357
+ obj_path = "#{klass._brick_index(:singular)}_path".to_sym
546
358
  link_arrow = link_to('⇛', send(obj_path, '____'), { class: 'big-arrow' })
547
- pk_as_array = relation.klass._pk_as_array
359
+ pk_as_array = klass._pk_as_array
548
360
  y_list.each do |y_item|
549
- out << " <tr><th>#{y_item.first}</th>
361
+ out << " <tr><th class=\"col-sticky\">#{y_item.first}</th>
550
362
  "
551
363
  x_list.each do |x_item|
552
364
  checked = existing.find { |e| e[1] == x_item.last && e[2] == y_item.last }
@@ -570,7 +382,7 @@ function onImagesLoaded(event) {
570
382
  _this = this;
571
383
  if (this.checked) {
572
384
  var ids = this.value.split(\"_\");
573
- doFetch(\"POST\", {modelName: \"#{relation.klass.name}\",
385
+ doFetch(\"POST\", {modelName: \"#{klass.name}\",
574
386
  args: [#{x_axis[1].inspect}, ids[0], #{y_axis[1].inspect}, ids[1]],
575
387
  _brick_action: \"/#{prefix}brick_associate\"},
576
388
  function (p) { // If it returns successfully, create an <a> element
@@ -586,7 +398,7 @@ function onImagesLoaded(event) {
586
398
  }
587
399
  );
588
400
  } else if (nextSib = this.nextElementSibling) {
589
- doFetch(\"DELETE\", {modelName: \"#{relation.klass.name}\",
401
+ doFetch(\"DELETE\", {modelName: \"#{klass.name}\",
590
402
  id: this.getAttribute(\"x-id\"),
591
403
  _brick_action: \"/#{prefix}brick_associate\"},
592
404
  function (p) { // If it returns successfully, remove the an <a> element
@@ -599,6 +411,7 @@ function onImagesLoaded(event) {
599
411
  </script>
600
412
  </form>
601
413
  "
414
+ set_grid_javascript(klass, pk_as_array, false)
602
415
  out.html_safe
603
416
  end # brick_constellation
604
417
 
@@ -606,7 +419,9 @@ function onImagesLoaded(event) {
606
419
  # Our cool N:M bezier visualisation
607
420
  # (...... work in progress .......)
608
421
  def brick_bezier(relation = nil, options = {}, x_axis: nil, y_axis: nil, bt_descrip: nil, bts: {})
422
+ relation ||= (instance_variable_get("@#{controller_name}".to_sym) || _brick_resource_from_iv)
609
423
  x_axis, x_list, y_axis, y_list, existing = _n_m_prep(relation, x_axis, y_axis)
424
+ rel = ::Brick.relations&.fetch(relation.table_name, nil)
610
425
  # HTML for constellation
611
426
  # X axis (List on left side)
612
427
  out = +"<table id=\"#{x_axis.first}\" class=\"shadow\">
@@ -629,13 +444,222 @@ function onImagesLoaded(event) {
629
444
  out.html_safe
630
445
  end # brick_bezier
631
446
 
447
+ # ---------------------------------------------------------------------------------------------------------
448
+ def brick_header(rel, klass, show_row_count, show_erd_button, show_in_app_button, show_avo_button, show_aa_button)
449
+ out = +"<div id=\"headerTopContainer\"><table id=\"headerTop\"></table>
450
+ <div id=\"headerTopAddNew\">
451
+ <div id=\"headerButtonBox\">
452
+ "
453
+ unless show_row_count == false
454
+ out << " <div id=\"rowCount\"></div>
455
+ "
456
+ end
457
+ unless show_erd_button == false
458
+ out << " <div id=\"imgErd\" title=\"Show ERD\"></div>
459
+ "
460
+ end
461
+ if rel && show_in_app_button != false && (in_app = rel.fetch(:existing, nil)&.fetch(:index, nil))
462
+ begin
463
+ in_app = send("#{in_app}_path") if in_app.is_a?(Symbol)
464
+ out << " <td title=\"Show in app\">#{link_to(::Brick::Rails::IN_APP.html_safe, in_app)}</td>
465
+ "
466
+ rescue ActionController::UrlGenerationError # Avoid snags like "No route matches {:action=>"index", :controller=>"categories/products"}, missing required keys: [:category_id]"
467
+ end
468
+ end
469
+ if show_avo_button != false && Object.const_defined?('Avo') && ::Avo.respond_to?(:railtie_namespace) && klass.name.exclude?('::')
470
+ out << "
471
+ <td>#{link_to_brick(
472
+ ::Brick::Rails::AVO_SVG.html_safe,
473
+ { index_proc: Proc.new do |_avo_model, relation|
474
+ path_helper = "resources_#{relation.fetch(:auto_prefixed_schema, nil)}#{klass.model_name.route_key}_path".to_sym
475
+ ::Avo.railtie_routes_url_helpers.send(path_helper) if ::Avo.railtie_routes_url_helpers.respond_to?(path_helper)
476
+ end,
477
+ title: "#{klass.name} in Avo" }
478
+ )}</td>
479
+ "
480
+ end
481
+
482
+ if show_aa_button != false && Object.const_defined?('ActiveAdmin')
483
+ ActiveAdmin.application.namespaces.names.each do |ns|
484
+ out << "
485
+ <td>#{link_to_brick(
486
+ ::Brick::Rails::AA_PNG.html_safe,
487
+ { index_proc: Proc.new do |aa_model, relation|
488
+ path_helper = "#{ns}_#{relation.fetch(:auto_prefixed_schema, nil)}#{aa_model.model_name.route_key}_path".to_sym
489
+ send(path_helper) if respond_to?(path_helper)
490
+ end,
491
+ title: "#{rel[:class_name]} in ActiveAdmin" }
492
+ )}</td>
493
+ "
494
+ end
495
+ end
496
+ out << " </div>
497
+ </div>
498
+ </div>
499
+ "
500
+ out
501
+ end # brick_header
502
+
503
+ # -----------------------------------------------------------------------------------------------
504
+ def set_grid_javascript(klass, pk, show_new_button = nil, row_count = nil, total_row_count = nil)
505
+ table_name = klass.table_name.split('.').last
506
+
507
+ # Javascript for brick_grid and brick_constellation
508
+ grid_scripts = (@_brick_javascripts ||= {})[:grid_scripts] = +''
509
+
510
+ grid_scripts << "
511
+ // Plunk the row count in now that we know it
512
+ var rowCount = document.getElementById(\"rowCount\");
513
+ if (rowCount) rowCount.innerHTML = \"#{pluralize(row_count, "row")}#{total_row_count} &nbsp;\";
514
+ var #{table_name}HtColumns;
515
+ " unless row_count.nil?
516
+
517
+ grid_scripts << "
518
+ // Snag first TR for sticky header
519
+ var grid = document.getElementById(\"#{table_name}\");
520
+ #{table_name}HtColumns = grid && [grid.getElementsByTagName(\"TR\")[0]];
521
+ var headerTop = document.getElementById(\"headerTop\");
522
+ var headerCols;
523
+ if (grid) {
524
+ // COLUMN HEADER AND TABLE CELL HIGHLIGHTING
525
+ var gridHighHeader = null,
526
+ gridHighCell = null;
527
+ grid.addEventListener(\"mouseenter\", gridMove);
528
+ grid.addEventListener(\"mousemove\", gridMove);
529
+ grid.addEventListener(\"mouseleave\", function (evt) {
530
+ if (gridHighCell) gridHighCell.classList.remove(\"highlight\");
531
+ gridHighCell = null;
532
+ if (gridHighHeader) gridHighHeader.classList.remove(\"highlight\");
533
+ gridHighHeader = null;
534
+ });
535
+ function gridMove(evt) {
536
+ var lastHighCell = gridHighCell;
537
+ gridHighCell = document.elementFromPoint(evt.x, evt.y);
538
+ while (gridHighCell && gridHighCell.tagName !== \"TD\" && gridHighCell.tagName !== \"TH\")
539
+ gridHighCell = gridHighCell.parentElement;
540
+ if (gridHighCell) {
541
+ if (lastHighCell !== gridHighCell) {
542
+ gridHighCell.classList.add(\"highlight\");
543
+ if (lastHighCell) lastHighCell.classList.remove(\"highlight\");
544
+ }
545
+ var lastHighHeader = gridHighHeader;
546
+ if ((gridHighHeader = headerCols[gridHighCell.cellIndex]) && lastHighHeader !== gridHighHeader) {
547
+ if (gridHighHeader) gridHighHeader.classList.add(\"highlight\");
548
+ if (lastHighHeader) lastHighHeader.classList.remove(\"highlight\");
549
+ }
550
+ }
551
+ }
552
+ // // Less touchy navigation back or forward in history when using mouse wheel
553
+ // grid.addEventListener(\"wheel\", function (evt) {
554
+ // grid.scrollLeft += evt.deltaX;
555
+ // document.body.scrollTop += (evt.deltaY * 0.6);
556
+ // evt.preventDefault();
557
+ // return false;
558
+ // });
559
+ }
560
+ function setHeaderSizes() {
561
+ if (grid.clientWidth > window.outerWidth)
562
+ document.getElementById(\"titleBox\").style.width = grid.clientWidth;
563
+ // console.log(\"start\");
564
+ // See if the headerTop is already populated
565
+ // %%% Grab the TRs from headerTop, clear it out, do this stuff, add them back
566
+ headerTop.innerHTML = \"\"; // %%% Would love to not have to clear it out like this every time! (Currently doing this to support resize events.)
567
+ var isEmpty = headerTop.childElementCount === 0;
568
+ var numFixed = parseInt(grid.getAttribute(\"x-num-frozen\")) || 0;
569
+ var fixedColLefts = [0];
570
+
571
+ // Set up proper sizings of sticky column header
572
+ var node;
573
+ for (var j = 0; j < #{table_name}HtColumns.length; ++j) {
574
+ var row = #{table_name}HtColumns[j];
575
+ var tr = isEmpty ? document.createElement(\"TR\") : headerTop.childNodes[j];
576
+ tr.innerHTML = row.innerHTML.trim();
577
+ var curLeft = 0.0;
578
+ // Match up widths from the original column headers
579
+ for (var i = 0; i < row.childNodes.length; ++i) {
580
+ node = row.childNodes[i];
581
+ if (node.nodeType === 1) {
582
+ var th = tr.childNodes[i];
583
+ th.style.minWidth = th.style.maxWidth = getComputedStyle(node).width;
584
+ // Add \"left: __px\" style to the fixed-width column THs
585
+ if (i <= numFixed) {
586
+ th.style.position = \"sticky\";
587
+ th.style.backgroundColor = \"#008061\";
588
+ th.style.zIndex = \"1\";
589
+ th.style.left = curLeft + \"px\";
590
+ fixedColLefts.push(curLeft += node.clientWidth);
591
+ }
592
+ if (#{pk&.present? ? 'i > 0' : 'true'}) {
593
+ // Add <span> at the end
594
+ var span = document.createElement(\"SPAN\");
595
+ span.className = \"exclude\";
596
+ span.innerHTML = \"X\";
597
+ span.addEventListener(\"click\", function (e) {
598
+ e.stopPropagation();
599
+ doFetch(\"POST\", {_brick_exclude: this.parentElement.getAttribute(\"x-order\")});
600
+ });
601
+ th.appendChild(span);
602
+ }
603
+ }
604
+ }
605
+ headerCols = tr.childNodes;
606
+ if (isEmpty) headerTop.appendChild(tr);
607
+ }
608
+ // Add \"left: __px\" style to all fixed-width column TDs
609
+ [...grid.children[1].children].forEach(function (row) {
610
+ for (var j = 1; j <= numFixed; ++j) {
611
+ row.children[j].style.left = fixedColLefts[j] + 'px';
612
+ }
613
+ });
614
+ grid.style.marginTop = \"-\" + getComputedStyle(headerTop).height;
615
+ // console.log(\"end\");
616
+ }
617
+
618
+ if (headerTop) {
619
+ onImagesLoaded(function() {
620
+ setHeaderSizes();
621
+ });
622
+ window.addEventListener(\"resize\", function(event) {
623
+ setHeaderSizes();
624
+ }, true);#{
625
+ "
626
+ var headerButtonBox = document.getElementById(\"headerButtonBox\");
627
+ if (headerButtonBox) {
628
+ var addNew = document.createElement(\"A\");
629
+ addNew.id = \"addNew\";
630
+ addNew.href = \"#{link_to_brick(klass, new: true, path_only: true)}\";
631
+ addNew.title = \"New #{table_name.singularize}\";
632
+ addNew.innerHTML = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"#fff\" d=\"M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z\"/></svg>';
633
+ headerButtonBox.append(addNew);
634
+ }
635
+ " unless klass.is_view? || show_new_button == false
636
+ }
637
+ }
638
+
639
+ function onImagesLoaded(event) {
640
+ var images = document.getElementsByTagName(\"IMG\");
641
+ var numLoaded = images.length;
642
+ for (var i = 0; i < images.length; ++i) {
643
+ if (images[i].complete)
644
+ --numLoaded;
645
+ else {
646
+ images[i].addEventListener(\"load\", function() {
647
+ if (--numLoaded <= 0)
648
+ event();
649
+ });
650
+ }
651
+ }
652
+ if (numLoaded <= 0)
653
+ event();
654
+ }
655
+ "
656
+ end
657
+
658
+ # -------------------------------------
632
659
  def _n_m_prep(relation, x_axis, y_axis)
633
- relation ||= (instance_variable_get("@#{controller_name}".to_sym) || _brick_resource_from_iv)
634
660
  # Just find the first two BT things at this point
635
661
 
636
662
  klass = relation.klass
637
- rel = ::Brick.relations&.fetch(relation.table_name, nil)
638
- # fk_assocs = rel[:fks].map { |k, fk| [fk[:assoc_name], fk[:fk]] }
639
663
  fk_assocs = klass.reflect_on_all_associations.each_with_object([]) do |assoc, s|
640
664
  s << [assoc.name.to_s, assoc.foreign_key, assoc.klass] if assoc.belongs_to?
641
665
  end
@@ -690,8 +714,10 @@ function onImagesLoaded(event) {
690
714
  kwargs[:visited] = {}
691
715
  end
692
716
 
693
- text = ((args.first.is_a?(String) || args.first.is_a?(Proc)) && args.shift) || args[1]
694
- text = text.call if text.is_a?(Proc)
717
+ unless (is_path_only = kwargs.delete(:path_only))
718
+ text = ((args.first.is_a?(String) || args.first.is_a?(Proc)) && args.shift) || args[1]
719
+ text = text.call if text.is_a?(Proc)
720
+ end
695
721
  klass_or_obj = ((args.first.is_a?(ActiveRecord::Relation) ||
696
722
  args.first.is_a?(ActiveRecord::Base) ||
697
723
  args.first.is_a?(Class)) &&
@@ -739,6 +765,8 @@ function onImagesLoaded(event) {
739
765
  filter_parts << "#{whr.first}=#{whr.last}" if whr.last && !whr.last.is_a?(Array)
740
766
  end
741
767
  klass_or_obj = klass_or_obj.klass
768
+ end
769
+ if klass_or_obj.is_a?(Class) && klass_or_obj <= ActiveRecord::Base
742
770
  type_col = klass_or_obj.inheritance_column
743
771
  if klass_or_obj.column_names.include?(type_col) && klass_or_obj.name != klass_or_obj.base_class.name
744
772
  filter_parts << "#{type_col}=#{klass_or_obj.name}"
@@ -750,11 +778,22 @@ function onImagesLoaded(event) {
750
778
  relation = ::Brick.relations.fetch(rel_name || klass.table_name, nil)
751
779
  if (klass_or_obj&.is_a?(Class) && klass_or_obj < ActiveRecord::Base) ||
752
780
  (klass_or_obj&.is_a?(ActiveRecord::Base) && klass_or_obj.new_record? && (klass_or_obj = klass_or_obj.class))
753
- path = (proc = kwargs[:index_proc]) ? proc.call(klass_or_obj, relation) : "#{app_routes.path_for(controller: klass_or_obj.base_class._brick_index(nil, '/', relation, true), action: :index)}#{filter}"
754
- lt_args = [text || "Index for #{klass_or_obj.name.pluralize}", path]
781
+ if kwargs.delete(:new)
782
+ path = (proc = kwargs[:new_proc]) ? proc.call(klass_or_obj, relation) : "#{app_routes.path_for(controller: klass_or_obj.base_class._brick_index(:singular, '/', relation, true), action: :new)}#{filter}"
783
+ return path if is_path_only
784
+
785
+ lt_args = [text || "New #{klass_or_obj.name}", path]
786
+ else
787
+ path = (proc = kwargs[:index_proc]) ? proc.call(klass_or_obj, relation) : "#{app_routes.path_for(controller: klass_or_obj.base_class._brick_index(nil, '/', relation, true), action: :index)}#{filter}"
788
+ return path if is_path_only
789
+
790
+ lt_args = [text || "Index for #{klass_or_obj.name.pluralize}", path]
791
+ end
755
792
  else
756
793
  # If there are multiple incoming parameters then last one is probably the actual ID, and first few might be some nested tree of stuff leading up to it
757
794
  path = (proc = kwargs[:show_proc]) ? proc.call(klass_or_obj, relation) : "#{app_routes.path_for(controller: klass_or_obj.class.base_class._brick_index(nil, '/', relation, true), action: :show, id: klass_or_obj)}#{filter}"
795
+ return path if is_path_only
796
+
758
797
  lt_args = [text || "Show this #{klass_or_obj.class.name}", path]
759
798
  end
760
799
  kwargs.delete(:visited)
@@ -341,7 +341,7 @@ ORDER BY 1, 2, c.internal_column_id, acc.position"
341
341
  fk[4].downcase! if fk[4] =~ /^[A-Z0-9_]+$/
342
342
  fk[2] = connection.send(:oracle_downcase, fk[2])
343
343
  end
344
- ::Brick._add_bt_and_hm(fk, relations)
344
+ ::Brick._add_bt_and_hm(fk, relations, nil, nil)
345
345
  end
346
346
  kcus = nil # Allow this large item to be garbage collected
347
347
  end
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 213
8
+ TINY = 214
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brick
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.213
4
+ version: 1.0.214
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-01 00:00:00.000000000 Z
11
+ date: 2024-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord