brick 1.0.52 → 1.0.53

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: e3d0b398d1d3926fa3e59281c976fe2f7a54bfc16de4f99683928ce71d7ace97
4
- data.tar.gz: 344c0de3e8691583e9a940ee451ad29015d46b0cbc55756d3b36e10d9ce27edb
3
+ metadata.gz: 737256fad5c987fa2ac603cf3708da959127a33ab9b27d164ceff858b71987b9
4
+ data.tar.gz: 144352db7686d19d9c330887069287da88de456276cc17aaeeaeb3c1de7a3281
5
5
  SHA512:
6
- metadata.gz: e0cff4e30c30d33dd13bd5a6a4a888d52e0552fc692369c42a53846da00e9ce677ab48ba840ef1396728d339984e5f7ff35d9ce33ea60f8421b9fa19edc14575
7
- data.tar.gz: 5971fcc802dd1732f71d3bcd015e4b616f7775028a10205c7e4b9b1fa41d13c0318f581c966c223e9a0661b8b9fa52e1197ae78c007144e93ec96de61b084663
6
+ metadata.gz: 83ec370e06c18bf9d62ec3ed445daf78dc5cbff825a85ff017cc7b814efb62f86e68022f7577734dd01ddf7e2f74b4b59de4b40b9c07656e83d0859ba6a4333d
7
+ data.tar.gz: 9106373ca7878dcc75c596f1fa44d420980c50cb09f5b63a1110d4e02dc63f02dafe3d1bc0d4de38a75d5678d964e3b8f12a720a722d2f593934e2f6be97f818
@@ -1116,6 +1116,11 @@ class Object
1116
1116
  if namespace && (idx = lookup_context.prefixes.index(table_name))
1117
1117
  lookup_context.prefixes[idx] = "#{namespace.name.underscore}/#{lookup_context.prefixes[idx]}"
1118
1118
  end
1119
+ @_brick_excl = session[:_brick_exclude]&.split(',')&.each_with_object([]) do |excl, s|
1120
+ if (excl_parts = excl.split('.')).first == table_name
1121
+ s << excl_parts.last
1122
+ end
1123
+ end
1119
1124
  @_brick_bt_descrip = model._br_bt_descrip
1120
1125
  @_brick_hm_counts = model._br_hm_counts
1121
1126
  @_brick_join_array = join_array
@@ -1156,8 +1161,20 @@ class Object
1156
1161
  code << " end\n"
1157
1162
  self.define_method :create do
1158
1163
  ::Brick.set_db_schema(params)
1159
- instance_variable_set("@#{singular_table_name}".to_sym,
1160
- model.send(:create, send(params_name_sym)))
1164
+ if (is_json = request.content_type == 'application/json') && (col = params['_brick_exclude'])
1165
+ session[:_brick_exclude] = ((session[:_brick_exclude]&.split(',') || []) + ["#{table_name}.#{col}"]).join(',')
1166
+ render json: { result: ::Brick.exclude_column(table_name, col) }
1167
+ elsif is_json && (col = params['_brick_unexclude'])
1168
+ if (excls = ((session[:_brick_exclude]&.split(',') || []) - ["#{table_name}.#{col}"]).join(',')).empty?
1169
+ session.delete(:_brick_exclude)
1170
+ else
1171
+ session[:_brick_exclude] = excls
1172
+ end
1173
+ render json: { result: ::Brick.unexclude_column(table_name, col) }
1174
+ else
1175
+ instance_variable_set("@#{singular_table_name}".to_sym,
1176
+ model.send(:create, send(params_name_sym)))
1177
+ end
1161
1178
  end
1162
1179
 
1163
1180
  if pk_col
@@ -132,23 +132,24 @@ module Brick
132
132
  end
133
133
  case args.first
134
134
  when 'index'
135
- hms_columns << if hm_assoc.macro == :has_many
136
- if hm_fk_name
137
- set_ct = if skip_klass_hms.key?(assoc_name.to_sym)
138
- 'nil'
139
- else
140
- # Postgres column names are limited to 63 characters
141
- attrib_name = "_br_#{assoc_name}_ct"[0..62]
142
- "#{obj_name}.#{attrib_name} || 0"
143
- end
144
- "#{hm_assoc.name}: [#{assoc_name.inspect}, #{set_ct}, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}]"
145
- else # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
146
- "#{hm_assoc.name}: [#{assoc_name.inspect}]"
147
- end
148
- else # has_one
149
- # 0..62 because Postgres column names are limited to 63 characters
150
- "#{hm_assoc.name}: [#{assoc_name.inspect}, nil, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}]"
135
+ hm_entry = +"'#{hm_assoc.name}' => [#{assoc_name.inspect}"
136
+ hm_entry << if hm_assoc.macro == :has_many
137
+ if hm_fk_name # %%% Can remove this check when multiple foreign keys to same destination becomes bulletproof
138
+ set_ct = if skip_klass_hms.key?(assoc_name.to_sym)
139
+ 'nil'
140
+ else
141
+ # Postgres column names are limited to 63 characters
142
+ "#{obj_name}.#{"_br_#{assoc_name}_ct"[0..62]} || 0"
143
+ end
144
+ ", #{set_ct}, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}"
151
145
  end
146
+ else # has_one
147
+ # 0..62 because Postgres column names are limited to 63 characters
148
+ ", nil, #{path_keys(hm_assoc, hm_fk_name, obj_name, pk)}"
149
+ end
150
+ hm_entry << ']'
151
+ puts hm_entry
152
+ hms_columns << hm_entry
152
153
  when 'show', 'update'
153
154
  hm_stuff << if hm_fk_name
154
155
  "<%= link_to '#{assoc_name}', #{hm_assoc.klass.name.underscore.tr('/', '_').pluralize}_path({ #{path_keys(hm_assoc, hm_fk_name, "@#{obj_name}", pk)} }) %>\n"
@@ -174,6 +175,9 @@ module Brick
174
175
  end.html_safe
175
176
  table_options << '<option value="brick_orphans">(Orphans)</option>'.html_safe if is_orphans
176
177
  css = +"<style>
178
+ h1, h3 {
179
+ margin-bottom: 0;
180
+ }
177
181
  #dropper {
178
182
  background-color: #eee;
179
183
  }
@@ -195,19 +199,41 @@ table {
195
199
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
196
200
  }
197
201
 
198
- table thead tr th, table tr th {
202
+ tr th {
199
203
  background-color: #009879;
200
204
  color: #fff;
201
205
  text-align: left;
202
206
  }
203
- #headerTop th:hover, #headerTop th:hover {
207
+ #headerTop tr th {
208
+ position: relative;
209
+ }
210
+ #headerTop tr th .exclude {
211
+ position: absolute;
212
+ display: none;
213
+ top: 0;
214
+ right: 0;
215
+ }
216
+ #headerTop tr th:hover {
204
217
  background-color: #18B090;
205
218
  }
206
- table thead tr th a, table tr th a {
219
+ #exclusions {
220
+ font-size: 0.7em;
221
+ }
222
+ #exclusions div {
223
+ border: 1px solid blue;
224
+ display: inline-block;
225
+ cursor: copy;
226
+ }
227
+ #headerTop tr th:hover .exclude {
228
+ display: inline;
229
+ cursor: pointer;
230
+ color: red;
231
+ }
232
+ tr th a {
207
233
  color: #80FFB8;
208
234
  }
209
235
 
210
- table th, table td {
236
+ tr th, tr td {
211
237
  padding: 0.2em 0.5em;
212
238
  }
213
239
 
@@ -253,6 +279,7 @@ a.big-arrow {
253
279
  }
254
280
  .dimmed {
255
281
  background-color: #C0C0C0;
282
+ text-align: center;
256
283
  }
257
284
  .orphan {
258
285
  color: red;
@@ -414,8 +441,19 @@ function setHeaderSizes() {
414
441
  for (var i = 0; i < row.childNodes.length; ++i) {
415
442
  node = row.childNodes[i];
416
443
  if (node.nodeType === 1) {
417
- var style = tr.childNodes[i].style;
418
- style.minWidth = style.maxWidth = getComputedStyle(node).width;
444
+ var th = tr.childNodes[i];
445
+ th.style.minWidth = th.style.maxWidth = getComputedStyle(node).width;
446
+ if (#{pk&.present? ? 'i > 0' : 'true'}) {
447
+ // Add <span> at the end
448
+ var span = document.createElement(\"SPAN\");
449
+ span.className = \"exclude\";
450
+ span.innerHTML = \"X\";
451
+ span.addEventListener(\"click\", function (e) {
452
+ e.stopPropagation();
453
+ doFetch(\"POST\", {_brick_exclude: this.parentElement.getAttribute(\"x-order\")});
454
+ });
455
+ th.appendChild(span);
456
+ }
419
457
  }
420
458
  }
421
459
  if (isEmpty) headerTop.appendChild(tr);
@@ -423,6 +461,18 @@ function setHeaderSizes() {
423
461
  grid.style.marginTop = \"-\" + getComputedStyle(headerTop).height;
424
462
  // console.log(\"end\");
425
463
  }
464
+ function doFetch(method, payload, success) {
465
+ payload.authenticity_token = <%= session[:_csrf_token].inspect.html_safe %>;
466
+ if (!success) {
467
+ success = function (p) {p.text().then(function (response) {
468
+ var result = JSON.parse(response).result;
469
+ if (result) location.href = location.href;
470
+ });};
471
+ }
472
+ var options = {method: method, headers: {\"Content-Type\": \"application/json\"}};
473
+ if (payload) options.body = JSON.stringify(payload);
474
+ return fetch(location.href, options).then(success);
475
+ }
426
476
  if (headerTop) {
427
477
  setHeaderSizes();
428
478
  window.addEventListener('resize', function(event) {
@@ -457,8 +507,8 @@ if (headerTop) {
457
507
  });
458
508
  btnImport.addEventListener(\"click\", function () {
459
509
  fetch(changeout(<%= #{path_obj_name}_path(-1, format: :csv).inspect.html_safe %>, \"_brick_schema\", brickSchema), {
460
- method: 'PATCH',
461
- headers: { 'Content-Type': 'text/tab-separated-values' },
510
+ method: \"PATCH\",
511
+ headers: { \"Content-Type\": \"text/tab-separated-values\" },
462
512
  body: droppedTSV
463
513
  }).then(function (tsvResponse) {
464
514
  btnImport.style.display = \"none\";
@@ -536,6 +586,7 @@ if (headerTop) {
536
586
  if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
537
587
  description %><br><%
538
588
  end
589
+ # FILTER PARAMETERS
539
590
  if @_brick_params&.present? %>
540
591
  <% if @_brick_params.length == 1 # %%% Does not yet work with composite keys
541
592
  k, id = @_brick_params.first
@@ -547,38 +598,62 @@ if (headerTop) {
547
598
  end
548
599
  end %>
549
600
  (<%= link_to 'See all #{model_plural.split('::').last}', #{path_obj_name.pluralize}_path %>)
601
+ <% end
602
+ # COLUMN EXCLUSIONS
603
+ if @_brick_excl&.present? %>
604
+ <div id=\"exclusions\">Excluded columns:
605
+ <% @_brick_excl.each do |excl| %>
606
+ <div class=\"colExclusion\"><%= excl %></div>
607
+ <% end %>
608
+ </div>
609
+ <script>
610
+ [... document.getElementsByClassName(\"colExclusion\")].forEach(function (excl) {
611
+ excl.addEventListener(\"click\", function () {
612
+ doFetch(\"POST\", {_brick_unexclude: this.innerHTML});
613
+ });
614
+ });
615
+ </script>
550
616
  <% end %>
551
- <br>
552
617
  <table id=\"headerTop\">
553
618
  <table id=\"#{table_name}\">
554
619
  <thead><tr>#{"<th x-order=\"#{pk.join(',')}\"></th>" if pk.present?}<%=
555
- col_order = []
556
- # Consider getting the name from the association -- h.first.name -- if a more \"friendly\" alias should be used for a screwy table name
557
- hms_hdrs = {#{hms_headers.map do |hm|
558
- "#{hm.first.name}: [#{hm.first.name.inspect}, #{(hm.first.options[:through] && !hm.first.through_reflection).inspect}, #{hm.first.klass.name}, #{hm[1].inspect}, #{hm[2].inspect}]"
559
- end.join(', ')}}
560
- (@#{table_name}.columns + hms_hdrs.values).each_with_object(+'') do |col, s|
561
- if col.is_a?(ActiveRecord::ConnectionAdapters::Column)
562
- next if (#{(pk || []).inspect}.include?(col_name = col.name) && col.type == :integer && !bts.key?(col_name)) ||
563
- ::Brick.config.metadata_columns.include?(col_name) || poly_cols.include?(col_name)
564
-
565
- col_order << col_name
620
+ # Consider getting the name from the association -- hm.first.name -- if a more \"friendly\" alias should be used for a screwy table name
621
+ cols = {#{hms_keys = []
622
+ hms_headers.map do |hm|
623
+ hms_keys << (assoc_name = (assoc = hm.first).name.to_s)
624
+ "#{assoc_name.inspect} => [#{(assoc.options[:through] && !assoc.through_reflection).inspect}, #{assoc.klass.name}, #{hm[1].inspect}, #{hm[2].inspect}]"
625
+ end.join(', ')}}
626
+ col_keys = @#{table_name}.columns.each_with_object([]) do |col, s|
627
+ col_name = col.name
628
+ next if @_brick_incl&.exclude?(col_name) ||
629
+ (#{(pk || []).inspect}.include?(col_name) && col.type == :integer && !bts.key?(col_name)) ||
630
+ ::Brick.config.metadata_columns.include?(col_name) || poly_cols.include?(col_name)
631
+
632
+ s << col_name
633
+ cols[col_name] = col
634
+ end
635
+ unless @_brick_sequence # If no sequence is defined, start with all inclusions
636
+ @_brick_sequence = col_keys + #{(hms_keys).inspect}.reject { |assoc_name| @_brick_incl&.exclude?(assoc_name) }
637
+ end
638
+ @_brick_sequence.reject! { |nm| @_brick_excl.include?(nm) } if @_brick_excl # Reject exclusions
639
+ @_brick_sequence.each_with_object(+'') do |col_name, s|
640
+ if (col = cols[col_name]).is_a?(ActiveRecord::ConnectionAdapters::Column)
641
+ s << '<th'
642
+ s << \" title=\\\"#\{col.comment}\\\"\" if col.respond_to?(:comment) && !col.comment.blank?
566
643
  s << if (bt = bts[col_name])
567
- \"<th#\{' x-order=\"' + bt.first.to_s + '\"' unless bt[2]}>BT \" + # Allow sorting any BT except polymorphics
644
+ # Allow sorting for any BT except polymorphics
645
+ \"#\{' x-order=\"' + bt.first.to_s + '\"' unless bt[2]}>BT \" +
568
646
  bt[1].map { |bt_pair| bt_pair.first.bt_link(bt.first) }.join(' ')
569
- else
570
- # Currently we always allow click to sort on non-BT columns
571
- \"<th#\{' x-order=\"' + col_name + '\"' if true}>#\{col_name}\"
572
- end + '</th>'
573
- else # Currently we always allow click to sort on all HM columns (col is the hm array)
574
- col_order << col.first # hm.name
575
- s << \"<th#\{' x-order=\"' + col.first.to_s + '\"' if true}>\"
576
- s << if col[1]
577
- \"#\{col[3]} #\{col[4]}\" # %%% Would be able to remove this when multiple foreign keys to same destination becomes bulletproof
578
- else
579
- \"#\{col[3]} #\{link_to(col[4], send(\"#\{col[2].name.underscore.tr('/', '_').pluralize}_path\"))}\"
580
- end + '</th>'
647
+ else # Normal column
648
+ \"#\{' x-order=\"' + col_name + '\"' if true}>#\{col_name}\"
649
+ end
650
+ elsif col # HM column
651
+ s << \"<th#\{' x-order=\"' + col_name + '\"' if true}>#\{col[2]} \"
652
+ s << (col.first ? \"#\{col[3]}\" : \"#\{link_to(col[3], send(\"#\{col[1].name.underscore.tr('/', '_').pluralize}_path\"))}\")
653
+ else # Bad column name!
654
+ s << \"<th title=\\\"<< Unknown column >>\\\">#\{col_name}\"
581
655
  end
656
+ s << '</th>'
582
657
  end.html_safe
583
658
  %></tr></thead>
584
659
  <tbody>
@@ -586,16 +661,15 @@ if (headerTop) {
586
661
  hms_cols = {#{hms_columns.join(', ')}} %>
587
662
  <tr>#{"
588
663
  <td><%= link_to '⇛', #{path_obj_name}_path(#{obj_pk}), { class: 'big-arrow' } %></td>" if obj_pk}
589
- <% col_order.each do |col_name|
664
+ <% @_brick_sequence.each do |col_name|
590
665
  val = #{obj_name}.attributes[col_name] %>
591
- <td><%
666
+ <td<%= ' class=\"dimmed\"'.html_safe unless cols.key?(col_name)%>><%
592
667
  if (bt = bts[col_name])
593
668
  if bt[2] # Polymorphic?
594
669
  bt_class = #{obj_name}.send(\"#\{bt.first\}_type\")
595
670
  base_class = (::Brick.existing_stis[bt_class] || bt_class).constantize.base_class.name.underscore
596
671
  poly_id = #{obj_name}.send(\"#\{bt.first\}_id\")
597
- %><%= link_to(\"#\{bt_class\} ##\{poly_id\}\",
598
- send(\"#\{base_class\}_path\".to_sym, poly_id)) if poly_id %><%
672
+ %><%= link_to(\"#\{bt_class\} ##\{poly_id\}\", send(\"#\{base_class\}_path\".to_sym, poly_id)) if poly_id %><%
599
673
  else
600
674
  bt_txt = (bt_class = bt[1].first.first).brick_descrip(
601
675
  # 0..62 because Postgres column names are limited to 63 characters
@@ -604,15 +678,14 @@ if (headerTop) {
604
678
  bt_txt ||= \"<span class=\\\"orphan\\\">&lt;&lt; Orphaned ID: #\{val} >></span>\".html_safe if val
605
679
  bt_id = bt_id_col.map { |id_col| #{obj_name}.send(id_col.to_sym) } %>
606
680
  <%= bt_id&.first ? link_to(bt_txt, send(\"#\{bt_class.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, bt_id)) : bt_txt %>
607
- <%#= Previously was: bt_obj = bt[1].first.first.find_by(bt[2] => val); link_to(bt_obj.brick_descrip, send(\"#\{bt[1].first.first.name.underscore\}_path\".to_sym, bt_obj.send(bt[1].first.first.primary_key.to_sym))) if bt_obj %>
608
- <% end %>
609
- <% elsif (hms_col = hms_cols[col_name])
681
+ <% end
682
+ elsif (hms_col = hms_cols[col_name])
610
683
  if hms_col.length == 1 %>
611
684
  <%= hms_col.first %>
612
685
  <% else
613
- klass = (col = hms_hdrs[col_name])[2]
614
- txt = if col[3] == 'HO'
615
- descrips = @_brick_bt_descrip[col_name][klass]
686
+ klass = (col = cols[col_name])[1]
687
+ txt = if col[2] == 'HO'
688
+ descrips = @_brick_bt_descrip[col_name.to_sym][klass]
616
689
  ho_txt = klass.brick_descrip(#{obj_name}, descrips[0..-2].map { |id| #{obj_name}.send(id.last[0..62]) }, (ho_id_col = descrips.last))
617
690
  ho_id = ho_id_col.map { |id_col| #{obj_name}.send(id_col.to_sym) }
618
691
  ho_id&.first ? link_to(ho_txt, send(\"#\{klass.base_class.name.underscore.tr('/', '_')\}_path\".to_sym, ho_id)) : ho_txt
@@ -620,9 +693,11 @@ if (headerTop) {
620
693
  \"#\{hms_col[1] || 'View'\} #\{hms_col.first}\"
621
694
  end %>
622
695
  <%= link_to txt, send(\"#\{klass.name.underscore.tr('/', '_').pluralize}_path\".to_sym, hms_col[2]) unless hms_col[1]&.zero? %>
623
- <% end %>
624
- <% else
696
+ <% end
697
+ elsif cols.key?(col_name)
625
698
  %><%= hide_bcrypt(val) %><%
699
+ else # Bad column name!
700
+ %>?<%
626
701
  end
627
702
  %></td>
628
703
  <% end %>
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 52
8
+ TINY = 53
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
data/lib/brick.rb CHANGED
@@ -190,6 +190,15 @@ module Brick
190
190
  [bts, hms]
191
191
  end
192
192
 
193
+ def exclude_column(table, col)
194
+ puts "Excluding #{table}.#{col}"
195
+ true
196
+ end
197
+ def unexclude_column(table, col)
198
+ puts "Unexcluding #{table}.#{col}"
199
+ true
200
+ end
201
+
193
202
  # Switches Brick auto-models on or off, for all threads
194
203
  # @api public
195
204
  def enable_models=(value)
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.52
4
+ version: 1.0.53
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lorin Thwaits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-04 00:00:00.000000000 Z
11
+ date: 2022-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord