super 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -13
- data/app/assets/javascripts/super/application.js +10970 -64
- data/app/assets/stylesheets/super/application.css +33270 -14020
- data/app/controllers/super/application_controller.rb +1 -0
- data/app/views/super/application/_form.html.erb +1 -2
- data/app/views/super/application/_form_field__destroy.html.erb +5 -0
- data/app/views/super/application/{_form_generic_select.html.erb → _form_field_select.html.erb} +3 -5
- data/app/views/super/application/{_form_generic_text.html.erb → _form_field_text.html.erb} +1 -3
- 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/frontend/super-frontend/build.js +3 -1
- data/frontend/super-frontend/dist/application.css +33270 -14020
- data/frontend/super-frontend/dist/application.js +10970 -64
- data/frontend/super-frontend/package.json +5 -2
- data/frontend/super-frontend/src/javascripts/super/{application.js → application.ts} +3 -1
- data/frontend/super-frontend/src/javascripts/super/nested_attributes_controller.ts +33 -0
- data/frontend/super-frontend/src/javascripts/super/rails__ujs.d.ts +1 -0
- data/frontend/super-frontend/tsconfig.json +13 -0
- data/frontend/super-frontend/yarn.lock +1559 -1523
- data/lib/super/action_inquirer.rb +13 -0
- data/lib/super/assets.rb +1 -0
- data/lib/super/configuration.rb +59 -44
- data/lib/super/controls.rb +31 -15
- data/lib/super/display/schema_types.rb +15 -16
- data/lib/super/engine.rb +1 -0
- data/lib/super/error.rb +1 -0
- data/lib/super/form/schema_types.rb +89 -21
- data/lib/super/navigation/automatic.rb +2 -0
- data/lib/super/schema.rb +50 -1
- data/lib/super/test_support/copy_app_templates/controllers/favorite_things_controller.rb +50 -0
- data/lib/super/test_support/copy_app_templates/{members_controller.rb → controllers/members_controller.rb} +10 -5
- data/lib/super/test_support/copy_app_templates/{ships_controller.rb → controllers/ships_controller.rb} +3 -3
- data/lib/super/test_support/copy_app_templates/{20190216224956_create_members.rb → migrations/20190216224956_create_members.rb} +0 -0
- data/lib/super/test_support/copy_app_templates/{20190803143320_create_ships.rb → migrations/20190803143320_create_ships.rb} +0 -0
- data/lib/super/test_support/copy_app_templates/{20190806014121_add_ship_to_members.rb → migrations/20190806014121_add_ship_to_members.rb} +0 -0
- data/lib/super/test_support/copy_app_templates/migrations/20191126050453_create_favorite_things.rb +10 -0
- data/lib/super/test_support/copy_app_templates/models/favorite_thing.rb +7 -0
- data/lib/super/test_support/copy_app_templates/{member.rb → models/member.rb} +7 -0
- data/lib/super/test_support/copy_app_templates/{ship.rb → models/ship.rb} +0 -0
- data/lib/super/test_support/copy_app_templates/routes.rb +1 -0
- data/lib/super/test_support/fixtures/favorite_things.yml +9 -0
- data/lib/super/test_support/generate_copy_app.rb +5 -16
- data/lib/super/test_support/generate_dummy.rb +0 -1
- data/lib/super/test_support/starfleet_seeder.rb +1 -0
- data/lib/super/version.rb +1 -1
- metadata +25 -14
- data/app/views/super/application/_form_field.html.erb +0 -7
@@ -1,7 +1,20 @@
|
|
1
1
|
module Super
|
2
|
+
# ```ruby
|
3
|
+
# action = Super::ActionInquirer.new(
|
4
|
+
# Super::ActionInquirer.default_resources,
|
5
|
+
# :index
|
6
|
+
# )
|
7
|
+
#
|
8
|
+
# action.read? # => true
|
9
|
+
# action.index? # => true
|
10
|
+
# action.show? # => false
|
11
|
+
# action.write? # => false
|
12
|
+
# ```
|
2
13
|
class ActionInquirer
|
3
14
|
attr_reader :action
|
4
15
|
|
16
|
+
# @return [Hash<Symbol, Array<Symbol>>] default settings for initialization
|
17
|
+
#
|
5
18
|
def self.default_resources
|
6
19
|
{
|
7
20
|
read: %i[index show new edit],
|
data/lib/super/assets.rb
CHANGED
data/lib/super/configuration.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
module Super
|
2
|
+
# @yield [Configuration]
|
3
|
+
# @return [Configuration]
|
2
4
|
def self.configuration
|
3
5
|
@configuration ||= Configuration.new
|
4
6
|
|
@@ -9,78 +11,91 @@ module Super
|
|
9
11
|
@configuration
|
10
12
|
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
public_send("#{key}=", value)
|
14
|
+
# Allows setting global configuration
|
15
|
+
#
|
16
|
+
# ```ruby
|
17
|
+
# Super.configuration do |c|
|
18
|
+
# c.title = "My Admin Site"
|
19
|
+
# end
|
20
|
+
# ```
|
21
|
+
class Configuration
|
22
|
+
module ConfigurationLogic # @api private
|
23
|
+
def self.included(base)
|
24
|
+
base.extend(ClassMethods)
|
24
25
|
end
|
25
|
-
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
def initialize
|
28
|
+
self.class.defaults.each do |key, value|
|
29
|
+
if value.respond_to?(:call)
|
30
|
+
value = value.call
|
31
|
+
end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
@defaults ||= {}
|
33
|
+
public_send("#{key}=", value)
|
34
|
+
end
|
34
35
|
end
|
35
36
|
|
36
|
-
def
|
37
|
-
|
37
|
+
def configured?(attr)
|
38
|
+
instance_variable_defined?("@#{attr}")
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
defaults
|
41
|
+
module ClassMethods
|
42
|
+
def defaults
|
43
|
+
@defaults ||= {}
|
43
44
|
end
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
def wraps
|
47
|
+
@wraps ||= {}
|
48
|
+
end
|
49
|
+
|
50
|
+
def configure(attr, wrap: nil, enum: nil, **kwargs)
|
51
|
+
if kwargs.key?(:default)
|
52
|
+
defaults[attr] = kwargs[:default]
|
48
53
|
end
|
49
54
|
|
50
|
-
|
55
|
+
define_method(attr) do
|
56
|
+
if !configured?(attr)
|
57
|
+
raise Error::UnconfiguredConfiguration, "unconfigured: #{attr}"
|
58
|
+
end
|
51
59
|
|
52
|
-
|
53
|
-
result
|
54
|
-
else
|
55
|
-
wrap.call(result)
|
56
|
-
end
|
57
|
-
end
|
60
|
+
result = instance_variable_get("@#{attr}")
|
58
61
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
"tried to set `#{attr}` to `#{value.inspect}`, " \
|
64
|
-
"expected: #{enum.join(", ")}"
|
62
|
+
if wrap.nil?
|
63
|
+
result
|
64
|
+
else
|
65
|
+
wrap.call(result)
|
65
66
|
end
|
66
67
|
end
|
67
68
|
|
68
|
-
|
69
|
-
|
69
|
+
define_method("#{attr}=") do |value|
|
70
|
+
if enum.is_a?(Array)
|
71
|
+
if !enum.include?(value)
|
72
|
+
raise Error::InvalidConfiguration,
|
73
|
+
"tried to set `#{attr}` to `#{value.inspect}`, " \
|
74
|
+
"expected: #{enum.join(", ")}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
instance_variable_set("@#{attr}", value)
|
79
|
+
value
|
80
|
+
end
|
70
81
|
end
|
71
82
|
end
|
72
83
|
end
|
73
|
-
end
|
74
84
|
|
75
|
-
class Configuration
|
76
85
|
include ConfigurationLogic
|
77
86
|
|
87
|
+
# @!attribute [rw]
|
78
88
|
configure :title
|
89
|
+
# @!attribute [rw]
|
79
90
|
configure :index_resources_per_page, default: 20
|
91
|
+
# @!attribute [rw]
|
80
92
|
configure :controller_namespace, default: "admin"
|
93
|
+
# @!attribute [rw]
|
81
94
|
configure :route_namespace, default: :admin, wrap: -> (val) { [val].flatten }
|
95
|
+
# @!attribute [rw]
|
82
96
|
configure :asset_handler, default: -> { Super::Assets.auto }
|
83
97
|
|
98
|
+
# @api private
|
84
99
|
def path_parts(*parts)
|
85
100
|
route_namespace + parts
|
86
101
|
end
|
data/lib/super/controls.rb
CHANGED
@@ -1,25 +1,41 @@
|
|
1
1
|
module Super
|
2
|
+
# A wrapper around the per-controller Controls classes. This class often
|
3
|
+
# directly delegates to the per-controller classes, but it can also provide
|
4
|
+
# some default implementation.
|
2
5
|
class Controls
|
3
|
-
def initialize(
|
4
|
-
@
|
6
|
+
def initialize(actual)
|
7
|
+
@actual = actual
|
5
8
|
end
|
6
9
|
|
7
|
-
attr_reader :
|
10
|
+
attr_reader :actual
|
8
11
|
|
9
|
-
def
|
10
|
-
|
11
|
-
@dashboard.public_send(method_name, *args)
|
12
|
-
else
|
13
|
-
super
|
14
|
-
end
|
12
|
+
def title
|
13
|
+
@actual.title
|
15
14
|
end
|
16
15
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
def model
|
17
|
+
@actual.model
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param action [ActionInquirer]
|
21
|
+
def scope(action:)
|
22
|
+
@actual.scope(action: action)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param params [ActionController::Parameters]
|
26
|
+
# @param action [ActionInquirer]
|
27
|
+
def permitted_params(params, action:)
|
28
|
+
@actual.permitted_params(params, action: action)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param action [ActionInquirer]
|
32
|
+
def display_schema(action:)
|
33
|
+
@actual.display_schema(action: action)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param action [ActionInquirer]
|
37
|
+
def form_schema(action:)
|
38
|
+
@actual.form_schema(action: action)
|
23
39
|
end
|
24
40
|
end
|
25
41
|
end
|
@@ -3,25 +3,24 @@ 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)
|
data/lib/super/engine.rb
CHANGED
data/lib/super/error.rb
CHANGED
@@ -2,33 +2,41 @@ module Super
|
|
2
2
|
class Form
|
3
3
|
# This schema type is used on your +#edit+ and +#new+ forms
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# ```ruby
|
6
|
+
# class MembersController::Controls
|
7
|
+
# # ...
|
7
8
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# "write_type_select",
|
18
|
-
# collection: Ship.all.map { |s| ["#{s.name} (Ship ##{s.id})", s.id] },
|
19
|
-
# )
|
20
|
-
# end
|
9
|
+
# def new_schema
|
10
|
+
# Super::Schema.new(Super::Form::SchemaTypes.new) do |fields, type|
|
11
|
+
# fields[:name] = type.generic("form_field_text")
|
12
|
+
# fields[:rank] = type.generic("form_field_select", collection: Member.ranks.keys)
|
13
|
+
# fields[:position] = type.generic("form_field_text")
|
14
|
+
# fields[:ship_id] = type.generic(
|
15
|
+
# "form_field_select",
|
16
|
+
# collection: Ship.all.map { |s| ["#{s.name} (Ship ##{s.id})", s.id] },
|
17
|
+
# )
|
21
18
|
# end
|
22
|
-
#
|
23
|
-
# # ...
|
24
19
|
# end
|
20
|
+
#
|
21
|
+
# # ...
|
22
|
+
# end
|
23
|
+
# ```
|
25
24
|
class SchemaTypes
|
26
25
|
class Generic
|
27
|
-
def initialize(partial_path:, extras:)
|
26
|
+
def initialize(partial_path:, extras:, nested:)
|
28
27
|
@partial_path = partial_path
|
29
28
|
@extras = extras
|
29
|
+
@nested_fields = nested
|
30
30
|
end
|
31
31
|
|
32
|
+
attr_reader :nested_fields
|
33
|
+
|
34
|
+
# This takes advantage of a feature of Rails. If the value of
|
35
|
+
# `#to_partial_path` is `my_form_field`, Rails renders
|
36
|
+
# `app/views/super/application/_my_form_field.html.erb`, and this
|
37
|
+
# instance of Generic is accessible via `my_form_field`
|
38
|
+
#
|
39
|
+
# @return [String] the filename of the partial that will be rendered.
|
32
40
|
def to_partial_path
|
33
41
|
@partial_path
|
34
42
|
end
|
@@ -36,11 +44,71 @@ module Super
|
|
36
44
|
def [](key)
|
37
45
|
@extras[key]
|
38
46
|
end
|
47
|
+
|
48
|
+
def reader
|
49
|
+
@extras[:reader]
|
50
|
+
end
|
51
|
+
|
52
|
+
def label
|
53
|
+
if @extras.key?(:label)
|
54
|
+
return @extras[:label]
|
55
|
+
end
|
56
|
+
|
57
|
+
if @extras.key?(:reader)
|
58
|
+
return @extras[:reader].to_s.singularize.humanize
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def ==(other)
|
63
|
+
return false if other.class != self.class
|
64
|
+
return false if other.instance_variable_get(:@partial_path) != @partial_path
|
65
|
+
return false if other.instance_variable_get(:@extras) != @extras
|
66
|
+
return false if other.instance_variable_get(:@nested) != @nested
|
67
|
+
|
68
|
+
true
|
69
|
+
end
|
39
70
|
end
|
40
71
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
72
|
+
def setup(fields:)
|
73
|
+
@fields = fields
|
74
|
+
end
|
75
|
+
|
76
|
+
def generic(partial_path, **extras)
|
77
|
+
Generic.new(partial_path: partial_path, extras: extras, nested: {})
|
78
|
+
end
|
79
|
+
|
80
|
+
def has_many(reader, **extras)
|
81
|
+
nested = @fields.nested do
|
82
|
+
yield
|
83
|
+
end
|
84
|
+
|
85
|
+
Generic.new(
|
86
|
+
partial_path: "form_has_many",
|
87
|
+
extras: extras.merge(reader: reader),
|
88
|
+
nested: nested
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
def has_one(reader, **extras)
|
93
|
+
nested = @fields.nested do
|
94
|
+
yield
|
95
|
+
end
|
96
|
+
|
97
|
+
Generic.new(
|
98
|
+
partial_path: "form_has_one",
|
99
|
+
extras: extras.merge(reader: reader),
|
100
|
+
nested: nested
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
alias_method :belongs_to, :has_one
|
105
|
+
|
106
|
+
def _destroy(**extras)
|
107
|
+
Generic.new(
|
108
|
+
partial_path: "form_field__destroy",
|
109
|
+
extras: extras,
|
110
|
+
nested: {}
|
111
|
+
)
|
44
112
|
end
|
45
113
|
end
|
46
114
|
end
|
data/lib/super/schema.rb
CHANGED
@@ -8,7 +8,11 @@ module Super
|
|
8
8
|
# @param schema_type [Display::SchemaTypes, Form::SchemaTypes]
|
9
9
|
def initialize(schema_type)
|
10
10
|
@schema_type = schema_type
|
11
|
-
@fields =
|
11
|
+
@fields = Fields.new
|
12
|
+
|
13
|
+
if @schema_type.respond_to?(:setup)
|
14
|
+
@schema_type.setup(fields: @fields)
|
15
|
+
end
|
12
16
|
|
13
17
|
if block_given?
|
14
18
|
yield(@fields, @schema_type)
|
@@ -20,5 +24,50 @@ module Super
|
|
20
24
|
def field_keys
|
21
25
|
fields.keys
|
22
26
|
end
|
27
|
+
|
28
|
+
class Fields
|
29
|
+
include Enumerable
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@backing = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](key)
|
36
|
+
@backing[key]
|
37
|
+
end
|
38
|
+
|
39
|
+
def []=(key, value)
|
40
|
+
@backing[key] = value
|
41
|
+
end
|
42
|
+
|
43
|
+
def keys
|
44
|
+
@backing.keys
|
45
|
+
end
|
46
|
+
|
47
|
+
def each
|
48
|
+
if block_given?
|
49
|
+
return @backing.each(&Proc.new)
|
50
|
+
end
|
51
|
+
|
52
|
+
enum_for(:each)
|
53
|
+
end
|
54
|
+
|
55
|
+
def replace(other)
|
56
|
+
@backing = other
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_h
|
60
|
+
@backing
|
61
|
+
end
|
62
|
+
|
63
|
+
def nested
|
64
|
+
outside = @backing
|
65
|
+
inside = {}
|
66
|
+
@backing = inside
|
67
|
+
yield
|
68
|
+
@backing = outside
|
69
|
+
inside
|
70
|
+
end
|
71
|
+
end
|
23
72
|
end
|
24
73
|
end
|