super 0.0.2 → 0.0.7
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/.yardopts +11 -0
- data/README.md +68 -76
- data/app/assets/javascripts/super/application.js +1252 -316
- data/app/assets/stylesheets/super/application.css +102704 -17321
- data/app/controllers/super/application_controller.rb +49 -71
- data/app/views/layouts/super/application.html.erb +10 -8
- data/app/views/super/application/_collection_header.html.erb +15 -0
- data/app/views/super/application/_filter.html.erb +14 -0
- data/app/views/super/application/_filter_type_select.html.erb +31 -0
- data/app/views/super/application/_filter_type_text.html.erb +22 -0
- data/app/views/super/application/_filter_type_timestamp.html.erb +35 -0
- data/app/views/super/application/_flash.html.erb +13 -13
- data/app/views/super/application/_form_field__destroy.html.erb +9 -0
- data/app/views/super/application/_form_field_select.html.erb +23 -0
- data/app/views/super/application/_form_field_text.html.erb +13 -0
- data/app/views/super/application/_form_fieldset.html.erb +8 -0
- data/app/views/super/application/_form_has_many.html.erb +21 -0
- data/app/views/super/application/_form_has_one.html.erb +11 -0
- data/app/views/super/application/_form_inline_errors.html.erb +10 -0
- data/app/views/super/application/_member_header.html.erb +16 -0
- data/app/views/super/application/_super_layout.html.erb +29 -0
- data/app/views/super/application/_super_pagination.html.erb +16 -0
- data/app/views/super/application/_super_panel.html.erb +7 -0
- data/app/views/super/application/_super_schema_display_actions.html.erb +5 -0
- data/app/views/super/application/_super_schema_display_index.html.erb +24 -0
- data/app/views/super/application/_super_schema_display_show.html.erb +8 -0
- data/app/views/super/application/_super_schema_form.html.erb +15 -0
- data/app/views/super/application/edit.html.erb +1 -6
- data/app/views/super/application/index.html.erb +1 -1
- data/app/views/super/application/new.html.erb +1 -6
- data/app/views/super/application/show.html.erb +1 -1
- data/app/views/super/feather/{_chevron_down.svg → _chevron_down.html} +0 -0
- data/config/locales/en.yml +5 -0
- data/docs/README.md +6 -0
- data/docs/cheat.md +41 -0
- data/docs/faq.md +44 -0
- data/docs/quick_start.md +45 -0
- data/docs/webpacker.md +17 -0
- data/docs/yard_customizations.rb +41 -0
- data/frontend/super-frontend/build.js +14 -12
- data/frontend/super-frontend/dist/application.css +102704 -17321
- data/frontend/super-frontend/dist/application.js +1252 -316
- data/frontend/super-frontend/package.json +11 -4
- data/frontend/super-frontend/postcss.config.js +4 -4
- data/frontend/super-frontend/src/javascripts/super/application.ts +18 -0
- data/frontend/super-frontend/src/javascripts/super/apply_template_controller.ts +19 -0
- data/frontend/super-frontend/src/javascripts/super/rails__ujs.d.ts +1 -0
- data/frontend/super-frontend/src/javascripts/super/toggle_pending_destruction_controller.ts +15 -0
- data/frontend/super-frontend/src/stylesheets/super/application.css +63 -0
- data/frontend/super-frontend/tailwind.config.js +12 -4
- data/frontend/super-frontend/tsconfig.json +13 -0
- data/frontend/super-frontend/yarn.lock +1891 -1798
- data/lib/generators/super/install/install_generator.rb +16 -0
- data/lib/generators/super/webpacker/webpacker_generator.rb +8 -0
- data/lib/super.rb +16 -6
- data/lib/super/action_inquirer.rb +14 -1
- data/lib/super/assets.rb +1 -0
- data/lib/super/client_error.rb +43 -0
- data/lib/super/compatibility.rb +25 -0
- data/lib/super/configuration.rb +66 -44
- data/lib/super/controls.rb +26 -15
- data/lib/super/controls/optional.rb +54 -0
- data/lib/super/controls/required.rb +41 -0
- data/lib/super/controls/steps.rb +128 -0
- data/lib/super/display/schema_types.rb +90 -18
- data/lib/super/engine.rb +7 -0
- data/lib/super/error.rb +9 -8
- data/lib/super/filter.rb +137 -0
- data/lib/super/filter/operator.rb +103 -0
- data/lib/super/filter/schema_types.rb +118 -0
- data/lib/super/form.rb +48 -0
- data/lib/super/form/schema_types.rb +96 -21
- data/lib/super/layout.rb +47 -0
- data/lib/super/link.rb +110 -0
- data/lib/super/navigation/automatic.rb +2 -0
- data/lib/super/pagination.rb +80 -8
- data/lib/super/panel.rb +30 -0
- data/lib/super/partial.rb +23 -0
- data/lib/super/partial/resolving.rb +24 -0
- data/lib/super/plugin.rb +34 -63
- data/lib/super/schema.rb +65 -1
- data/lib/super/version.rb +1 -1
- data/lib/super/view_helper.rb +43 -0
- metadata +132 -33
- data/app/views/super/application/_form.html.erb +0 -15
- data/app/views/super/application/_form_field.html.erb +0 -7
- data/app/views/super/application/_form_generic_select.html.erb +0 -19
- data/app/views/super/application/_form_generic_text.html.erb +0 -7
- data/app/views/super/application/_index.html.erb +0 -60
- data/app/views/super/application/_show.html.erb +0 -12
- data/frontend/super-frontend/src/javascripts/super/application.js +0 -11
- data/lib/super/display.rb +0 -9
- data/lib/super/inline_callback.rb +0 -82
- data/lib/super/test_support/copy_app_templates/20190216224956_create_members.rb +0 -11
- data/lib/super/test_support/copy_app_templates/20190803143320_create_ships.rb +0 -11
- data/lib/super/test_support/copy_app_templates/20190806014121_add_ship_to_members.rb +0 -5
- data/lib/super/test_support/copy_app_templates/member.rb +0 -16
- data/lib/super/test_support/copy_app_templates/members_controller.rb +0 -52
- data/lib/super/test_support/copy_app_templates/routes.rb +0 -10
- data/lib/super/test_support/copy_app_templates/seeds.rb +0 -2
- data/lib/super/test_support/copy_app_templates/ship.rb +0 -3
- data/lib/super/test_support/copy_app_templates/ships_controller.rb +0 -47
- data/lib/super/test_support/fixtures/members.yml +0 -336
- data/lib/super/test_support/fixtures/ships.yml +0 -10
- data/lib/super/test_support/generate_copy_app.rb +0 -52
- data/lib/super/test_support/generate_dummy.rb +0 -94
- data/lib/super/test_support/starfleet_seeder.rb +0 -49
- data/lib/super/view.rb +0 -25
- data/lib/tasks/super_tasks.rake +0 -4
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
module Super
|
|
2
|
+
class Controls
|
|
3
|
+
# Methods that are called by controller actions. All of these methods have
|
|
4
|
+
# a default implementation, but feel free to override as needed.
|
|
5
|
+
module Steps
|
|
6
|
+
# Tells the controller how to load records in the index action using
|
|
7
|
+
# `#scope`
|
|
8
|
+
#
|
|
9
|
+
# @param action [ActionInquirer]
|
|
10
|
+
# @param params [ActionController::Parameters]
|
|
11
|
+
# @return [ActiveRecord::Relation]
|
|
12
|
+
def load_records(action:, params:)
|
|
13
|
+
default_for(:load_records, action: action, params: params) do
|
|
14
|
+
scope(action: action)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Loads a record using `#scope`
|
|
19
|
+
#
|
|
20
|
+
# @param action [ActionInquirer]
|
|
21
|
+
# @param params [ActionController::Parameters]
|
|
22
|
+
# @return [ActiveRecord::Base]
|
|
23
|
+
def load_record(action:, params:)
|
|
24
|
+
default_for(:load_record, action: action, params: params) do
|
|
25
|
+
scope(action: action).find(params[:id])
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Builds a record using `#scope`
|
|
30
|
+
#
|
|
31
|
+
# @param action [ActionInquirer]
|
|
32
|
+
# @return [ActiveRecord::Base]
|
|
33
|
+
def build_record(action:)
|
|
34
|
+
default_for(:build_record) do
|
|
35
|
+
scope(action: action).build
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Builds and populates a record using `#scope`
|
|
40
|
+
#
|
|
41
|
+
# @param action [ActionInquirer]
|
|
42
|
+
# @param params [ActionController::Parameters]
|
|
43
|
+
# @return [ActiveRecord::Base]
|
|
44
|
+
def build_record_with_params(action:, params:)
|
|
45
|
+
default_for(:build_record_with_params, action: action, params: params) do
|
|
46
|
+
scope(action: action).build(permitted_params(params, action: action))
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Saves a record
|
|
51
|
+
#
|
|
52
|
+
# @param action [ActionInquirer]
|
|
53
|
+
# @param params [ActionController::Parameters]
|
|
54
|
+
# @return [ActiveRecord::Base]
|
|
55
|
+
def save_record(action:, record:, params:)
|
|
56
|
+
default_for(:save_record, action: action, record: record, params: params) do
|
|
57
|
+
record.save
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Saves a record
|
|
62
|
+
#
|
|
63
|
+
# @param action [ActionInquirer]
|
|
64
|
+
# @param params [ActionController::Parameters]
|
|
65
|
+
# @return [ActiveRecord::Base]
|
|
66
|
+
def update_record(action:, record:, params:)
|
|
67
|
+
default_for(:update_record, action: action, record: record, params: params) do
|
|
68
|
+
record.update(permitted_params(params, action: action))
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Destroys a record
|
|
73
|
+
#
|
|
74
|
+
# @param action [ActionInquirer]
|
|
75
|
+
# @param params [ActionController::Parameters]
|
|
76
|
+
# @return [ActiveRecord::Base, false]
|
|
77
|
+
def destroy_record(action:, record:, params:)
|
|
78
|
+
default_for(:update_record, action: action, record: record, params: params) do
|
|
79
|
+
record.destroy
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def build_index_view
|
|
84
|
+
Super::Layout.new(
|
|
85
|
+
mains: [
|
|
86
|
+
Super::Panel.new(
|
|
87
|
+
Super::Partial.new("collection_header"),
|
|
88
|
+
:@display
|
|
89
|
+
),
|
|
90
|
+
]
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def build_show_view
|
|
95
|
+
Super::Layout.new(
|
|
96
|
+
mains: [
|
|
97
|
+
Super::Panel.new(
|
|
98
|
+
Super::Partial.new("member_header"),
|
|
99
|
+
:@display
|
|
100
|
+
),
|
|
101
|
+
]
|
|
102
|
+
)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def build_new_view
|
|
106
|
+
Super::Layout.new(
|
|
107
|
+
mains: [
|
|
108
|
+
Super::Panel.new(
|
|
109
|
+
Super::Partial.new("collection_header"),
|
|
110
|
+
:@form
|
|
111
|
+
),
|
|
112
|
+
]
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def build_edit_view
|
|
117
|
+
Super::Layout.new(
|
|
118
|
+
mains: [
|
|
119
|
+
Super::Panel.new(
|
|
120
|
+
Super::Partial.new("member_header"),
|
|
121
|
+
:@form
|
|
122
|
+
),
|
|
123
|
+
]
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -3,39 +3,111 @@ module Super
|
|
|
3
3
|
# This schema type is meant to be used for +#index+ or +#show+ actions to
|
|
4
4
|
# transform database fields into something that is human friendly.
|
|
5
5
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
6
|
+
# ```
|
|
7
|
+
# class MembersController::Controls
|
|
8
|
+
# # ...
|
|
8
9
|
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
# fields[:ship] = type.dynamic { |ship| "#{ship.name} (Ship ##{ship.id})" }
|
|
18
|
-
# fields[:created_at] = type.dynamic { |created_at| created_at.iso8601 }
|
|
19
|
-
# fields[:updated_at] = type.dynamic { |updated_at| updated_at.iso8601 }
|
|
20
|
-
# end
|
|
10
|
+
# def show_schema
|
|
11
|
+
# Super::Schema.new(Super::Display::SchemaTypes.new) do |fields, type|
|
|
12
|
+
# fields[:name] = type.dynamic { |name| name }
|
|
13
|
+
# fields[:rank] = type.dynamic { |rank| rank }
|
|
14
|
+
# fields[:position] = type.dynamic { |position| position }
|
|
15
|
+
# fields[:ship] = type.dynamic { |ship| "#{ship.name} (Ship ##{ship.id})" }
|
|
16
|
+
# fields[:created_at] = type.dynamic { |created_at| created_at.iso8601 }
|
|
17
|
+
# fields[:updated_at] = type.dynamic { |updated_at| updated_at.iso8601 }
|
|
21
18
|
# end
|
|
22
|
-
#
|
|
23
|
-
# # ...
|
|
24
19
|
# end
|
|
20
|
+
#
|
|
21
|
+
# # ...
|
|
22
|
+
# end
|
|
23
|
+
# ```
|
|
25
24
|
class SchemaTypes
|
|
26
25
|
class Dynamic
|
|
27
26
|
def initialize(transform_block)
|
|
28
27
|
@transform_block = transform_block
|
|
29
28
|
end
|
|
30
29
|
|
|
31
|
-
def present(
|
|
32
|
-
@transform_block.call(
|
|
30
|
+
def present(value)
|
|
31
|
+
@transform_block.call(value)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def real?
|
|
35
|
+
true
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class Bypass
|
|
40
|
+
def initialize(partial:, real:)
|
|
41
|
+
@partial = partial
|
|
42
|
+
@real = real
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def present
|
|
46
|
+
Partial.new(@partial)
|
|
33
47
|
end
|
|
48
|
+
|
|
49
|
+
def real?
|
|
50
|
+
@real
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def initialize(action_inquirer)
|
|
55
|
+
@action_inquirer = action_inquirer
|
|
56
|
+
@actions_called = false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def before_yield(fields:)
|
|
60
|
+
@fields = fields
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def after_yield
|
|
64
|
+
return if !@action_inquirer.index?
|
|
65
|
+
return if @actions_called
|
|
66
|
+
@fields[:actions] = actions
|
|
34
67
|
end
|
|
35
68
|
|
|
36
69
|
def dynamic(&transform_block)
|
|
37
70
|
Dynamic.new(transform_block)
|
|
38
71
|
end
|
|
72
|
+
|
|
73
|
+
def actions
|
|
74
|
+
@actions_called = true
|
|
75
|
+
Bypass.new(partial: "super_schema_display_actions", real: false)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def to_partial_path
|
|
79
|
+
if @action_inquirer.index?
|
|
80
|
+
"super_schema_display_index"
|
|
81
|
+
elsif @action_inquirer.show?
|
|
82
|
+
"super_schema_display_show"
|
|
83
|
+
else
|
|
84
|
+
"super_schema_display_#{@action_inquirer.action}"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# @private
|
|
89
|
+
def render_field(template:, record:, column:)
|
|
90
|
+
formatter = @fields[column]
|
|
91
|
+
|
|
92
|
+
formatted =
|
|
93
|
+
if formatter.real?
|
|
94
|
+
value = record.public_send(column)
|
|
95
|
+
formatter.present(value)
|
|
96
|
+
else
|
|
97
|
+
formatter.present
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
if formatted.respond_to?(:to_partial_path)
|
|
101
|
+
if formatted.respond_to?(:locals)
|
|
102
|
+
formatted.locals[:record] ||= record
|
|
103
|
+
template.render(formatted, formatted.locals)
|
|
104
|
+
else
|
|
105
|
+
template.render(formatted)
|
|
106
|
+
end
|
|
107
|
+
else
|
|
108
|
+
formatted
|
|
109
|
+
end
|
|
110
|
+
end
|
|
39
111
|
end
|
|
40
112
|
end
|
|
41
113
|
end
|
data/lib/super/engine.rb
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
module Super
|
|
2
|
+
# Configures the host Rails app to work with Super
|
|
2
3
|
class Engine < ::Rails::Engine
|
|
3
4
|
initializer "super.assets.precompile" do |app|
|
|
4
5
|
if Super::Assets.sprockets_available?
|
|
5
6
|
app.config.assets.precompile << "config/super_manifest.js"
|
|
6
7
|
end
|
|
7
8
|
end
|
|
9
|
+
|
|
10
|
+
config.to_prepare do
|
|
11
|
+
Super::Plugin::Registry.controller.ordered do |klass, method_name|
|
|
12
|
+
Super::ApplicationController.public_send(method_name, klass)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
8
15
|
end
|
|
9
16
|
end
|
data/lib/super/error.rb
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
module Super
|
|
2
|
+
# A container class for all internal errors thrown by this library
|
|
3
|
+
#
|
|
4
|
+
# See also `Super::ClientError`
|
|
2
5
|
class Error < StandardError
|
|
6
|
+
# Error raised when some configuration is not set
|
|
3
7
|
class UnconfiguredConfiguration < Error; end
|
|
8
|
+
# Error raised when a configuration is set to a invalid value
|
|
4
9
|
class InvalidConfiguration < Error; end
|
|
5
|
-
|
|
10
|
+
# Error raised on problematic plugins, see `Super::Plugin`
|
|
6
11
|
class InvalidPluginArgument < Error; end
|
|
12
|
+
# Error raised on problematic ActionInquirer settings, see `Super::ActionInquirer`
|
|
7
13
|
class ActionInquirerError < Error; end
|
|
8
|
-
|
|
9
|
-
class
|
|
10
|
-
class BadRequest < ClientError; end
|
|
11
|
-
class Unauthorized < ClientError; end
|
|
12
|
-
class Forbidden < ClientError; end
|
|
13
|
-
class NotFound < ClientError; end
|
|
14
|
-
class UnprocessableEntity < ClientError; end
|
|
14
|
+
# Error raised when a `Super::Link` couldn't be found
|
|
15
|
+
class LinkNotRegistered < Error; end
|
|
15
16
|
end
|
|
16
17
|
end
|
data/lib/super/filter.rb
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
module Super
|
|
2
|
+
class Filter
|
|
3
|
+
module ControllerMethods
|
|
4
|
+
def index
|
|
5
|
+
super
|
|
6
|
+
@filter_form = controls.initialize_filtering(params: params, query_params: request.GET)
|
|
7
|
+
@records = controls.filter_records(filter_form: @filter_form, records: @records)
|
|
8
|
+
@view.asides.push(:@filter_form)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class FilterFormField
|
|
13
|
+
def initialize(humanized_field_name:, field_name:, type:, params:)
|
|
14
|
+
@humanized_field_name = humanized_field_name
|
|
15
|
+
@field_name = field_name
|
|
16
|
+
@field_type = type
|
|
17
|
+
@params = params
|
|
18
|
+
@specified_values =
|
|
19
|
+
type.q
|
|
20
|
+
.map do |query_field_name|
|
|
21
|
+
[
|
|
22
|
+
query_field_name,
|
|
23
|
+
(params || {})[query_field_name],
|
|
24
|
+
]
|
|
25
|
+
end
|
|
26
|
+
.to_h
|
|
27
|
+
|
|
28
|
+
@specified_values.each do |key, value|
|
|
29
|
+
define_singleton_method(key) { value }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attr_reader :humanized_field_name
|
|
34
|
+
attr_reader :field_name
|
|
35
|
+
attr_reader :field_type
|
|
36
|
+
attr_reader :specified_values
|
|
37
|
+
|
|
38
|
+
def op
|
|
39
|
+
(@params || {})[:op]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def operators
|
|
43
|
+
@field_type.operators
|
|
44
|
+
.map { |o| [o.name, o.identifier] }
|
|
45
|
+
.to_h
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def to_partial_path
|
|
49
|
+
@field_type.to_partial_path
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def initialize(model:, url:, schema:, params:)
|
|
54
|
+
@model = model
|
|
55
|
+
@url = url
|
|
56
|
+
@schema = schema
|
|
57
|
+
@params = params
|
|
58
|
+
|
|
59
|
+
@form_fields = {}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def each_field
|
|
63
|
+
@schema.fields.each do |field_name, _field_type|
|
|
64
|
+
yield(form_field_for(field_name))
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def url
|
|
69
|
+
@url
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def to_partial_path
|
|
73
|
+
"filter"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def to_search_query(relation)
|
|
77
|
+
each_field do |form_field|
|
|
78
|
+
next if form_field.specified_values.values.map(&:to_s).map(&:strip).all? { |specified_value| specified_value == "" }
|
|
79
|
+
next if !Super::Filter::Operator.registry.key?(form_field.op)
|
|
80
|
+
|
|
81
|
+
operator = Super::Filter::Operator.registry[form_field.op]
|
|
82
|
+
updated_relation = operator.filter(relation, form_field.field_name, *form_field.specified_values.values)
|
|
83
|
+
|
|
84
|
+
if updated_relation.is_a?(ActiveRecord::Relation)
|
|
85
|
+
relation = updated_relation
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
relation
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def form_field_for(field_name)
|
|
95
|
+
@form_fields[field_name] ||=
|
|
96
|
+
FilterFormField.new(
|
|
97
|
+
humanized_field_name: @model.human_attribute_name(field_name),
|
|
98
|
+
field_name: field_name,
|
|
99
|
+
type: @schema.fields[field_name],
|
|
100
|
+
params: (@params || {})[field_name]
|
|
101
|
+
)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class Controls
|
|
106
|
+
module Optional
|
|
107
|
+
def filters_enabled?
|
|
108
|
+
actual.respond_to?(:filter_schema)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def filter_schema
|
|
112
|
+
actual.filter_schema
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
module Steps
|
|
117
|
+
def initialize_filtering(params:, query_params:)
|
|
118
|
+
if filters_enabled?
|
|
119
|
+
Super::Filter.new(
|
|
120
|
+
model: model,
|
|
121
|
+
schema: filter_schema,
|
|
122
|
+
params: params[:q],
|
|
123
|
+
url: query_params
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def filter_records(filter_form:, records:)
|
|
129
|
+
if filters_enabled? && records
|
|
130
|
+
filter_form.to_search_query(records)
|
|
131
|
+
else
|
|
132
|
+
records
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
module Super
|
|
2
|
+
class Filter
|
|
3
|
+
module Operator
|
|
4
|
+
class Definition
|
|
5
|
+
def initialize(identifier, name, filter)
|
|
6
|
+
@identifier = identifier
|
|
7
|
+
@name = name
|
|
8
|
+
@filter = filter
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
attr_reader :identifier
|
|
12
|
+
attr_reader :name
|
|
13
|
+
|
|
14
|
+
def filter(*args)
|
|
15
|
+
@filter.call(args)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
def registry
|
|
21
|
+
@registry ||= {}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def range_defaults
|
|
25
|
+
[
|
|
26
|
+
registry["between"],
|
|
27
|
+
]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def select_defaults
|
|
31
|
+
[
|
|
32
|
+
registry["eq"],
|
|
33
|
+
registry["neq"],
|
|
34
|
+
]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def text_defaults
|
|
38
|
+
[
|
|
39
|
+
registry["eq"],
|
|
40
|
+
registry["neq"],
|
|
41
|
+
registry["contain"],
|
|
42
|
+
registry["ncontain"],
|
|
43
|
+
registry["start"],
|
|
44
|
+
registry["end"],
|
|
45
|
+
]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def define(identifier, name, &filter)
|
|
49
|
+
identifier = identifier.to_s
|
|
50
|
+
name = name.to_s
|
|
51
|
+
|
|
52
|
+
definition = Definition.new(identifier, name, filter)
|
|
53
|
+
|
|
54
|
+
registry[identifier] = definition
|
|
55
|
+
|
|
56
|
+
define_singleton_method(identifier) do
|
|
57
|
+
registry[identifier]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
define("eq", "equals") do |relation, field, query|
|
|
63
|
+
relation.where(field => query)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
define("neq", "doesn't equal") do |relation, field, query|
|
|
67
|
+
relation.where.not(field => query)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
define("contain", "contains") do |relation, field, query|
|
|
71
|
+
query = "%#{Compatability.sanitize_sql_like(query)}%"
|
|
72
|
+
relation.where("#{field} LIKE ?", "%#{query}%")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
define("ncontain", "doesn't contain") do |relation, field, query|
|
|
76
|
+
query = "%#{Compatability.sanitize_sql_like(query)}%"
|
|
77
|
+
relation.where("#{field} NOT LIKE ?", query)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
define("start", "starts with") do |relation, field, query|
|
|
81
|
+
query = "#{Compatability.sanitize_sql_like(query)}%"
|
|
82
|
+
relation.where("#{field} LIKE ?", query)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
define("end", "ends with") do |relation, field, query|
|
|
86
|
+
query = "%#{Compatability.sanitize_sql_like(query)}"
|
|
87
|
+
relation.where("#{field} LIKE ?", query)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
define("between", "between") do |relation, field, query0, query1|
|
|
91
|
+
if query0.present?
|
|
92
|
+
relation = relation.where("#{field} >= ?", query0)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
if query1.present?
|
|
96
|
+
relation = relation.where("#{field} <= ?", query1)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
relation
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|