brick 1.0.60 → 1.0.63

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: 741384ed503092151ed20f360abd8819fdf3b25fc4042e5aa953dae928acab6d
4
- data.tar.gz: 11e88b4b7bdc51b9237e095fdaae1297741e1c315737e18d7194c3c84e937797
3
+ metadata.gz: c28a4db728e9312def40be9a9a790f1f22f464c6d6ade2b6e12f255730cd4111
4
+ data.tar.gz: c2e75de42686c9ad0707fd6eca3d0b0a12207e051d77622d70276845d9af0949
5
5
  SHA512:
6
- metadata.gz: daa2950ea3ff1354c642949797a4ed7e7ed5c14cfcba4e5560572e997e4df43b537ecb12e84dc2d710b3e067870a91c69519ee41735ea7e9ada0d110ae2bd906
7
- data.tar.gz: 3e74b2d21d72d84ea7286a7b8959b0abb293c50844b5e3ba4fce73cc4f8b5dd68fa7a50dc9753901f0b82b6a3196ab3fd282c4e709d0ae82af37e5a4e68488a9
6
+ metadata.gz: a897f30028aac1b6e14edc967a82c268aa58236cd424ecf977409a0c893d42b9e291c11ac2b2a411f00dc35c23b80a4ed6adecde394587c96d11b9f51c173fd8
7
+ data.tar.gz: 538d694b6a0717045c6e23ec536a000a552bc0ece9009f74511e33013e0dde97f8cefadbc61a45d4b7ea884dd0c1dd985f5defc58175ec51318d345a7e561c2d
@@ -1132,6 +1132,7 @@ class Object
1132
1132
  @_brick_bt_descrip = model._br_bt_descrip
1133
1133
  @_brick_hm_counts = model._br_hm_counts
1134
1134
  @_brick_join_array = join_array
1135
+ @_brick_erd = params['_brick_erd']&.to_i
1135
1136
  end
1136
1137
 
1137
1138
  _, order_by_txt = model._brick_calculate_ordering(default_ordering(table_name, pk))
@@ -1460,7 +1461,9 @@ module ActiveRecord::ConnectionHandling
1460
1461
  INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS kcu2
1461
1462
  ON kcu2.CONSTRAINT_CATALOG = rc.UNIQUE_CONSTRAINT_CATALOG
1462
1463
  AND kcu2.CONSTRAINT_SCHEMA = rc.UNIQUE_CONSTRAINT_SCHEMA
1463
- AND kcu2.CONSTRAINT_NAME = rc.UNIQUE_CONSTRAINT_NAME
1464
+ AND kcu2.CONSTRAINT_NAME = rc.UNIQUE_CONSTRAINT_NAME#{"
1465
+ AND kcu2.TABLE_NAME = kcu1.REFERENCED_TABLE_NAME
1466
+ AND kcu2.COLUMN_NAME = kcu1.REFERENCED_COLUMN_NAME" unless is_postgres }
1464
1467
  AND kcu2.ORDINAL_POSITION = kcu1.ORDINAL_POSITION#{"
1465
1468
  WHERE kcu1.CONSTRAINT_SCHEMA = COALESCE(current_setting('SEARCH_PATH'), 'public')" if is_postgres && schema }"
1466
1469
  # AND kcu2.TABLE_NAME = ?;", Apartment::Tenant.current, table_name
@@ -1540,8 +1543,10 @@ module ActiveRecord::ConnectionHandling
1540
1543
  ON kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
1541
1544
  AND kcu.TABLE_NAME = tc.TABLE_NAME
1542
1545
  AND kcu.CONSTRAINT_NAME = tc.constraint_name
1543
- WHERE t.table_schema NOT IN ('information_schema', #{
1544
- is_postgres ? "'pg_catalog'" : "'mysql', 'performance_schema', 'sys'"})#{"
1546
+ WHERE t.table_schema #{is_postgres ?
1547
+ "NOT IN ('information_schema', 'pg_catalog')"
1548
+ :
1549
+ "= '#{ActiveRecord::Base.connection.current_database.tr("'", "''")}'"}#{"
1545
1550
  AND t.table_schema = COALESCE(current_setting('SEARCH_PATH'), 'public')" if is_postgres && schema }
