active_element 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +3 -3
  4. data/app/assets/javascripts/active_element/highlight.js +311 -0
  5. data/app/assets/javascripts/active_element/json_field.js +51 -20
  6. data/app/assets/javascripts/active_element/popover.js +6 -4
  7. data/app/assets/stylesheets/active_element/_dark.scss +1 -1
  8. data/app/assets/stylesheets/active_element/application.scss +39 -1
  9. data/app/controllers/concerns/active_element/default_controller_actions.rb +7 -7
  10. data/app/views/active_element/components/fields/_json.html.erb +3 -2
  11. data/app/views/active_element/components/form/_field.html.erb +2 -1
  12. data/app/views/active_element/components/form/_json.html.erb +2 -0
  13. data/app/views/active_element/components/form/_label.html.erb +7 -0
  14. data/app/views/active_element/components/form.html.erb +2 -2
  15. data/app/views/layouts/active_element.html.erb +25 -4
  16. data/example_app/Gemfile.lock +1 -1
  17. data/lib/active_element/components/form.rb +1 -8
  18. data/lib/active_element/components/util/display_value_mapping.rb +0 -2
  19. data/lib/active_element/components/util/form_field_mapping.rb +2 -1
  20. data/lib/active_element/components/util.rb +7 -0
  21. data/lib/active_element/controller_interface.rb +2 -1
  22. data/lib/active_element/controller_state.rb +1 -1
  23. data/lib/active_element/default_controller/actions.rb +3 -0
  24. data/lib/active_element/default_controller/controller.rb +145 -0
  25. data/lib/active_element/default_controller/json_params.rb +48 -0
  26. data/lib/active_element/default_controller/params.rb +97 -0
  27. data/lib/active_element/default_controller/search.rb +112 -0
  28. data/lib/active_element/default_controller.rb +10 -132
  29. data/lib/active_element/version.rb +1 -1
  30. data/lib/active_element.rb +0 -2
  31. data/rspec-documentation/_head.html.erb +2 -0
  32. data/rspec-documentation/pages/000-Introduction.md +8 -5
  33. data/rspec-documentation/pages/005-Setup.md +21 -28
  34. data/rspec-documentation/pages/010-Components/Form Fields.md +35 -0
  35. data/rspec-documentation/pages/015-Custom Controllers.md +32 -0
  36. data/rspec-documentation/pages/016-Default Controller.md +132 -0
  37. data/rspec-documentation/pages/Themes.md +3 -0
  38. metadata +11 -4
  39. data/lib/active_element/default_record_params.rb +0 -62
  40. data/lib/active_element/default_search.rb +0 -110
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveElement
4
- # Provides params for ActiveRecord models when using the default boilerplate controller
5
- # actions. Navigates input parameters and maps them to appropriate relations as needed.
6
- class DefaultRecordParams
7
- def initialize(controller:, model:)
8
- @controller = controller
9
- @model = model
10
- end
11
-
12
- def params
13
- with_transformed_relations(
14
- controller.params.require(controller.controller_name.singularize)
15
- .permit(controller.active_element.state.editable_fields)
16
- )
17
- end
18
-
19
- private
20
-
21
- attr_reader :controller, :model
22
-
23
- def with_transformed_relations(params)
24
- params.to_h.to_h do |key, value|
25
- next [key, value] unless relation?(key)
26
-
27
- relation_param(key, value)
28
- end
29
- end
30
-
31
- def relation_param(key, value)
32
- case relation(key).macro
33
- when :belongs_to
34
- belongs_to_param(key, value)
35
- when :has_one
36
- has_one_param(key, value)
37
- when :has_many
38
- has_many_param(key, value)
39
- end
40
- end
41
-
42
- def belongs_to_param(key, value)
43
- [relation(key).foreign_key, value]
44
- end
45
-
46
- def has_one_param(key, value) # rubocop:disable Naming/PredicateName
47
- [relation(key).name, relation(key).klass.find_by(relation(key).klass.primary_key => value)]
48
- end
49
-
50
- def has_many_param(key, _value) # rubocop:disable Naming/PredicateName
51
- [relation(key).name, relation(key).klass.where(relation(key).klass.primary_key => relation(key).value)]
52
- end
53
-
54
- def relation?(attribute)
55
- relation(attribute.to_sym).present?
56
- end
57
-
58
- def relation(attribute)
59
- model.reflect_on_association(attribute.to_sym)
60
- end
61
- end
62
- end
@@ -1,110 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveElement
4
- # Full text search and datetime querying for DefaultController, provides full text search
5
- # filters for all controllers with configured searchable fields. Includes support for querying
6
- # across relations.
7
- class DefaultSearch
8
- def initialize(controller:, model:)
9
- @controller = controller
10
- @model = model
11
- end
12
-
13
- def search_filters
14
- @search_filters ||= controller.params.permit(*searchable_fields).transform_values do |value|
15
- value.try(:compact_blank) || value
16
- end.compact_blank
17
- end
18
-
19
- def text_search?
20
- search_filters.present?
21
- end
22
-
23
- def text_search
24
- conditions = search_filters.to_h.map do |key, value|
25
- next relation_matches(key, value) if relation?(key)
26
- next datetime_between(key, value) if datetime?(key)
27
-
28
- model.arel_table[key].matches("#{value}%")
29
- end
30
- conditions[1..].reduce(conditions.first) do |accumulated, condition|
31
- accumulated.and(condition)
32
- end
33
- end
34
-
35
- def search_relations
36
- search_filters.to_h.keys.map { |key| relation?(key) ? key.to_sym : nil }.compact
37
- end
38
-
39
- private
40
-
41
- attr_reader :controller, :model
42
-
43
- def searchable_fields
44
- controller.active_element.state.searchable_fields.map do |field|
45
- next field unless field.to_s.end_with?('_at')
46
-
47
- { field => %i[from to] }
48
- end
49
- end
50
-
51
- def noop
52
- Arel::Nodes::True.new.eq(Arel::Nodes::True.new)
53
- end
54
-
55
- def datetime?(key)
56
- model.columns.find { |column| column.name.to_s == key.to_s }&.type == :datetime
57
- end
58
-
59
- def datetime_between(key, value)
60
- return noop if value[:from].blank? && value[:to].blank?
61
-
62
- model.arel_table[key].between(range_begin(value)...range_end(value))
63
- end
64
-
65
- def range_begin(value)
66
- value[:from].present? ? Time.zone.parse(value[:from]) + timezone_offset : -Float::INFINITY
67
- end
68
-
69
- def range_end(value)
70
- value[:to].present? ? Time.zone.parse(value[:to]) + timezone_offset : Float::INFINITY
71
- end
72
-
73
- def timezone_offset
74
- controller.request.cookies['timezone_offset'].to_i.minutes
75
- end
76
-
77
- def relation_matches(key, value)
78
- fields = searchable_relation_fields(key)
79
- relation_model = relation(key).klass
80
- fields.select! do |field|
81
- relation_model.columns.find { |column| column.name.to_s == field.to_s }&.type == :string
82
- end
83
-
84
- return noop if fields.empty?
85
-
86
- relation_conditions(fields, value, relation_model)
87
- end
88
-
89
- def relation_conditions(fields, value, relation_model)
90
- fields[1..].reduce(relation_model.arel_table[fields.first].matches("#{value}%")) do |condition, field|
91
- condition.or(relation_model.arel_table[field].matches("#{value}%"))
92
- end
93
- end
94
-
95
- def searchable_relation_fields(key)
96
- Components::Util.relation_controller(model, controller, key)
97
- &.active_element
98
- &.state
99
- &.fetch(:searchable_fields, []) || []
100
- end
101
-
102
- def relation?(attribute)
103
- relation(attribute.to_sym).present?
104
- end
105
-
106
- def relation(attribute)
107
- model.reflect_on_association(attribute.to_sym)
108
- end
109
- end
110
- end