active_element 0.0.14 → 0.0.16

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +9 -24
  3. data/app/assets/javascripts/active_element/form.js +2 -1
  4. data/app/assets/javascripts/active_element/json_field.js +8 -1
  5. data/app/views/active_element/components/button.html.erb +6 -4
  6. data/app/views/active_element/components/form/_check_boxes.html.erb +6 -4
  7. data/app/views/active_element/components/form/_date_range_field.html.erb +14 -0
  8. data/app/views/active_element/components/form/_field.html.erb +3 -0
  9. data/app/views/active_element/components/form/_summary.html.erb +10 -0
  10. data/app/views/active_element/components/form.html.erb +12 -2
  11. data/app/views/active_element/components/table/_collection_row.html.erb +3 -3
  12. data/app/views/active_element/components/table/_field.html.erb +2 -2
  13. data/app/views/active_element/components/table/collection.html.erb +20 -11
  14. data/app/views/active_element/components/table/item.html.erb +4 -0
  15. data/app/views/active_element/default_views/forbidden.html.erb +17 -3
  16. data/app/views/active_element/default_views/index.html.erb +14 -6
  17. data/config/locales/en.yml +3 -0
  18. data/example_app/.ruby-version +1 -1
  19. data/example_app/Gemfile +0 -2
  20. data/example_app/Gemfile.lock +5 -4
  21. data/lib/active_element/components/button.rb +6 -4
  22. data/lib/active_element/components/collection_table.rb +10 -3
  23. data/lib/active_element/components/form.rb +27 -2
  24. data/lib/active_element/components/item_table.rb +5 -3
  25. data/lib/active_element/components/navbar.rb +1 -1
  26. data/lib/active_element/components/util/association_mapping.rb +48 -26
  27. data/lib/active_element/components/util/default_display_value.rb +51 -0
  28. data/lib/active_element/components/util/display_value_mapping.rb +10 -0
  29. data/lib/active_element/components/util/field_mapping.rb +2 -2
  30. data/lib/active_element/components/util/form_field_mapping.rb +68 -15
  31. data/lib/active_element/components/util/record_mapping.rb +24 -3
  32. data/lib/active_element/components/util/record_path.rb +52 -20
  33. data/lib/active_element/components/util.rb +13 -0
  34. data/lib/active_element/controller_interface.rb +15 -1
  35. data/lib/active_element/controller_state.rb +5 -2
  36. data/lib/active_element/default_controller/controller.rb +1 -1
  37. data/lib/active_element/default_controller/params.rb +9 -1
  38. data/lib/active_element/default_controller/search.rb +22 -16
  39. data/lib/active_element/field_options.rb +20 -0
  40. data/lib/active_element/version.rb +1 -1
  41. data/lib/active_element.rb +1 -0
  42. data/rspec-documentation/pages/016-Default Controller.md +10 -1
  43. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa975f8cc5ef82840b9fc0e8d2765e7189ab390824f413c7b3cfe1b9ed5df525
4
- data.tar.gz: 9f793eb2f627888673d1741d63d6a630a94e679d6e26eb61f2d66246a8046f91
3
+ metadata.gz: a5061acace969c49903b783f1395dfcac9683001fca5b18099b50222b62ce25d
4
+ data.tar.gz: b884bb15effdeca54b82c1a27140418304e09d10c17f3b8d49253d75f9dc8a76
5
5
  SHA512:
6
- metadata.gz: 5a8c6b96d8e34086277292cea537843c4a4b87db1171d8e272ef0748e0c1a1ff2fdff8a92d3eb345c4a324f251f27c24a5296aa27f9f065335d6f828d9c5791c
7
- data.tar.gz: c66d161434d29b86aa8b5edf4f7a077cb9ead633748491e2249ea24055af7025d4eed55a79ccdc50b6ab67f467554c89e45f8352ac9afd84a4fa19d8f5632bb8
6
+ metadata.gz: b3b3b9df909c578397d11260209daabfe8e6e9af8424ce9865c28da05be980f3cea7614dc898fd585e0ab695befe8e214ec16d5cf40ddb2b69e05c8067a3d3c0
7
+ data.tar.gz: ce25ad80b730f77837e06967e4e4d5217878af9609c1c88bfbaa09eb5f86cbaebbe92233465c3a542b58bf27d842b2cc9ef7a91b2f4b4e565044d9bc030adda9
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active_element (0.0.14)
4
+ active_element (0.0.16)
5
5
  bootstrap (~> 5.3.0alpha3)