1546
1551
  -- AND t.table_type IN ('VIEW') -- 'BASE TABLE', 'FOREIGN TABLE'
1547
1552
  AND t.table_name NOT IN ('pg_stat_statements', ?, ?)
@@ -47,7 +47,10 @@ module Brick
47
47
  end
48
48
 
49
49
  # After we're initialized and before running the rest of stuff, put our configuration in place
50
- ActiveSupport.on_load(:after_initialize) do
50
+ ActiveSupport.on_load(:after_initialize) do |app|
51
+ assets_path = File.expand_path("#{__dir__}/../../../../vendor/assets")
52
+ (app.config.assets.precompile ||= []) << "#{assets_path}/images/brick_erd.png"
53
+ (app.config.assets.paths ||= []) << assets_path
51
54
  # ====================================
52
55
  # Dynamically create generic templates
53
56
  # ====================================
@@ -179,6 +182,30 @@ module Brick
179
182
  h1, h3 {
180
183
  margin-bottom: 0;
181
184
  }
185
+ #resourceName {
186
+ }
187
+ #imgErd {
188
+ background-image:url(assets/brick_erd.png);
189
+ background-size: 100% 100%;
190
+ width: 2.2em;
191
+ height: 2.2em;
192
+ cursor: pointer;
193
+ }
194
+ #mermaidErd {
195
+ position: relative;
196
+ display: none;
197
+ }
198
+ #mermaidErd .exclude {
199
+ position: absolute;
200
+ color: red;
201
+ top: 0;
202
+ right: 0;
203
+ cursor: pointer;
204
+ }
205
+ .relatedModel {
206
+ cursor: pointer;
207
+ }
208
+
182
209
  #dropper {
183
210
  background-color: #eee;
184
211
  }
@@ -196,6 +223,8 @@ table {
196
223
  border-collapse: collapse;
197
224
  font-size: 0.9em;
198
225
  font-family: sans-serif;
226
+ }
227
+ table.shadow {
199
228
  min-width: 400px;
200
229
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
201
230
  }
@@ -213,6 +242,7 @@ tr th {
213
242
  display: none;
214
243
  top: 0;
215
244
  right: 0;
245
+ cursor: pointer;
216
246
  }
217
247
  #headerTop tr th:hover {
218
248
  background-color: #18B090;
@@ -245,7 +275,7 @@ tr th, tr td {
245
275
  color: #80B8D2;
246
276
  }
247
277
 
