active_element 0.0.13 → 0.0.15
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 +4 -4
- data/Gemfile.lock +16 -31
- data/app/assets/javascripts/active_element/form.js +2 -1
- data/app/assets/javascripts/active_element/json_field.js +8 -1
- data/app/views/active_element/_title.html.erb +1 -0
- data/app/views/active_element/components/button.html.erb +6 -4
- data/app/views/active_element/components/form/_check_boxes.html.erb +6 -4
- data/app/views/active_element/components/form/_date_range_field.html.erb +14 -0
- data/app/views/active_element/components/form/_field.html.erb +3 -0
- data/app/views/active_element/components/form/_summary.html.erb +10 -0
- data/app/views/active_element/components/form.html.erb +12 -2
- data/app/views/active_element/components/table/_collection_row.html.erb +3 -3
- data/app/views/active_element/components/table/_field.html.erb +2 -2
- data/app/views/active_element/components/table/collection.html.erb +20 -11
- data/app/views/active_element/components/table/item.html.erb +4 -0
- data/app/views/active_element/default_views/forbidden.html.erb +17 -3
- data/app/views/active_element/default_views/index.html.erb +14 -6
- data/app/views/layouts/active_element.html.erb +4 -2
- data/config/locales/en.yml +3 -0
- data/example_app/.ruby-version +1 -1
- data/example_app/Gemfile +0 -2
- data/example_app/Gemfile.lock +5 -4
- data/lib/active_element/components/button.rb +6 -4
- data/lib/active_element/components/collection_table.rb +10 -3
- data/lib/active_element/components/form.rb +27 -2
- data/lib/active_element/components/item_table.rb +5 -3
- data/lib/active_element/components/navbar.rb +1 -1
- data/lib/active_element/components/util/association_mapping.rb +50 -26
- data/lib/active_element/components/util/default_display_value.rb +51 -0
- data/lib/active_element/components/util/display_value_mapping.rb +10 -0
- data/lib/active_element/components/util/field_mapping.rb +2 -2
- data/lib/active_element/components/util/form_field_mapping.rb +68 -15
- data/lib/active_element/components/util/record_mapping.rb +24 -3
- data/lib/active_element/components/util/record_path.rb +51 -20
- data/lib/active_element/components/util.rb +13 -0
- data/lib/active_element/controller_interface.rb +11 -1
- data/lib/active_element/controller_state.rb +4 -2
- data/lib/active_element/default_controller/params.rb +9 -1
- data/lib/active_element/default_controller/search.rb +22 -16
- data/lib/active_element/field_options.rb +20 -0
- data/lib/active_element/version.rb +1 -1
- data/lib/active_element.rb +1 -0
- data/rspec-documentation/pages/016-Default Controller.md +10 -1
- metadata +6 -2
@@ -8,6 +8,7 @@ require_relative 'util/form_field_mapping'
|
|
8
8
|
require_relative 'util/form_value_mapping'
|
9
9
|
require_relative 'util/display_value_mapping'
|
10
10
|
require_relative 'util/association_mapping'
|
11
|
+
require_relative 'util/default_display_value'
|
11
12
|
require_relative 'util/decorator'
|
12
13
|
require_relative 'util/numeric_field'
|
13
14
|
|
@@ -23,12 +24,24 @@ module ActiveElement
|
|
23
24
|
record&.try(:model_name)&.try(&:singular) || default_record_name(record)
|
24
25
|
end
|
25
26
|
|
27
|
+
# TODO: Remove and use .sti_record_names everywhere instead.
|
26
28
|
def self.sti_record_name(record)
|
27
29
|
return default_record_name(record) unless record.class.respond_to?(:inheritance_column)
|
28
30
|
|
29
31
|
record&.class&.superclass&.model_name&.singular if record&.try(record.class.inheritance_column).present?
|
30
32
|
end
|
31
33
|
|
34
|
+
def self.sti_record_names(record) # rubocop:disable Metrics/CyclomaticComplexity
|
35
|
+
record.class.ancestors.select do |ancestor|
|
36
|
+
next false if ancestor == record.class
|
37
|
+
next false if ancestor.try(:inheritance_column).blank?
|
38
|
+
next false unless ancestor < ActiveRecord::Base
|
39
|
+
next false if ancestor.abstract_class?
|
40
|
+
|
41
|
+
true
|
42
|
+
end.map(&:model_name).map(&:singular)
|
43
|
+
end
|
44
|
+
|
32
45
|
def self.default_record_name(record)
|
33
46
|
(record.is_a?(Class) ? record.name : record.class.name).demodulize.underscore
|
34
47
|
end
|
@@ -38,10 +38,16 @@ module ActiveElement
|
|
38
38
|
state.editable_fields.concat(args.map(&:to_sym)).uniq!
|
39
39
|
end
|
40
40
|
|
41
|
-
def searchable_fields(*args)
|
41
|
+
def searchable_fields(*args, required: false)
|
42
42
|
state.searchable_fields.concat(args.map(&:to_sym)).uniq!
|
43
|
+
state.search_required = required
|
43
44
|
end
|
44
45
|
|
46
|
+
def field_options(field, &block)
|
47
|
+
state.field_options[field] = block
|
48
|
+
end
|
49
|
+
alias field field_options
|
50
|
+
|
45
51
|
def deletable
|
46
52
|
state.deletable = true
|
47
53
|
end
|
@@ -50,6 +56,10 @@ module ActiveElement
|
|
50
56
|
RailsComponent.new(::Rails).application_name
|
51
57
|
end
|
52
58
|
|
59
|
+
def t(identifier, **kwargs)
|
60
|
+
::I18n.t("active_element.#{identifier}", **kwargs)
|
61
|
+
end
|
62
|
+
|
53
63
|
def authenticate_with(&block)
|
54
64
|
state.authenticator = block
|
55
65
|
end
|
@@ -5,9 +5,10 @@ module ActiveElement
|
|
5
5
|
# configuration. Used throughout ActiveElement for generating dynamic content based on
|
6
6
|
# controller configuration.
|
7
7
|
class ControllerState
|
8
|
-
attr_reader :permissions, :listable_fields, :viewable_fields, :editable_fields, :searchable_fields
|
8
|
+
attr_reader :permissions, :listable_fields, :viewable_fields, :editable_fields, :searchable_fields,
|
9
|
+
:field_options
|
9
10
|
attr_accessor :sign_in_path, :sign_in, :sign_in_method, :sign_out_path, :sign_out_method,
|
10
|
-
:deletable, :authorizor, :authenticator, :list_order
|
11
|
+
:deletable, :authorizor, :authenticator, :list_order, :search_required
|
11
12
|
|
12
13
|
def initialize(controller:)
|
13
14
|
@controller = controller
|
@@ -19,6 +20,7 @@ module ActiveElement
|
|
19
20
|
@viewable_fields = []
|
20
21
|
@editable_fields = []
|
21
22
|
@searchable_fields = []
|
23
|
+
@field_options = {}
|
22
24
|
end
|
23
25
|
|
24
26
|
def deletable?
|
@@ -33,7 +33,15 @@ module ActiveElement
|
|
33
33
|
scalar, json = controller.active_element.state.editable_fields.partition do |field|
|
34
34
|
scalar?(field)
|
35
35
|
end
|
36
|
-
scalar + [json_params(json)]
|
36
|
+
scalar + relation_fields + [json_params(json)]
|
37
|
+
end
|
38
|
+
|
39
|
+
def relation_fields
|
40
|
+
controller.active_element.state.editable_fields.map do |field|
|
41
|
+
next nil unless relation?(field)
|
42
|
+
|
43
|
+
relation(field).try(:foreign_key)
|
44
|
+
end.compact
|
37
45
|
end
|
38
46
|
|
39
47
|
def scalar?(field)
|
@@ -25,9 +25,11 @@ module ActiveElement
|
|
25
25
|
conditions = search_filters.to_h.map do |key, value|
|
26
26
|
next relation_matches(key, value) if relation?(key)
|
27
27
|
next datetime_between(key, value) if datetime?(key)
|
28
|
+
next model.arel_table[key].matches("#{value}%") if string_like_column?(key)
|
28
29
|
|
29
|
-
model.arel_table[key].
|
30
|
+
model.arel_table[key].eq(value)
|
30
31
|
end
|
32
|
+
|
31
33
|
conditions[1..].reduce(conditions.first) do |accumulated, condition|
|
32
34
|
accumulated.and(condition)
|
33
35
|
end
|
@@ -41,12 +43,27 @@ module ActiveElement
|
|
41
43
|
|
42
44
|
attr_reader :controller, :model
|
43
45
|
|
46
|
+
def string_like_column?(key)
|
47
|
+
[:string, :text].include?(
|
48
|
+
model.columns.find { |column| column.name.to_s == key.to_s }&.type&.to_sym
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
44
52
|
def searchable_fields
|
45
|
-
controller.active_element.state.searchable_fields.map do |field|
|
53
|
+
fields = controller.active_element.state.searchable_fields.map do |field|
|
46
54
|
next field unless field.to_s.end_with?('_at')
|
47
55
|
|
48
56
|
{ field => %i[from to] }
|
49
57
|
end
|
58
|
+
(fields + relation_fields).uniq
|
59
|
+
end
|
60
|
+
|
61
|
+
def relation_fields
|
62
|
+
controller.active_element.state.searchable_fields.map do |field|
|
63
|
+
next nil unless relation?(field)
|
64
|
+
|
65
|
+
relation(field).try(:foreign_key)
|
66
|
+
end.compact
|
50
67
|
end
|
51
68
|
|
52
69
|
def noop
|
@@ -76,21 +93,10 @@ module ActiveElement
|
|
76
93
|
end
|
77
94
|
|
78
95
|
def relation_matches(key, value)
|
79
|
-
|
80
|
-
|
81
|
-
fields.select! do |field|
|
82
|
-
relation_model.columns.find { |column| column.name.to_s == field.to_s }&.type == :string
|
83
|
-
end
|
84
|
-
|
85
|
-
return noop if fields.empty?
|
96
|
+
foreign_key = relation(key).try(:foreign_key)
|
97
|
+
return noop unless foreign_key.present?
|
86
98
|
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
def relation_conditions(fields, value, relation_model)
|
91
|
-
fields[1..].reduce(relation_model.arel_table[fields.first].matches("#{value}%")) do |condition, field|
|
92
|
-
condition.or(relation_model.arel_table[field].matches("#{value}%"))
|
93
|
-
end
|
99
|
+
model.arel_table[foreign_key].eq(value)
|
94
100
|
end
|
95
101
|
|
96
102
|
def searchable_relation_fields(key)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ActiveElement
|
2
|
+
class FieldOptions
|
3
|
+
attr_accessor :type, :options
|
4
|
+
attr_reader :field
|
5
|
+
|
6
|
+
def self.from_state(field, state, record)
|
7
|
+
block = state.field_options[field]
|
8
|
+
return nil if block.blank?
|
9
|
+
|
10
|
+
field_options = new(field)
|
11
|
+
block.call(field_options, record)
|
12
|
+
field_options
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(field)
|
16
|
+
@field = field
|
17
|
+
@options = {}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/active_element.rb
CHANGED
@@ -14,6 +14,7 @@ require_relative 'active_element/permissions_report'
|
|
14
14
|
require_relative 'active_element/controller_interface'
|
15
15
|
require_relative 'active_element/controller_state'
|
16
16
|
require_relative 'active_element/controller_action'
|
17
|
+
require_relative 'active_element/field_options'
|
17
18
|
require_relative 'active_element/default_controller'
|
18
19
|
require_relative 'active_element/pre_render_processors'
|
19
20
|
require_relative 'active_element/rails_component'
|
@@ -105,7 +105,7 @@ The results will be rendered in a horizontal table with one row for each item, i
|
|
105
105
|
# app/controllers/restaurants_controller.rb
|
106
106
|
|
107
107
|
class RestaurantsController < ApplicationController
|
108
|
-
active_element.
|
108
|
+
active_element.viewable_fields :name, :restaurateur, :created_at
|
109
109
|
end
|
110
110
|
```
|
111
111
|
|
@@ -119,6 +119,15 @@ Note that each field type can be overridden and configured by defining `config/f
|
|
119
119
|
|
120
120
|
By default, `json` and `jsonb` fields use the [JSON Field](form-fields/json.html) type, allowing you to edit complex _JSON_ data structures via user-friendly _HTML_ forms. A [schema file](form-fields/json/schema.html) **must** be defined for these fields. See the `json_field` documentation for more details.
|
121
121
|
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
# app/controllers/restaurants_controller.rb
|
125
|
+
|
126
|
+
class RestaurantsController < ApplicationController
|
127
|
+
active_element.editable_fields :name, :restaurateur
|
128
|
+
end
|
129
|
+
```
|
130
|
+
|
122
131
|
## Deletable
|
123
132
|
|
124
133
|
The `active_element.deletable` declaration does not receive any arguments but specifies that a record can be deleted by a user.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_element
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Farrell
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bootstrap
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- app/assets/stylesheets/active_element/application.scss
|
132
132
|
- app/controllers/active_element/application_controller.rb
|
133
133
|
- app/controllers/concerns/active_element/default_controller_actions.rb
|
134
|
+
- app/views/active_element/_title.html.erb
|
134
135
|
- app/views/active_element/_user.html.erb
|
135
136
|
- app/views/active_element/components/_horizontal_tabs.html.erb
|
136
137
|
- app/views/active_element/components/_vertical_tabs.html.erb
|
@@ -140,6 +141,7 @@ files:
|
|
140
141
|
- app/views/active_element/components/form.html.erb
|
141
142
|
- app/views/active_element/components/form/_check_box.html.erb
|
142
143
|
- app/views/active_element/components/form/_check_boxes.html.erb
|
144
|
+
- app/views/active_element/components/form/_date_range_field.html.erb
|
143
145
|
- app/views/active_element/components/form/_datetime_range_field.html.erb
|
144
146
|
- app/views/active_element/components/form/_field.html.erb
|
145
147
|
- app/views/active_element/components/form/_generic_field.html.erb
|
@@ -307,6 +309,7 @@ files:
|
|
307
309
|
- lib/active_element/components/util.rb
|
308
310
|
- lib/active_element/components/util/association_mapping.rb
|
309
311
|
- lib/active_element/components/util/decorator.rb
|
312
|
+
- lib/active_element/components/util/default_display_value.rb
|
310
313
|
- lib/active_element/components/util/display_value_mapping.rb
|
311
314
|
- lib/active_element/components/util/field_mapping.rb
|
312
315
|
- lib/active_element/components/util/form_field_mapping.rb
|
@@ -325,6 +328,7 @@ files:
|
|
325
328
|
- lib/active_element/default_controller/params.rb
|
326
329
|
- lib/active_element/default_controller/search.rb
|
327
330
|
- lib/active_element/engine.rb
|
331
|
+
- lib/active_element/field_options.rb
|
328
332
|
- lib/active_element/json_field_schema.rb
|
329
333
|
- lib/active_element/permissions_check.rb
|
330
334
|
- lib/active_element/permissions_report.rb
|