6
6
  kaminari (~> 1.2)
7
7
  paintbrush (~> 0.1.2)
@@ -80,20 +80,19 @@ GEM
80
80
  addressable (2.8.4)
81
81
  public_suffix (>= 2.0.2, < 6.0)
82
82
  ast (2.4.2)
83
- autoprefixer-rails (10.4.15.0)
83
+ autoprefixer-rails (10.4.16.0)
84
84
  execjs (~> 2)
85
85
  bcrypt (3.1.18)
86
- bootstrap (5.3.1)
86
+ bootstrap (5.3.2)
87
87
  autoprefixer-rails (>= 9.1.0)
88
88
  popper_js (>= 2.11.8, < 3)
89
- sassc-rails (>= 2.0.0)
90
89
  brakeman (5.4.1)
91
90
  builder (3.2.4)
92
91
  concurrent-ruby (1.2.2)
93
92
  crack (0.4.5)
94
93
  rexml
95
94
  crass (1.0.6)
96
- date (3.3.3)
95
+ date (3.3.4)
97
96
  devise (4.9.2)
98
97
  bcrypt (~> 3.0)
99
98
  orm_adapter (~> 0.1)
@@ -151,16 +150,16 @@ GEM
151
150
  mini_mime (1.1.5)
152
151
  mini_portile2 (2.8.2)
153
152
  minitest (5.18.1)
154
- net-imap (0.4.1)
153
+ net-imap (0.4.9.1)
155
154
  date
156
155
  net-protocol
157
156
  net-pop (0.1.2)
158
157
  net-protocol
159
- net-protocol (0.2.1)
158
+ net-protocol (0.2.2)
160
159
  timeout
161
- net-smtp (0.4.0)
160
+ net-smtp (0.4.0.1)
162
161
  net-protocol
163
- nio4r (2.5.9)
162
+ nio4r (2.7.0)
164
163
  nokogiri (1.15.2)
165
164
  mini_portile2 (~> 2.8.2)
166
165
  racc (~> 1.4)
@@ -286,27 +285,13 @@ GEM
286
285
  ruby-progressbar (1.13.0)
287
286
  sassc (2.4.0)
288
287
  ffi (~> 1.9)
289
- sassc-rails (2.1.2)
290
- railties (>= 4.0.0)
291
- sassc (>= 2.0)
292
- sprockets (> 3.0)
293
- sprockets-rails
294
- tilt
295
- sprockets (4.2.1)
296
- concurrent-ruby (~> 1.0)
297
- rack (>= 2.2.4, < 4)
298
- sprockets-rails (3.4.2)
299
- actionpack (>= 5.2)
300
- activesupport (>= 5.2)
301
- sprockets (>= 3.0.0)
302
288
  sqlite3 (1.6.3)
303
289
  mini_portile2 (~> 2.8.0)
304
290
  strong_versions (0.4.5)
305
291
  i18n (>= 0.5)
306
292
  paint (~> 2.0)
307
293
  thor (1.2.2)
308
- tilt (2.3.0)
309
- timeout (0.4.0)
294
+ timeout (0.4.1)
310
295
  tzinfo (2.0.6)
311
296
  concurrent-ruby (~> 1.0)
312
297
  unicode-display_width (2.4.2)
@@ -31,7 +31,8 @@
31
31
  clearFormButton.addEventListener('click', (ev) => {
32
32
  ev.preventDefault();
33
33
 
34
- form.querySelectorAll('.form-fields input, .form-fields select, .form-fields textarea')
34
+ form.querySelectorAll('.form-fields input:enabled, .form-fields select:enabled, .form-fields textarea:enabled')
35
+ .filter((formInput) => !formInput.readonly)
35
36
  .forEach((formInput) => formInput.value = '');
36
37
  });
37
38
  });
@@ -432,7 +432,14 @@ ActiveElement.JsonField = (() => {
432
432
  element.append(Option({ value: '' }));
433
433
 
434
434
  schema.options.forEach((value) => {
435
- element.append(Option({ value, selected: value === store.getValue(state) }));
435
+ let label = value;
436
+
437
+ if (isObject(value)) {
438
+ label = value.label;
439
+ value = value.value;
440
+ }
441
+
442
+ element.append(Option({ value, label, selected: value === store.getValue(state) }));
436
443
  });
437
444
 
438
445
  return element;
@@ -1,11 +1,13 @@
1
-
2
1
  <%=
3
2
  link_to(
4
3
  path.presence || '#',
5
4
  method: path.present? && method != :get ? method : nil,
6
- data: { confirm_action: confirm },
5
+ data: { confirm_action: confirm }.merge(tooltip ? {
6
+ 'bs-trigger': 'hover',
7
+ 'bs-toggle': 'popover',
8
+ 'bs-content': title,
9
+ } : {}),
7
10
  class: "btn #{button_class} #{float_class} #{kwargs_class}",
8
- title: title,
9
11
  **kwargs
10
12
  ) do %>
11
13
  <% if block_given %>
@@ -15,7 +17,7 @@
15
17
  <% if icon.present? %>
16
18
  <i class="fa-solid fa-<%= icon %>"></i>
17
19
  <% elsif type == :show %>
18
- <i class="fa-solid fa-eye"></i>
20
+ <i class="fa-solid fa-magnifying-glass"></i>
19
21
  <% elsif type == :edit %>
20
22
  <i class="fa-solid fa-pen"></i>
21
23
  <% elsif type == :destroy %>
@@ -17,12 +17,14 @@
17
17
  <% else %>
18
18
  <div class="container w-100">
19
19
  <%= form.fields_for field do |subform| %>
20
- <% options.fetch(:options).each_slice(options.fetch(:columns, 1)) do |slice| %>
20
+ <% options.fetch(:options).in_groups(options.fetch(:columns, 1)).reduce(&:zip).each do |columns| %>
21
21
  <div class="row w-100">
22
- <% slice.each do |label, name, checked| %>
22
+ <% columns.each do |label, name, checked| %>
23
23
  <div class="col">
24
- <%= subform.check_box(name, checked: checked, class: 'me-2', tabindex: component.tabindex) %>
25
- <%= subform.label name, label %>
24
+ <% if [label, name, checked].any?(&:present?) %>
25
+ <%= subform.check_box(name, checked: checked, class: 'me-2', tabindex: component.tabindex) %>
26
+ <%= subform.label name, label %>
27
+ <% end %>
26
28
  </div>
27
29
  <br/>
28
30
  <% end %>
@@ -0,0 +1,14 @@
1
+ <div class="d-flex">
2
+ <%= form.label(nil, class: 'me-2 mt-1') { 'Between' } %>
3
+ <%= form.date_field("#{field}[from]", name: "#{field}[from]",
4
+ value: component.value_for(field, :from),
5
+ class: "form-control #{component.valid?(field) ? nil : 'is-invalid'}",
6
+ tabindex: component.tabindex,
7
+ **options) %>
8
+ <%= form.label(nil, class: 'ms-2 mt-1 me-2') { 'and' } %>
9
+ <%= form.date_field("#{field}[to]", name: "#{field}[to]",
10
+ value: component.value_for(field, :to),
11
+ class: "form-control #{component.valid?(field) ? nil : 'is-invalid'}",
12
+ tabindex: component.tabindex,
13
+ **options) %>
14
+ </div>
@@ -20,6 +20,9 @@
20
20
  <% elsif type == :datetime_range_field %>
21
21
  <%= render partial: 'active_element/components/form/datetime_range_field',
22
22
  locals: { form_id: id, form: form, field: field, type: type, options: options, component: component } %>
23
+ <% elsif type == :date_range_field %>
24
+ <%= render partial: 'active_element/components/form/date_range_field',
25
+ locals: { form_id: id, form: form, field: field, type: type, options: options, component: component } %>
23
26
  <% else %>
24
27
  <%= render partial: 'active_element/components/form/generic_field',
25
28
  locals: { form_id: id, form: form, field: field, type: type, options: options, component: component } %>
@@ -24,6 +24,16 @@
24
24
  <% elsif type == :datetime_range_field %>
25
25
  <% next unless value.present? %>
26
26
 
27
+ <% values << value %>
28
+ <div class="d-inline me-3">
29
+ <span class="text-secondary"><%= options.fetch(:label) %>:</span>
30
+ <span class="ms-1 text-primary"><%= value[:from] %></span>
31
+ <span class="text-secondary">&rarr;</span>
32
+ <span class="ms-1 text-primary"><%= value[:to] %></span>
33
+ </div>
34
+ <% elsif type == :date_range_field %>
35
+ <% next unless value.present? %>
36
+
27
37
  <% values << value %>
28
38
  <div class="d-inline me-3">
29
39
  <span class="text-secondary"><%= options.fetch(:label) %>:</span>
@@ -35,12 +35,22 @@
35
35
  <% end %>
36
36
 
37
37
  <div class="form <%= modal ? 'd-none' : 'pb-3' %>" id="form-wrapper-<%= id %>">
38
- <%= form_with local: true, action: action, method: method, id: id, class: "#{class_name} m-3", **kwargs do |form| %>
38
+ <%= form_with model: model_param,
39
+ scope: becomes_model&.model_name&.param_key,
40
+ url: record_path.path,
41
+ local: true,
42
+ action: action,
43
+ method: method,
44
+ id: id,
45
+ class: "#{class_name} m-3",
46
+ **kwargs do |form| %>
39
47
  <% if %i[top both].include?(submit_position) %>
40
48
  <div class="row mb-3 form-group sticky-top" style="top: 0.5rem;">
41
49
  <div class="col-sm-3"></div>
42
50
  <div class="col pb-3">
43
- <%= form.submit submit_label, name: '', class: "btn btn-#{method == :post ? 'success' : 'primary'} ms-2 float-end" %>
51
+ <%= form.submit submit_label,
52
+ name: '',
53
+ class: "btn btn-#{method == :post ? 'success' : 'primary'} ms-2 float-end" %>
44
54
  <%= active_element.component.button 'Clear Form', class: 'btn-secondary float-end', data: { 'form-input-type': 'clear' } %>
45
55
  </div>
46
56
  </div>
@@ -13,19 +13,19 @@
13
13
 
14
14
  <% if show %>
15
15
  <td class="<%= "#{class_name}-show" %> action-column text-end">
16
- <%= active_element.component.show_button(item, show, class: 'btn-sm') %>
16
+ <%= active_element.component.show_button(item, show, tooltip: true, class: 'btn-sm') %>
17
17
  </td>
18
18
  <% end %>
19
19
 
20
20
  <% if edit %>
21
21
  <td class="<%= "#{class_name}-edit" %> action-column text-end">
22
- <%= active_element.component.edit_button(item, show, class: 'btn-sm') %>
22
+ <%= active_element.component.edit_button(item, show, tooltip: true, class: 'btn-sm') %>
23
23
  </td>
24
24
  <% end %>
25
25
 
26
26
  <% if destroy %>
27
27
  <td class="<%= "#{class_name}-destroy" %> action-column text-end">
28
- <%= active_element.component.destroy_button(item, destroy, class: 'btn-sm') %>
28
+ <%= active_element.component.destroy_button(item, destroy, tooltip: true, class: 'btn-sm') %>
29
29
  </td>
30
30
  <% end %>
31
31
  </tr>
@@ -1,7 +1,7 @@
1
1
  <% if value.is_a?(Array) %>
2
+ <ul>
2
3
  <% value.sort.each_with_index do |each_value, index| %>
3
- <%= each_value %>
4
- <%= index < value.size - 1 ? '|' : nil %>
4
+ <li><%= each_value %></li>
5
5
  <% end %>
6
6
  <% else %>
7
7
  <%= value %>
@@ -2,6 +2,11 @@
2
2
  <%= active_element.component.new_button(component.model&.new, float: 'end', class: 'mb-3') %>
3
3
  <% end %>
4
4
 
5
+
6
+ <% if title.present? %>
7
+ <%= active_element.component.page_section_title(title) %>
8
+ <% end %>
9
+
5
10
  <% if display_pagination %>
6
11
  <%=
7
12
  render partial: 'active_element/components/table/pagination',
@@ -25,15 +30,19 @@
25
30
  i18n: i18n,
26
31
  row_class_mapper: row_class_mapper } %>
27
32
  <% else %>
28
- <%= render partial: 'active_element/components/table/ungrouped_collection',
29
- locals: { component: component,
30
- collection: collection,
31
- fields: fields,
32
- show: show,
33
- edit: edit,
34
- destroy: destroy,
35
- class_name: class_name,
36
- style: style,
37
- i18n: i18n,
38
- row_class_mapper: row_class_mapper } %>
33
+ <% if collection.try(:empty?) %>
34
+ <p><i>(No items to display).</i></p>
35
+ <% else %>
36
+ <%= render partial: 'active_element/components/table/ungrouped_collection',
37
+ locals: { component: component,
38
+ collection: collection,
39
+ fields: fields,
40
+ show: show,
41
+ edit: edit,
42
+ destroy: destroy,
43
+ class_name: class_name,
44
+ style: style,
45
+ i18n: i18n,
46
+ row_class_mapper: row_class_mapper } %>
47
+ <% end %>
39
48
  <% end %>
@@ -10,6 +10,10 @@
10
10
  <%= active_element.component.new_button(component.model, float: 'end', class: 'mb-3') %>
11
11
  <% end %>
12
12
 
13
+ <% if title.present? %>
14
+ <%= active_element.component.page_section_title(title) %>
15
+ <% end %>
16
+
13
17
  <table class="<%= class_name %> table" style="<%= style %>">
14
18
  <tbody>
15
19
  <% fields.each do |field, class_mapper, label, value_mapper, options| %>
@@ -1,7 +1,21 @@
1
- <h1>Forbidden</h1>
1
+ <% if Rails.env.development? %>
2
+ <h1>Not Configured</h1>
2
3
 
3
- <h2 class="text-danger">Access to this resource has not been configured</h2>
4
+ <p>The <code><%= type %></code> resource for <code><%= controller_name.titleize %></code> has not been configured.</p>
4
5
 
5
- <p>The <span class="text-primary font-monospace"><%= type %></span> resource for <span class="text-primary font-monospace"><%= controller_name.titleize %></span> has not been configured, please contact your administrator.</p>
6
+ <p>Configure <code><%= controller.class.name %></code> like the example below:</p>
7
+
8
+ <code><pre class="border p-3">class <%= controller.class.name %>
9
+ active_element.<%= type %>_fields :name, :email, :date_of_birth
10
+ end</pre></code>
11
+
12
+ <p>This message is visible in <code>development</code> mode only.</p>
13
+ <% else %>
14
+ <h1>Forbidden</h1>
15
+
16
+ <h2 class="text-danger">Access to this resource has not been configured</h2>
17
+
18
+ <p>The <span class="text-primary font-monospace"><%= type %></span> resource for <span class="text-primary font-monospace"><%= controller_name.titleize %></span> has not been configured, please contact your administrator.</p>
19
+ <% end %>
6
20
 
7
21
  <hr/>
@@ -7,9 +7,17 @@
7
7
  fields: active_element.state.searchable_fields %>
8
8
  <% end %>
9
9
 
10
- <%= active_element.component.table new: active_element.state.creatable?,
11
- show: active_element.state.viewable?,
12
- edit: active_element.state.editable?,
13
- destroy: active_element.state.deletable?,
14
- collection: collection,
15
- fields: active_element.state.listable_fields %>
10
+ <% if active_element.state.search_required && search_filters.compact_blank.blank? %>
11
+ <% if active_element.state.creatable? %>
12
+ <%= active_element.component.new_button(collection.model&.new, float: 'end', class: 'mb-3') %>
13
+ <% end %>
14
+ <%= active_element.component.page_section_title active_element.t('search_required.title') %>
15
+ <%= active_element.component.page_description active_element.t('search_required.description') %>
16
+ <% else %>
17
+ <%= active_element.component.table new: active_element.state.creatable?,
18
+ show: active_element.state.viewable?,
19
+ edit: active_element.state.editable?,
20
+ destroy: active_element.state.deletable?,
21
+ collection: collection,
22
+ fields: active_element.state.listable_fields %>
23
+ <% end %>
@@ -1,3 +1,6 @@
1
1
  en:
2
2
  active_element:
3
3
  unexpected_error: 'Unexpected error'
4
+ search_required:
5
+ title: 'Apply search filters to view results'
6
+ description: 'This page requires at least one search filter to be applied before results will be displayed.'
@@ -1 +1 @@
1
- 2.7.8
1
+ 3.2.2
data/example_app/Gemfile CHANGED
@@ -2,8 +2,6 @@ source "https://rubygems.org"
2
2
 
3
3
  git_source(:github) { |repo| "https://github.com/#{repo}.git" }
4
4
 
5
- ruby "2.7.8"
6
-
7
5
  gem 'devise'
8
6
  gem 'faker'
9
7
  gem "rails", "~> 7.0.4", ">= 7.0.4.3"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- active_element (0.0.13)
4
+ active_element (0.0.14)
5
5
  bootstrap (~> 5.3.0alpha3)
6
6
  kaminari (~> 1.2)
7
7
  paintbrush (~> 0.1.2)
@@ -166,6 +166,8 @@ GEM
166
166
  net-smtp (0.3.3)
167
167
  net-protocol
168
168
  nio4r (2.5.9)
169
+ nokogiri (1.15.2-arm64-darwin)
170
+ racc (~> 1.4)
169
171
  nokogiri (1.15.2-x86_64-linux)
170
172
  racc (~> 1.4)
171
173
  orm_adapter (0.5.0)
@@ -234,6 +236,7 @@ GEM
234
236
  actionpack (>= 5.2)
235
237
  activesupport (>= 5.2)
236
238
  sprockets (>= 3.0.0)
239
+ sqlite3 (1.6.3-arm64-darwin)
237
240
  sqlite3 (1.6.3-x86_64-linux)
238
241
  stimulus-rails (1.2.1)
239
242
  railties (>= 6.0.0)
@@ -266,6 +269,7 @@ GEM
266
269
  zeitwerk (2.6.8)
267
270
 
268
271
  PLATFORMS
272
+ arm64-darwin-21
269
273
  x86_64-linux
270
274
 
271
275
  DEPENDENCIES
@@ -289,8 +293,5 @@ DEPENDENCIES
289
293
  web-console
290
294
  webdrivers
291
295
 
292
- RUBY VERSION
293
- ruby 2.7.8p225
294
-
295
296
  BUNDLED WITH
296
297
  2.4.13
@@ -6,7 +6,7 @@ module ActiveElement
6
6
  class Button
7
7
  # rubocop:disable Metrics/MethodLength
8
8
  def initialize(controller, record, flag_or_options, confirm: false, type: :primary, method: nil,
9
- float: nil, icon: nil, **kwargs, &block)
9
+ float: nil, icon: nil, tooltip: false, **kwargs, &block)
10
10
  @controller = controller
11
11
  @record = record.is_a?(ActiveRecord::Relation) ? record.klass.new : record
12
12
  @flag_or_options = flag_or_options
@@ -19,6 +19,7 @@ module ActiveElement
19
19
  @icon = icon
20
20
  @block_given = block_given?
21
21
  @content = block.call if block_given?
22
+ @tooltip = tooltip
22
23
  end
23
24
  # rubocop:enable Metrics/MethodLength
24
25
 
@@ -40,14 +41,15 @@ module ActiveElement
40
41
  kwargs_class: kwargs_class,
41
42
  kwargs: kwargs,
42
43
  content: content,
43
- block_given: block_given
44
+ block_given: block_given,
45
+ tooltip: tooltip
44
46
  }
45
47
  end
46
48
 
47
49
  private
48
50
 
49
51
  attr_reader :controller, :record, :flag_or_options, :float, :kwargs, :kwargs_class, :type, :method, :icon,
50
- :block_given, :content, :confirm
52
+ :block_given, :content, :confirm, :tooltip
51
53
 
52
54
  def link_method
53
55
  return method if method.present?
@@ -60,7 +62,7 @@ module ActiveElement
60
62
  when :destroy
61
63
  'btn-danger destroy-button action-button'
62
64
  when :show
63
- 'btn-primary show-button action-button'
65
+ 'btn-info show-button action-button'
64
66
  when :edit
65
67
  'btn-primary edit-button action-button'
66
68
  when :new
@@ -15,7 +15,7 @@ module ActiveElement
15
15
  # rubocop:disable Metrics/MethodLength
16
16
  def initialize(controller, class_name:, collection:, fields:, params:, model_name: nil, style: nil,
17
17
  show: false, new: false, edit: false, destroy: false, paginate: true, group: nil,
18
- group_title: false, row_class: nil, **_kwargs)
18
+ group_title: false, row_class: nil, title: nil, **_kwargs)
19
19
  @controller = controller
20
20
  @class_name = class_name
21
21
  @model_name = model_name
@@ -31,6 +31,7 @@ module ActiveElement
31
31
  @group = group
32
32
  @group_title = group_title
33
33
  @row_class = row_class
34
+ @title = title
34
35
  verify_paginate_and_group
35
36
  end
36
37
  # rubocop:enable Metrics/MethodLength
@@ -43,6 +44,7 @@ module ActiveElement
43
44
  {
44
45
  component: self,
45
46
  class_name: class_name,
47
+ title: title,
46
48
  collection: group ? collection : paginated_collection,
47
49
  fields: Util::FieldMapping.new(self, fields, class_name).mapped_fields,
48
50
  style: style,
@@ -76,10 +78,10 @@ module ActiveElement
76
78
 
77
79
  attr_reader :class_name, :collection, :fields, :style, :row_class,
78
80
  :new, :show, :edit, :destroy,
79
- :paginate, :params, :group, :group_title
81
+ :paginate, :params, :group, :group_title, :title
80
82
 
81
83
  def paginated_collection
82
- return collection unless paginate && collection.respond_to?(:page)
84
+ return collection unless paginate && collection.respond_to?(:page) && !limit?
83
85
  return collection.page(page_number).per(page_size) if supports_pagination_but_not_yet_paginated?
84
86
 
85
87
  @paginated_collection ||= collection.page(page_number).per(page_size)
@@ -99,6 +101,7 @@ module ActiveElement
99
101
 
100
102
  def display_pagination?
101
103
  return false if group.present?
104
+ return false if limit?
102
105
  return false unless paginate && paginated_collection.respond_to?(:total_count)
103
106
 
104
107
  paginated_collection.total_count > (params[:page_size].presence&.to_i || DEFAULT_PAGE_SIZE)
@@ -120,6 +123,10 @@ module ActiveElement
120
123
 
121
124
  collection.includes(fields.select { |field| collection.model.reflect_on_association(field).present? })
122
125
  end
126
+
127
+ def limit?
128
+ !collection.try(:limit_value).nil?
129
+ end
123
130
  end
124
131
  end
125
132
  end
@@ -20,6 +20,7 @@ module ActiveElement
20
20
  @item = item
21
21
  @modal = modal
22
22
  @kwargs = kwargs
23
+ @model = model
23
24
  @columns = columns
24
25
  @search = search
25
26
  @action = kwargs.delete(:action) { default_action }
@@ -40,9 +41,12 @@ module ActiveElement
40
41
  submit_label: submit_label,
41
42
  submit_position: submit_position,
42
43
  class_name: class_name,
44
+ becomes_model: becomes_model,
43
45
  method: method,
44
46
  action: action,
45
47
  kwargs: kwargs,
48
+ model_param: model_param,
49
+ record_path: record_path,
46
50
  destroy: destroy,
47
51
  modal: modal,
48
52
  columns: columns,
@@ -178,7 +182,11 @@ module ActiveElement
178
182
  end
179
183
 
180
184
  def humanized_model_name
181
- record.class.name.titleize
185
+ if record.respond_to?(:to_model)
186
+ record.to_model.model_name.name.titleize
187
+ else
188
+ record.class.name.titleize
189
+ end
182
190
  end
183
191
 
184
192
  def base_options_for_select(field, field_options)
@@ -233,10 +241,27 @@ module ActiveElement
233
241
  end
234
242
  end
235
243
 
244
+ def becomes_model
245
+ return nil unless record.is_a?(ActiveRecord::Base)
246
+ return nil if record_path.model == model
247
+
248
+ record_path.model
249
+ end
250
+
236
251
  def default_action
237
252
  return controller.request.path unless record.class.is_a?(ActiveModel::Naming)
238
253
 
239
- Util::RecordPath.new(record: record, controller: controller, type: default_action_type).path
254
+ record_path.path
255
+ end
256
+
257
+ def record_path
258
+ @record_path ||= Util::RecordPath.new(record: record, controller: controller, type: default_action_type)
259
+ end
260
+
261
+ def model_param
262
+ return nil if record.blank?
263
+
264
+ [record_path.namespace, becomes_model.present? ? record.becomes(becomes_model) : record].compact_blank
240
265
  end
241
266
  end
242
267
  end
@@ -10,7 +10,7 @@ module ActiveElement
10
10
  attr_reader :controller, :model_name
11
11
 
12
12
  def initialize(controller, item:, fields:, class_name: nil, model_name: nil,
13
- edit: false, new: false, destroy: false, style: nil, row_class: nil, **_kwargs)
13
+ edit: false, new: false, destroy: false, style: nil, row_class: nil, title: nil, **_kwargs)
14
14
  @controller = controller
15
15
  @class_name = class_name
16
16
  @model_name = model_name
@@ -21,6 +21,7 @@ module ActiveElement
21
21
  @new = new
22
22
  @style = style
23
23
  @row_class = row_class
24
+ @title = title
24
25
  end
25
26
 
26
27
  def template
@@ -37,7 +38,8 @@ module ActiveElement
37
38
  edit: edit,
38
39
  new: new,
39
40
  style: style,
40
- row_class_mapper: row_class_mapper
41
+ row_class_mapper: row_class_mapper,
42
+ title: title
41
43
  }
42
44
  end
43
45
 
@@ -47,7 +49,7 @@ module ActiveElement
47
49
 
48
50
  private
49
51
 
50
- attr_reader :class_name, :item, :fields, :edit, :new, :destroy, :style, :row_class
52
+ attr_reader :class_name, :item, :fields, :edit, :new, :destroy, :style, :row_class, :title
51
53
 
52
54
  def row_class_mapper
53
55
  row_class.is_a?(Proc) ? row_class : proc { row_class }
@@ -50,7 +50,7 @@ module ActiveElement
50
50
 
51
51
  @items ||= user_routes(controller.active_element.current_user).available.select(&:primary?).map do |route|
52
52
  { path: route.path, title: route.title, spec: route.spec }
53
- end
53
+ end.uniq { |item| item[:title] }
54
54
  end
55
55
 
56
56
  def user_routes(user)