248
- table tbody tr {
278
+ table.shadow tbody tr {
249
279
  border-bottom: thin solid #dddddd;
250
280
  }
251
281
 
@@ -253,7 +283,7 @@ table tbody tr:nth-of-type(even) {
253
283
  background-color: #f3f3f3;
254
284
  }
255
285
 
256
- table tbody tr:last-of-type {
286
+ table.shadow tbody tr:last-of-type {
257
287
  border-bottom: 2px solid #009879;
258
288
  }
259
289
 
@@ -327,6 +357,28 @@ def hide_bcrypt(val, max_len = 200)
327
357
  end
328
358
  val
329
359
  end
360
+ end
361
+ def display_value(col_type, val)
362
+ case col_type
363
+ when 'geometry'
364
+ if Object.const_defined?('RGeo')
365
+ @is_mysql = ActiveRecord::Base.connection.adapter_name == 'Mysql2' if @is_mysql.nil?
366
+ if @is_mysql
367
+ # MySQL's \"Internal Geometry Format\" is like WKB, but with an initial 4 bytes that indicates the SRID.
368
+ srid = val[..3].unpack('I')
369
+ val = val[4..]
370
+ end
371
+ RGeo::WKRep::WKBParser.new.parse(val)
372
+ else
373
+ '(Add RGeo gem to parse geometry detail)'
374
+ end
375
+ else
376
+ if col_type
377
+ hide_bcrypt(val)
378
+ else
379
+ '?'
380
+ end
381
+ end
330
382
  end %>"
331
383
 
332
384
  if ['index', 'show', 'update'].include?(args.first)
@@ -416,10 +468,11 @@ function changeout(href, param, value, trimAfter) {
416
468
  hrefParts[0] = pathParts.join(\"/\");
417
469
  }
418
470
  var params = hrefParts.length > 1 ? hrefParts[1].split(\"&\") : [];
419
- params = params.reduce(function (s, v) { var parts = v.split(\"=\"); s[parts[0]] = parts[1]; return s; }, {});
471
+ params = params.reduce(function (s, v) { var parts = v.split(\"=\"); if (parts[1] !== null) s[parts[0]] = parts[1]; return s; }, {});
420
472
  if (value === undefined) return params[param];
421
473
  params[param] = value;
422
- return hrefParts[0] + \"?\" + Object.keys(params).reduce(function (s, v) { s.push(v + \"=\" + params[v]); return s; }, []).join(\"&\");
474
+ var finalParams = Object.keys(params).reduce(function (s, v) { if (params[v] !== null) s.push(v + \"=\" + params[v]); return s; }, []).join(\"&\");
475
+ return hrefParts[0] + (finalParams.length > 0 ? \"?\" + finalParams : \"\");
423
476
  }
424
477
 
425
478
  // Snag first TR for sticky header
@@ -583,7 +636,10 @@ if (headerTop) {
583
636
  <p style=\"color: green\"><%= notice %></p>#{"
584
637
  <select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
585
638
  <select id=\"tbl\">#{table_options}</select>
586
- <h1>#{model_plural = model_name.pluralize}</h1>#{template_link}<%
639
+ <table id=\"resourceName\"><tr>
640
+ <td><h1>#{model_plural = model_name.pluralize}</h1></td>
641
+ <td id=\"imgErd\" title=\"Show ERD\"></td>
642
+ </tr></table>#{template_link}<%
587
643
  if (description = (relation = Brick.relations[#{model_name}.table_name])&.fetch(:description, nil)) %><%=
588
644
  description %><br><%
589
645
  end
@@ -614,10 +670,41 @@ if (headerTop) {
614
670
  });
615
671
  });
616
672
  </script>
673
+ <% end
674
+ if true # @_brick_erd
675
+ %><div id=\"mermaidErd\" class=\"mermaid\">
676
+ erDiagram
677
+ <% model_short_name = #{@_brick_model.name.split('::').last.inspect}
678
+ callbacks = {}
679
+ @_brick_bt_descrip.each do |bt|
680
+ bt_full_name = bt[1].first.first.name
681
+ callbacks[bt_name = bt_full_name.split('::').last] = bt_full_name
682
+ # binding.pry
683
+ %> <%= \"#\{model_short_name} #\{'||'}--#\{
684
+ 'o{'} #\{bt_name} : \\\"#\{
685
+ bt.first unless bt.first.to_s == bt[1].first.first.name.underscore.singularize.tr('/', '_')
686
+ }\\\"\".html_safe %>
687
+ <% end %>
688
+ <% @_brick_hm_counts.each do |hm|
689
+ hm_full_name = hm.last.klass.name
690
+ callbacks[hm_name = hm_full_name.split('::').last] = hm_full_name
691
+ %> <%= \"#\{model_short_name} #\{'}o'}--#\{
692
+ '||'} #\{hm_name} : \\\"#\{
693
+ hm.first unless hm.first.to_s == hm_full_name.underscore.pluralize.tr('/', '_')
694
+ }\\\"\".html_safe %>
695
+ <% end %>
696
+ <% callbacks.keys.each do |cb|
697
+ %> <%= cb %> {
698
+ int id
699
+ }
700
+ <% end
701
+ # callback < %= cb_k % > erdClick
702
+ %>
703
+ </div>
617
704
  <% end
618
705
 
619
- %><table id=\"headerTop\">
620
- <table id=\"#{table_name}\">
706
+ %><table id=\"headerTop\"></table>
707
+ <table id=\"#{table_name}\" class=\"shadow\">
621
708
  <thead><tr>#{"<th x-order=\"#{pk.join(',')}\"></th>" if pk.present?}<%=
622
709
  # Consider getting the name from the association -- hm.first.name -- if a more \"friendly\" alias should be used for a screwy table name
623
710
  cols = {#{hms_keys = []
@@ -683,7 +770,7 @@ if (headerTop) {
683
770
  <% end
684
771
  elsif (hms_col = hms_cols[col_name])
685
772
  if hms_col.length == 1 %>
686
- <%= hms_col.first %>
773
+ <%= hms_col.first %>
687
774
  <% else
688
775
  klass = (col = cols[col_name])[1]
689
776
  txt = if col[2] == 'HO'
@@ -696,8 +783,8 @@ if (headerTop) {
696
783
  end %>
697
784
  <%= link_to txt, send(\"#\{klass.name.underscore.tr('/', '_').pluralize}_path\".to_sym, hms_col[2]) unless hms_col[1]&.zero? %>
698
785
  <% end
699
- elsif cols.key?(col_name)
700
- %><%= hide_bcrypt(val) %><%
786
+ elsif (col = cols[col_name])
787
+ %><%= display_value(col&.type || col&.sql_type, val) %><%
701
788
  else # Bad column name!
702
789
  %>?<%
703
790
  end
@@ -720,7 +807,7 @@ if (headerTop) {
720
807
  <select id=\"schema\">#{schema_options}</select>" if ::Brick.config.schema_behavior[:multitenant] && ::Brick.db_schemas.length > 1}
721
808
  <select id=\"tbl\">#{table_options}</select>
722
809
  <h1>Status</h1>
723
- <table id=\"status\"><thead><tr>
810
+ <table id=\"status\" class=\"shadow\"><thead><tr>
724
811
  <th>Resource</th>
725
812
  <th>Table</th>
726
813
  <th>Migration</th>
@@ -754,7 +841,7 @@ if (headerTop) {
754
841
  %></td>
755
842
  <tr>
756
843
  <% end %>
757
- </tbody><table>
844
+ </tbody></table>
758
845
  #{script}"
759
846
 
760
847
  when 'orphans'
@@ -796,7 +883,7 @@ end
796
883
  # path_options << { '_brick_schema': } if
797
884
  # url = send(:#{model_name.underscore}_path, obj.#{pk})
798
885
  form_for(obj.becomes(#{model_name})) do |f| %>
799
- <table>
886
+ <table class=\"shadow\">
800
887
  <% has_fields = false
801
888
  @#{obj_name}.attributes.each do |k, val|
802
889
  col = #{model_name}.columns_hash[k] %>
@@ -853,7 +940,7 @@ end
853
940
  <% else
854
941
  html_options = {}
855
942
  html_options[:class] = 'dimmed' unless val
856
- case (col_type = #{model_name}.column_for_attribute(k).type)
943
+ case (col_type = col.type || col.sql_type)
857
944
  when :string, :text %>
858
945
  <% if is_bcrypt?(val) # || .readonly? %>
859
946
  <%= hide_bcrypt(val, 1000) %>
@@ -883,6 +970,8 @@ end
883
970
  # If it's not yet enabled then: create extension ltree;
884
971
  val %>
885
972
  <% when :binary, :primary_key %>
973
+ <% else %>
974
+ <%= display_value(col_type, val) %>
886
975
  <% end %>
887
976
  <% end %>
888
977
  </td>
@@ -903,7 +992,7 @@ end
903
992
  if (pk = hm.first.klass.primary_key)
904
993
  hm_singular_name = (hm_name = hm.first.name.to_s).singularize.underscore
905
994
  obj_pk = (pk.is_a?(Array) ? pk : [pk]).each_with_object([]) { |pk_part, s| s << "#{hm_singular_name}.#{pk_part}" }.join(', ')
906
- s << "<table id=\"#{hm_name}\">
995
+ s << "<table id=\"#{hm_name}\" class=\"shadow\">
907
996
  <tr><th>#{hm[3]}</th></tr>
908
997
  <% collection = @#{obj_name}.#{hm_name}
909
998
  collection = collection.is_a?(ActiveRecord::Associations::CollectionProxy) ? collection.order(#{pk.inspect}) : [collection].compact
@@ -938,7 +1027,61 @@ flatpickr(\".datetimepicker\", {enableTime: true});
938
1027
  flatpickr(\".timepicker\", {enableTime: true, noCalendar: true});
939
1028
  </script>
940
1029
  <% end %>
1030
+
1031
+ <% if true # @_brick_erd
1032
+ %>
941
1033
  <script>
1034
+ var imgErd = document.getElementById(\"imgErd\");
1035
+ var mermaidErd = document.getElementById(\"mermaidErd\");
1036
+ var mermaidCode;
1037
+ var cbs = {<%= callbacks.map { |k, v| \"#\{k}: \\\"#\{v.underscore.pluralize}\\\"\" }.join(', ').html_safe %>};
1038
+ imgErd.addEventListener(\"click\", showErd);
1039
+ function showErd() {
1040
+ imgErd.style.display = \"none\";
1041
+ mermaidErd.style.display = \"inline-block\";
1042
+ if (mermaidCode) return; // Cut it short if we've already rendered the diagram
1043
+
1044
+ mermaidCode = document.createElement(\"SCRIPT\");
1045
+ mermaidCode.setAttribute(\"src\", \"https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js\");
1046
+ mermaidCode.addEventListener(\"load\", function () {
1047
+ mermaid.initialize({
1048
+ startOnLoad: true,
1049
+ securityLevel: \"loose\",
1050
+ mermaid: {callback: function(objId) {
1051
+ var svg = document.getElementById(objId);
1052
+ var cb;
1053
+ for(cb in cbs) {
1054
+ var gErd = svg.getElementById(cb);
1055
+ gErd.setAttribute(\"class\", \"relatedModel\");
1056
+ gErd.addEventListener(\"click\",
1057
+ function (evt) {
1058
+ location.href = changeout(changeout(location.href, null, cbs[this.id]), \"_brick_erd\", \"1\");
1059
+ }
1060
+ );
1061
+ }
1062
+ }}
1063
+ });
1064
+ mermaid.contentLoaded();
1065
+ // Add <span> at the end
1066
+ var span = document.createElement(\"SPAN\");
1067
+ span.className = \"exclude\";
1068
+ span.innerHTML = \"X\";
1069
+ span.addEventListener(\"click\", function (e) {
1070
+ e.stopPropagation();
1071
+ imgErd.style.display = \"table-cell\";
1072
+ mermaidErd.style.display = \"none\";
1073
+ window.history.pushState({}, '', changeout(location.href, '_brick_erd', null));
1074
+ });
1075
+ mermaidErd.appendChild(span);
1076
+ });
1077
+ document.body.appendChild(mermaidCode);
1078
+ }
1079
+ <%= \" showErd();\n\" if (@_brick_erd || 0) > 0
1080
+ %></script>
1081
+
1082
+ <% end
1083
+
1084
+ %><script>
942
1085
  <% # Make column headers sort when clicked
943
1086
  # %%% Create a smart javascript routine which can do this client-side %>
944
1087
  [... document.getElementsByTagName(\"TH\")].forEach(function (th) {
@@ -5,7 +5,7 @@ module Brick
5
5
  module VERSION
6
6
  MAJOR = 1
7
7
  MINOR = 0
8
- TINY = 60
8
+ TINY = 63
9
9
 
10
10
  # PRE is nil unless it's a pre-release (beta, RC, etc.)
11
11
  PRE = nil
@@ -21,7 +21,7 @@ module Brick
21
21
  'timestamp with time zone' => 'timestamp',
22
22
  'time without time zone' => 'time',
23
23
  'time with time zone' => 'time',
24
- 'double precision' => 'float', # might work with 'double'
24
+ 'double precision' => 'float',
25
25
  'smallint' => 'integer' } # %%% Need to put in "limit: 2"
26
26
  # (Still need to find what "inet" and "json" data types map to.)
27
27
 
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.60
4
+ version: 1.0.63
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-23 00:00:00.000000000 Z
11
+ date: 2022-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord