brick 1.0.213 → 1.0.214

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: 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