super 0.0.6 → 0.0.11
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 +2 -0
- data/CONTRIBUTING.md +56 -0
- data/README.md +55 -57
- data/Rakefile +16 -14
- data/STABILITY.md +50 -0
- data/app/assets/javascripts/super/application.js +297 -97
- data/app/assets/stylesheets/super/application.css +5600 -0
- data/app/controllers/super/application_controller.rb +15 -6
- data/app/helpers/super/form_builder_helper.rb +25 -0
- data/app/views/layouts/super/application.html.erb +22 -6
- data/app/views/super/application/_display_rich_text.html.erb +1 -0
- data/app/views/super/application/_filter.html.erb +6 -0
- data/app/views/super/application/_filter_type_select.html.erb +21 -0
- data/app/views/super/application/_filter_type_text.html.erb +18 -0
- data/app/views/super/application/_filter_type_timestamp.html.erb +24 -0
- data/app/views/super/application/_form_field__destroy.html.erb +1 -9
- data/app/views/super/application/_form_field_checkbox.html.erb +1 -0
- data/app/views/super/application/_form_field_rich_text_area.html.erb +1 -0
- data/app/views/super/application/_form_field_select.html.erb +1 -23
- data/app/views/super/application/_form_field_text.html.erb +1 -13
- data/app/views/super/application/_query.html.erb +18 -0
- data/app/views/super/application/_sort.html.erb +18 -0
- data/app/views/super/application/_sort_expression.html.erb +25 -0
- data/app/views/super/application/_super_layout.html.erb +5 -5
- data/app/views/super/application/_super_pagination.html.erb +16 -0
- data/app/views/super/application/_super_panel.html.erb +2 -2
- data/app/views/super/application/_super_schema_display_index.html.erb +9 -24
- data/app/views/super/application/_super_schema_display_show.html.erb +4 -4
- data/app/views/super/application/_super_schema_form.html.erb +3 -3
- data/app/views/super/application/edit.html.erb +2 -6
- data/app/views/super/application/index.html.erb +2 -6
- data/app/views/super/application/new.html.erb +2 -6
- data/app/views/super/application/show.html.erb +2 -6
- data/app/views/super/feather/README.md +1 -0
- data/app/views/super/feather/_x.html +15 -0
- data/config/routes.rb +2 -0
- data/docs/README.md +4 -2
- data/docs/action_text.md +48 -0
- data/docs/cheat.md +8 -8
- data/docs/faq.md +3 -3
- data/docs/installation.md +21 -0
- data/docs/quick_start.md +1 -16
- data/docs/webpacker.md +13 -5
- data/docs/yard_customizations.rb +2 -0
- data/frontend/super-frontend/dist/application.css +5600 -0
- data/frontend/super-frontend/dist/application.js +297 -97
- data/lib/generators/super/action_text/USAGE +23 -0
- data/lib/generators/super/action_text/action_text_generator.rb +32 -0
- data/lib/generators/super/action_text/templates/pack_super_action_text.css +23 -0
- data/lib/generators/super/action_text/templates/pack_super_action_text.js +4 -0
- data/lib/generators/super/install/install_generator.rb +2 -0
- data/lib/generators/super/resource/resource_generator.rb +2 -0
- data/lib/generators/super/resource/templates/resources_controller.rb.tt +1 -31
- data/lib/generators/super/webpacker/USAGE +5 -4
- data/lib/generators/super/webpacker/webpacker_generator.rb +5 -2
- data/lib/super.rb +23 -2
- data/lib/super/action_inquirer.rb +2 -0
- data/lib/super/assets.rb +114 -38
- data/lib/super/client_error.rb +2 -0
- data/lib/super/compatibility.rb +15 -1
- data/lib/super/configuration.rb +22 -69
- data/lib/super/controls.rb +6 -25
- data/lib/super/controls/optional.rb +71 -24
- data/lib/super/controls/required.rb +3 -29
- data/lib/super/controls/steps.rb +44 -53
- data/lib/super/controls/view.rb +55 -0
- data/lib/super/display.rb +80 -0
- data/lib/super/display/guesser.rb +36 -0
- data/lib/super/display/schema_types.rb +28 -33
- data/lib/super/engine.rb +11 -1
- data/lib/super/error.rb +14 -0
- data/lib/super/filter.rb +14 -0
- data/lib/super/filter/form_object.rb +94 -0
- data/lib/super/filter/guesser.rb +32 -0
- data/lib/super/filter/operator.rb +105 -0
- data/lib/super/filter/schema_types.rb +114 -0
- data/lib/super/form.rb +29 -40
- data/lib/super/form/builder.rb +206 -0
- data/lib/super/form/guesser.rb +29 -0
- data/lib/super/form/inline_errors.rb +28 -0
- data/lib/super/form/schema_types.rb +31 -29
- data/lib/super/form/strong_params.rb +31 -0
- data/lib/super/layout.rb +2 -0
- data/lib/super/link.rb +2 -0
- data/lib/super/navigation/automatic.rb +2 -0
- data/lib/super/pagination.rb +57 -0
- data/lib/super/panel.rb +2 -0
- data/lib/super/partial.rb +14 -0
- data/lib/super/partial/resolving.rb +2 -0
- data/lib/super/plugin.rb +36 -63
- data/lib/super/query/form_object.rb +48 -0
- data/lib/super/schema.rb +2 -24
- data/lib/super/schema/common.rb +27 -0
- data/lib/super/schema/guesser.rb +79 -0
- data/lib/super/sort.rb +110 -0
- data/lib/super/version.rb +3 -1
- data/lib/super/view_helper.rb +2 -19
- metadata +74 -22
- data/app/helpers/super/application_helper.rb +0 -39
- data/app/views/super/application/_form_inline_errors.html.erb +0 -10
- data/frontend/super-frontend/build.js +0 -36
- data/frontend/super-frontend/package.json +0 -21
- data/frontend/super-frontend/postcss.config.js +0 -6
- data/frontend/super-frontend/src/javascripts/super/application.ts +0 -18
- data/frontend/super-frontend/src/javascripts/super/apply_template_controller.ts +0 -19
- data/frontend/super-frontend/src/javascripts/super/rails__ujs.d.ts +0 -1
- data/frontend/super-frontend/src/javascripts/super/toggle_pending_destruction_controller.ts +0 -15
- data/frontend/super-frontend/src/stylesheets/super/application.css +0 -77
- data/frontend/super-frontend/tailwind.config.js +0 -15
- data/frontend/super-frontend/tsconfig.json +0 -13
- data/frontend/super-frontend/yarn.lock +0 -5448
data/lib/super/layout.rb
CHANGED
data/lib/super/link.rb
CHANGED
data/lib/super/pagination.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Super
|
|
2
4
|
class Pagination
|
|
3
5
|
include Enumerable
|
|
@@ -52,6 +54,10 @@ module Super
|
|
|
52
54
|
end
|
|
53
55
|
end
|
|
54
56
|
|
|
57
|
+
def to_partial_path
|
|
58
|
+
"super_pagination"
|
|
59
|
+
end
|
|
60
|
+
|
|
55
61
|
private
|
|
56
62
|
|
|
57
63
|
def pages
|
|
@@ -66,5 +72,56 @@ module Super
|
|
|
66
72
|
end
|
|
67
73
|
end
|
|
68
74
|
end
|
|
75
|
+
|
|
76
|
+
module ControllerMethods
|
|
77
|
+
def index
|
|
78
|
+
super
|
|
79
|
+
@pagination = controls.initialize_pagination(action: action_inquirer, records: @records, query_params: request.GET)
|
|
80
|
+
@records = controls.paginate_records(action: action_inquirer, records: @records, pagination: @pagination)
|
|
81
|
+
@view.mains.first.parts.push(:@pagination)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class Controls
|
|
87
|
+
module Optional
|
|
88
|
+
# Specifies how many records to show per page
|
|
89
|
+
#
|
|
90
|
+
# @param action [ActionInquirer]
|
|
91
|
+
# @param query_params [Hash]
|
|
92
|
+
# @return [ActiveRecord::Relation]
|
|
93
|
+
def records_per_page(action:, query_params:)
|
|
94
|
+
Super.configuration.index_records_per_page
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
module Steps
|
|
99
|
+
# Sets up pagination
|
|
100
|
+
#
|
|
101
|
+
# @param action [ActionInquirer]
|
|
102
|
+
# @param records [ActiveRecord::Relation]
|
|
103
|
+
# @param query_params [Hash]
|
|
104
|
+
# @return [Pagination]
|
|
105
|
+
def initialize_pagination(action:, records:, query_params:)
|
|
106
|
+
Pagination.new(
|
|
107
|
+
total_count: records.size,
|
|
108
|
+
limit: records_per_page(action: action, query_params: query_params),
|
|
109
|
+
query_params: query_params,
|
|
110
|
+
page_query_param: :page
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Paginates
|
|
115
|
+
#
|
|
116
|
+
# @param action [ActionInquirer]
|
|
117
|
+
# @param records [ActiveRecord::Relation]
|
|
118
|
+
# @param pagination [Pagination]
|
|
119
|
+
# @return [ActiveRecord::Relation]
|
|
120
|
+
def paginate_records(action:, records:, pagination:)
|
|
121
|
+
records
|
|
122
|
+
.limit(pagination.limit)
|
|
123
|
+
.offset(pagination.offset)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
69
126
|
end
|
|
70
127
|
end
|
data/lib/super/panel.rb
CHANGED
data/lib/super/partial.rb
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Super
|
|
2
4
|
class Partial
|
|
5
|
+
def self.render(partialish, template:)
|
|
6
|
+
if partialish.respond_to?(:to_partial_path)
|
|
7
|
+
if partialish.respond_to?(:locals)
|
|
8
|
+
template.render(partialish, partialish.locals)
|
|
9
|
+
else
|
|
10
|
+
template.render(partialish)
|
|
11
|
+
end
|
|
12
|
+
else
|
|
13
|
+
partialish
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
3
17
|
def initialize(path, locals: {})
|
|
4
18
|
@to_partial_path = path
|
|
5
19
|
@locals = locals
|
data/lib/super/plugin.rb
CHANGED
|
@@ -1,88 +1,61 @@
|
|
|
1
|
-
|
|
2
|
-
class Pluggable < Module
|
|
3
|
-
def initialize(registry_name)
|
|
4
|
-
@registry_name = registry_name
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def included(base)
|
|
8
|
-
super
|
|
1
|
+
# frozen_string_literal: true
|
|
9
2
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
module Super
|
|
4
|
+
module Plugin
|
|
5
|
+
class Registry
|
|
6
|
+
class << self
|
|
7
|
+
def controller
|
|
8
|
+
@controller ||= Registry.new
|
|
9
|
+
end
|
|
16
10
|
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
11
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
plugin_push(name.to_sym, :include, klass)
|
|
12
|
+
def initialize
|
|
13
|
+
@registry = {}
|
|
14
|
+
@ordering = Hash.new { |hash, key| hash[key] = [] }
|
|
24
15
|
end
|
|
25
16
|
|
|
26
|
-
def
|
|
27
|
-
|
|
17
|
+
def use(include: nil, prepend: nil)
|
|
18
|
+
register(include: include, prepend: prepend, before: [], after: [])
|
|
28
19
|
end
|
|
29
20
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
plugins.fetch(name) { {} }
|
|
21
|
+
def insert_before(*before, include: nil, prepend: nil)
|
|
22
|
+
register(include: include, prepend: prepend, before: before, after: [])
|
|
34
23
|
end
|
|
35
24
|
|
|
36
|
-
def
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if !klass.kind_of?(Class)
|
|
40
|
-
raise Error::InvalidPluginArgument,
|
|
41
|
-
"Received `#{klass}` which must be a class"
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
bases[name] = klass
|
|
45
|
-
|
|
46
|
-
true
|
|
25
|
+
def insert_after(*after, include: nil, prepend: nil)
|
|
26
|
+
register(include: include, prepend: prepend, before: [], after: after)
|
|
47
27
|
end
|
|
48
28
|
|
|
49
|
-
def
|
|
50
|
-
|
|
29
|
+
def classes_ordered
|
|
30
|
+
each_node = -> (&b) { @ordering.each_key(&b) }
|
|
31
|
+
each_child = -> (cb, &b) { @ordering[cb].each(&b) }
|
|
51
32
|
|
|
52
|
-
|
|
33
|
+
TSort.tsort(each_node, each_child)
|
|
53
34
|
end
|
|
54
35
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if ![:include, :prepend].include?(method_name)
|
|
59
|
-
raise Error::InvalidPluginArgument,
|
|
60
|
-
"Received `#{method_name.inspect}`, must be either :include or :prepend"
|
|
36
|
+
def ordered
|
|
37
|
+
classes_ordered.each do |class_name|
|
|
38
|
+
yield class_name, @registry[class_name]
|
|
61
39
|
end
|
|
40
|
+
end
|
|
62
41
|
|
|
63
|
-
|
|
64
|
-
raise Error::InvalidPluginArgument,
|
|
65
|
-
"Received `#{klass}` which must be a module"
|
|
66
|
-
end
|
|
42
|
+
private
|
|
67
43
|
|
|
68
|
-
|
|
69
|
-
|
|
44
|
+
def register(include:, prepend:, before: [], after: [])
|
|
45
|
+
raise Error::InvalidPluginArgument, "only one of :include or :prepend can be filled out" if include && prepend
|
|
46
|
+
raise Error::InvalidPluginArgument, "at least one of :include or :prepend must be filled out" if include.nil? && prepend.nil?
|
|
70
47
|
|
|
71
|
-
|
|
48
|
+
klass = include || prepend
|
|
49
|
+
@registry[klass] = :include if include
|
|
50
|
+
@registry[klass] = :prepend if prepend
|
|
72
51
|
|
|
73
|
-
|
|
74
|
-
|
|
52
|
+
before.each do |b|
|
|
53
|
+
@ordering[b].push(klass)
|
|
75
54
|
end
|
|
76
55
|
|
|
77
|
-
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def plugins
|
|
81
|
-
@plugins ||= {}
|
|
82
|
-
end
|
|
56
|
+
@ordering[klass].push(*after)
|
|
83
57
|
|
|
84
|
-
|
|
85
|
-
@bases ||= {}
|
|
58
|
+
nil
|
|
86
59
|
end
|
|
87
60
|
end
|
|
88
61
|
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Super
|
|
4
|
+
class Query
|
|
5
|
+
class FormObject
|
|
6
|
+
def initialize(model:, params:, namespace:, current_path:)
|
|
7
|
+
@model = model
|
|
8
|
+
@all_params = params.dup
|
|
9
|
+
@namespace = namespace
|
|
10
|
+
@params = params[namespace] || ActionController::Parameters.new
|
|
11
|
+
@path = current_path
|
|
12
|
+
@addons = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :namespace
|
|
16
|
+
attr_reader :path
|
|
17
|
+
attr_reader :addons
|
|
18
|
+
|
|
19
|
+
def add(klass, namespace:, **additional_initialization_arguments)
|
|
20
|
+
instance = klass.new(
|
|
21
|
+
model: @model,
|
|
22
|
+
params: params_dig(namespace),
|
|
23
|
+
**additional_initialization_arguments
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
addons[namespace] = instance
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def apply_changes(records)
|
|
30
|
+
addons.each_value do |addon|
|
|
31
|
+
records = addon.apply_changes(records)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
records
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def to_partial_path
|
|
38
|
+
"query"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def params_dig(*keys)
|
|
44
|
+
@params.dig(*keys) || ActionController::Parameters.new
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/super/schema.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Super
|
|
2
4
|
# The Schema is a general purpose container for describing the "schema"
|
|
3
5
|
# for various purposes. It primarily exists to provide a cohesive user-facing
|
|
@@ -5,30 +7,6 @@ module Super
|
|
|
5
7
|
#
|
|
6
8
|
# The various "schema types" are likely of more interest
|
|
7
9
|
class Schema
|
|
8
|
-
# @param schema_type [Display::SchemaTypes, Form::SchemaTypes]
|
|
9
|
-
def initialize(schema_type)
|
|
10
|
-
@schema_type = schema_type
|
|
11
|
-
@fields = Fields.new
|
|
12
|
-
|
|
13
|
-
@schema_type.before_yield(fields: @fields)
|
|
14
|
-
|
|
15
|
-
if block_given?
|
|
16
|
-
yield(@fields, @schema_type)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
@schema_type.after_yield
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
attr_reader :fields
|
|
23
|
-
|
|
24
|
-
def field_keys
|
|
25
|
-
fields.keys
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def to_partial_path
|
|
29
|
-
@schema_type.to_partial_path
|
|
30
|
-
end
|
|
31
|
-
|
|
32
10
|
# This class can be thought of as a Hash, where the keys usually refer to
|
|
33
11
|
# the model's column name and the value refers to the column type. Note
|
|
34
12
|
# though that this isn't always the case—different `SchemaTypes` can do
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Super
|
|
4
|
+
class Schema
|
|
5
|
+
module Common
|
|
6
|
+
def each_attribute_name
|
|
7
|
+
if block_given?
|
|
8
|
+
@fields.keys.each do |key|
|
|
9
|
+
yield(key)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
enum_for(:each_attribute_name)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def each_attribute
|
|
17
|
+
if block_given?
|
|
18
|
+
@fields.each do |key, value|
|
|
19
|
+
yield(key, value)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
enum_for(:each_attribute)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Super
|
|
4
|
+
class Schema
|
|
5
|
+
class Guesser
|
|
6
|
+
def initialize(model:, fields:, type:)
|
|
7
|
+
@model = model
|
|
8
|
+
@fields = fields
|
|
9
|
+
@type = type
|
|
10
|
+
@rejects = []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def limit
|
|
14
|
+
@limit = yield
|
|
15
|
+
self
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def reject(&block)
|
|
19
|
+
@rejects.push(block)
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def ignore_foreign_keys
|
|
24
|
+
@rejects.push(-> (attribute_name) { is_foreign_key[attribute_name] })
|
|
25
|
+
self
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def assign_type(&block)
|
|
29
|
+
@assign_type = block
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def call
|
|
34
|
+
result = sorted_attribute_names
|
|
35
|
+
result = @rejects.reduce(result) do |intermediary_result, rejection_proc|
|
|
36
|
+
intermediary_result.reject(&rejection_proc)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
result = result.first(@limit) if @limit && @limit != Float::INFINITY
|
|
40
|
+
|
|
41
|
+
result.each do |name|
|
|
42
|
+
@fields[name] = @assign_type.call(name)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def sorted_attribute_names
|
|
49
|
+
@model
|
|
50
|
+
.attribute_names
|
|
51
|
+
.sort_by { |name| sort_weight[name] }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def sort_weight
|
|
55
|
+
@sort_weight ||= Hash.new do |hash, name|
|
|
56
|
+
hash[name] =
|
|
57
|
+
case name
|
|
58
|
+
when "id" then 0
|
|
59
|
+
when "title" then 1000
|
|
60
|
+
when "name" then 1300
|
|
61
|
+
when "created_at" then 9500
|
|
62
|
+
when "updated_at" then 9750
|
|
63
|
+
else
|
|
64
|
+
2000 + hash.size
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def is_foreign_key
|
|
70
|
+
@is_foreign_key ||=
|
|
71
|
+
@model
|
|
72
|
+
.reflect_on_all_associations
|
|
73
|
+
.select { |a| a.macro == :belongs_to }
|
|
74
|
+
.map { |a| [a.foreign_key, true] }
|
|
75
|
+
.to_h
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|