super 0.0.0 → 0.0.1
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/LICENSE +165 -0
- data/README.md +102 -8
- data/app/assets/config/super_manifest.js +1 -0
- data/app/assets/javascripts/super/application.js +3483 -0
- data/app/assets/stylesheets/super/application.css +35265 -0
- data/app/controllers/super/application_controller.rb +84 -0
- data/app/views/layouts/super/application.html.erb +39 -0
- data/app/views/super/application/_form.html.erb +13 -0
- data/app/views/super/application/_form_field.html.erb +7 -0
- data/app/views/super/application/_form_generic_select.html.erb +19 -0
- data/app/views/super/application/_form_generic_text.html.erb +7 -0
- data/app/views/super/application/_index.html.erb +58 -0
- data/app/views/super/application/edit.html.erb +7 -0
- data/app/views/super/application/index.html.erb +1 -0
- data/app/views/super/application/new.html.erb +7 -0
- data/app/views/super/application/show.html.erb +10 -0
- data/app/views/super/feather/README.md +32 -0
- data/app/views/super/feather/_chevron_down.svg +1 -0
- data/frontend/super-frontend/build.js +34 -0
- data/frontend/super-frontend/dist/application.css +35265 -0
- data/frontend/super-frontend/dist/application.js +3483 -0
- data/frontend/super-frontend/package.json +14 -0
- data/frontend/super-frontend/postcss.config.js +6 -0
- data/frontend/super-frontend/src/javascripts/super/application.js +11 -0
- data/frontend/super-frontend/src/stylesheets/super/application.css +14 -0
- data/frontend/super-frontend/tailwind.config.js +7 -0
- data/frontend/super-frontend/yarn.lock +5355 -0
- data/lib/generators/super/install/USAGE +32 -0
- data/lib/generators/super/install/install_generator.rb +47 -0
- data/lib/generators/super/install/templates/base_controller.rb.tt +2 -0
- data/lib/generators/super/install/templates/initializer.rb.tt +5 -0
- data/lib/generators/super/resource/USAGE +9 -0
- data/lib/generators/super/resource/resource_generator.rb +54 -0
- data/lib/generators/super/resource/templates/resource_dashboard.rb.tt +65 -0
- data/lib/generators/super/resource/templates/resources_controller.rb.tt +9 -0
- data/lib/generators/super/webpacker/USAGE +14 -0
- data/lib/generators/super/webpacker/templates/pack_super_application.js.erb.tt +2 -0
- data/lib/generators/super/webpacker/webpacker_generator.rb +17 -0
- data/lib/super.rb +17 -4
- data/lib/super/assets.rb +62 -0
- data/lib/super/configuration.rb +88 -0
- data/lib/super/controls.rb +25 -0
- data/lib/super/display.rb +9 -0
- data/lib/super/display/schema_types.rb +41 -0
- data/lib/super/engine.rb +5 -0
- data/lib/super/error.rb +8 -0
- data/lib/super/form/schema_types.rb +47 -0
- data/lib/super/inline_callback.rb +82 -0
- data/lib/super/navigation/automatic.rb +69 -0
- data/lib/super/pagination.rb +59 -0
- data/lib/super/plugin.rb +89 -0
- data/lib/super/schema.rb +24 -0
- data/lib/super/test_support/fixtures/members.yml +336 -0
- data/lib/super/test_support/fixtures/ships.yml +10 -0
- data/lib/super/test_support/setup.rb +79 -0
- data/lib/super/test_support/starfleet_seeder.rb +49 -0
- data/lib/super/test_support/templates/20190216224956_create_members.rb +11 -0
- data/lib/super/test_support/templates/20190803143320_create_ships.rb +11 -0
- data/lib/super/test_support/templates/20190806014121_add_ship_to_members.rb +5 -0
- data/lib/super/test_support/templates/admin/members_controller.rb +9 -0
- data/lib/super/test_support/templates/admin/ships_controller.rb +9 -0
- data/lib/super/test_support/templates/admin_controller.rb +2 -0
- data/lib/super/test_support/templates/member.rb +16 -0
- data/lib/super/test_support/templates/member_dashboard.rb +90 -0
- data/lib/super/test_support/templates/routes.rb +10 -0
- data/lib/super/test_support/templates/seeds.rb +2 -0
- data/lib/super/test_support/templates/ship.rb +3 -0
- data/lib/super/test_support/templates/ship_dashboard.rb +79 -0
- data/lib/super/version.rb +1 -1
- data/lib/super/view.rb +25 -0
- metadata +131 -12
- data/LICENSE.txt +0 -40
@@ -0,0 +1,25 @@
|
|
1
|
+
module Super
|
2
|
+
class Controls
|
3
|
+
def initialize(dashboard)
|
4
|
+
@dashboard = dashboard
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :dashboard
|
8
|
+
|
9
|
+
def method_missing(method_name, *args)
|
10
|
+
if @dashboard.respond_to?(method_name)
|
11
|
+
@dashboard.public_send(method_name, *args)
|
12
|
+
else
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond_to_missing?(method_name, _ = false)
|
18
|
+
if @dashboard.respond_to?(method_name)
|
19
|
+
true
|
20
|
+
else
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Super
|
2
|
+
class Display
|
3
|
+
# This schema type is meant to be used for +#index+ or +#show+ actions to
|
4
|
+
# transform database fields into something that is human friendly.
|
5
|
+
#
|
6
|
+
# Note: The constants under "Defined Under Namespace" are considered
|
7
|
+
# private.
|
8
|
+
#
|
9
|
+
# class MemberDashboard
|
10
|
+
# # ...
|
11
|
+
#
|
12
|
+
# def show_schema
|
13
|
+
# Super::Schema.new(Super::Display::SchemaTypes.new) do |fields, type|
|
14
|
+
# fields[:name] = type.dynamic { |name| name }
|
15
|
+
# fields[:rank] = type.dynamic { |rank| rank }
|
16
|
+
# fields[:position] = type.dynamic { |position| position }
|
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
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # ...
|
24
|
+
# end
|
25
|
+
class SchemaTypes
|
26
|
+
class Dynamic
|
27
|
+
def initialize(transform_block)
|
28
|
+
@transform_block = transform_block
|
29
|
+
end
|
30
|
+
|
31
|
+
def present(field)
|
32
|
+
@transform_block.call(field)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def dynamic(&transform_block)
|
37
|
+
Dynamic.new(transform_block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/super/engine.rb
CHANGED
data/lib/super/error.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Super
|
2
|
+
class Form
|
3
|
+
# This schema type is used on your +#edit+ and +#new+ forms
|
4
|
+
#
|
5
|
+
# Note: The constants under "Defined Under Namespace" are considered
|
6
|
+
# private.
|
7
|
+
#
|
8
|
+
# class MemberDashboard
|
9
|
+
# # ...
|
10
|
+
#
|
11
|
+
# def new_schema
|
12
|
+
# Super::Schema.new(Super::Form::SchemaTypes.new) do |fields, type|
|
13
|
+
# fields[:name] = type.generic("write_type_text")
|
14
|
+
# fields[:rank] = type.generic("write_type_select", collection: Member.ranks.keys)
|
15
|
+
# fields[:position] = type.generic("write_type_text")
|
16
|
+
# fields[:ship_id] = type.generic(
|
17
|
+
# "write_type_select",
|
18
|
+
# collection: Ship.all.map { |s| ["#{s.name} (Ship ##{s.id})", s.id] },
|
19
|
+
# )
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # ...
|
24
|
+
# end
|
25
|
+
class SchemaTypes
|
26
|
+
class Generic
|
27
|
+
def initialize(partial_path:, extras:)
|
28
|
+
@partial_path = partial_path
|
29
|
+
@extras = extras
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_partial_path
|
33
|
+
@partial_path
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](key)
|
37
|
+
@extras[key]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def generic(partial_path, extras = nil)
|
42
|
+
extras ||= {}
|
43
|
+
Generic.new(partial_path: partial_path, extras: extras)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Super
|
2
|
+
module InlineCallback
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
register_inline_callback(:yield, on: :index)
|
7
|
+
end
|
8
|
+
|
9
|
+
class_methods do
|
10
|
+
def inline_callback_registry
|
11
|
+
@inline_callback_registry ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def inline_callback_defined?(action)
|
15
|
+
action = action.to_sym
|
16
|
+
|
17
|
+
inline_callback_registry.key?(action)
|
18
|
+
end
|
19
|
+
|
20
|
+
def inline_callbacks_for(action, check_ancestors = true)
|
21
|
+
action = action.to_sym
|
22
|
+
|
23
|
+
inline_callback_registry[action] ||= {}
|
24
|
+
|
25
|
+
if check_ancestors
|
26
|
+
ancestors.each do |ancestor|
|
27
|
+
if ancestor.respond_to?(:inline_callback_defined?)
|
28
|
+
if ancestor.inline_callback_defined?(action)
|
29
|
+
parent_class_callbacks = ancestor.inline_callbacks_for(action, false)
|
30
|
+
inline_callback_registry[action] = parent_class_callbacks.merge(inline_callback_registry[action])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if ancestor == Super::ApplicationController
|
35
|
+
break
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
inline_callback_registry[action]
|
41
|
+
end
|
42
|
+
|
43
|
+
def register_inline_callback(callback, on:, after: nil)
|
44
|
+
action = on.to_sym
|
45
|
+
after = after.to_sym if after.respond_to?(:to_sym)
|
46
|
+
|
47
|
+
callbacks = inline_callbacks_for(action)
|
48
|
+
if !callbacks.key?(callback)
|
49
|
+
callbacks[callback] = []
|
50
|
+
end
|
51
|
+
|
52
|
+
if after
|
53
|
+
callbacks[callback].push(after)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def with_inline_callbacks
|
59
|
+
action = params[:action].to_sym
|
60
|
+
|
61
|
+
callbacks = self.class.inline_callbacks_for(action)
|
62
|
+
|
63
|
+
each_node = -> (&b) { callbacks.each_key(&b) }
|
64
|
+
each_child = -> (cb, &b) { callbacks[cb].each(&b) }
|
65
|
+
|
66
|
+
yield_called = false
|
67
|
+
|
68
|
+
TSort.tsort_each(each_node, each_child) do |callback|
|
69
|
+
if callback == :yield
|
70
|
+
yield_called = true
|
71
|
+
yield
|
72
|
+
else
|
73
|
+
send(callback)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
if !yield_called
|
78
|
+
yield
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Super
|
2
|
+
class Navigation
|
3
|
+
class Automatic
|
4
|
+
def initialize(route_namespace:)
|
5
|
+
route_namespace = route_namespace.to_s
|
6
|
+
|
7
|
+
if route_namespace.include?("/")
|
8
|
+
raise "Can't be nested namespace"
|
9
|
+
end
|
10
|
+
|
11
|
+
@route_namespace = route_namespace
|
12
|
+
end
|
13
|
+
|
14
|
+
def each
|
15
|
+
if !block_given?
|
16
|
+
return enum_for(:each)
|
17
|
+
end
|
18
|
+
|
19
|
+
navigable_namespace_routes = Rails.application.routes.routes.select do |route|
|
20
|
+
path_spec = route.path.spec
|
21
|
+
|
22
|
+
next if route.verb != "GET"
|
23
|
+
next if !path_spec.respond_to?(:right)
|
24
|
+
next if path_spec.right.left.to_s != @route_namespace
|
25
|
+
next if route.required_parts.any?
|
26
|
+
next if route.defaults.empty?
|
27
|
+
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
navigable_defaults = navigable_namespace_routes.map do |route|
|
32
|
+
controller_name = route.defaults[:controller] + "_controller"
|
33
|
+
_controller =
|
34
|
+
begin
|
35
|
+
controller_name.camelize.constantize
|
36
|
+
rescue NameError
|
37
|
+
warn("[super] Couldn't find controller: #{controller_name}")
|
38
|
+
next
|
39
|
+
end
|
40
|
+
|
41
|
+
route.defaults
|
42
|
+
end
|
43
|
+
|
44
|
+
grouped_navigable_defaults =
|
45
|
+
navigable_defaults.compact.uniq.group_by { |d| d[:controller] }
|
46
|
+
|
47
|
+
grouped_navigable_defaults.each do |controller, defaults|
|
48
|
+
actions = defaults.map { |d| [d[:action], d[:action]] }.to_h
|
49
|
+
action = actions["index"] || actions["show"]
|
50
|
+
|
51
|
+
next if action.nil?
|
52
|
+
|
53
|
+
path =
|
54
|
+
begin
|
55
|
+
Rails.application.routes.url_for(
|
56
|
+
controller: controller,
|
57
|
+
action: action,
|
58
|
+
only_path: true
|
59
|
+
)
|
60
|
+
rescue ActionController::UrlGenerationError
|
61
|
+
next
|
62
|
+
end
|
63
|
+
|
64
|
+
yield(controller.split("/").last.humanize, path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Super
|
2
|
+
class Pagination
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :current_pageno
|
6
|
+
attr_reader :limit
|
7
|
+
|
8
|
+
def initialize(total_count:, limit:, query_params:, page_query_param:)
|
9
|
+
@total_count = total_count.to_i
|
10
|
+
@limit = limit.to_i
|
11
|
+
@query_params = query_params
|
12
|
+
@page_query_param = page_query_param
|
13
|
+
|
14
|
+
self.current_pageno = query_params[page_query_param]
|
15
|
+
end
|
16
|
+
|
17
|
+
def offset
|
18
|
+
limit * (current_pageno - 1)
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_pageno=(pageno)
|
22
|
+
pageno = pageno.to_i
|
23
|
+
|
24
|
+
@current_pageno =
|
25
|
+
if pageno.zero?
|
26
|
+
1
|
27
|
+
else
|
28
|
+
pageno
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def each
|
33
|
+
if !block_given?
|
34
|
+
return enum_for(:each)
|
35
|
+
end
|
36
|
+
|
37
|
+
quotient, remainder = @total_count.divmod(@limit)
|
38
|
+
pages =
|
39
|
+
if remainder.zero?
|
40
|
+
quotient
|
41
|
+
else
|
42
|
+
quotient + 1
|
43
|
+
end
|
44
|
+
|
45
|
+
(1..pages).each do |pageno|
|
46
|
+
is_current_page = pageno == current_pageno
|
47
|
+
display = pageno.to_s
|
48
|
+
page_query_params = @query_params.dup
|
49
|
+
if pageno == 1
|
50
|
+
page_query_params.delete(:page)
|
51
|
+
else
|
52
|
+
page_query_params[@page_query_param] = pageno
|
53
|
+
end
|
54
|
+
|
55
|
+
yield(page_query_params, is_current_page, display)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/super/plugin.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
module Super
|
2
|
+
class Pluggable < Module
|
3
|
+
def initialize(registry_name)
|
4
|
+
@registry_name = registry_name
|
5
|
+
end
|
6
|
+
|
7
|
+
def included(base)
|
8
|
+
super
|
9
|
+
|
10
|
+
PluginRegistry.base_set(@registry_name, base)
|
11
|
+
|
12
|
+
plugins = PluginRegistry.plugins_for(@registry_name)
|
13
|
+
|
14
|
+
plugins.each do |klass, method_name|
|
15
|
+
base.public_send(method_name, klass)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class PluginRegistry
|
21
|
+
class << self
|
22
|
+
def include_to(name, klass)
|
23
|
+
plugin_push(name.to_sym, :include, klass)
|
24
|
+
end
|
25
|
+
|
26
|
+
def prepend_to(name, klass)
|
27
|
+
plugin_push(name.to_sym, :prepend, klass)
|
28
|
+
end
|
29
|
+
|
30
|
+
def plugins_for(name)
|
31
|
+
name = name.to_sym
|
32
|
+
|
33
|
+
plugins.fetch(name) { {} }
|
34
|
+
end
|
35
|
+
|
36
|
+
def base_set(name, klass)
|
37
|
+
name = name.to_sym
|
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
|
47
|
+
end
|
48
|
+
|
49
|
+
def base_get(name)
|
50
|
+
name = name.to_sym
|
51
|
+
|
52
|
+
bases[name]
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def plugin_push(name, method_name, klass)
|
58
|
+
if ![:include, :prepend].include?(method_name)
|
59
|
+
raise Error::InvalidPluginArgument,
|
60
|
+
"Received `#{method_name.inspect}`, must be either :include or :prepend"
|
61
|
+
end
|
62
|
+
|
63
|
+
if !klass.kind_of?(Module)
|
64
|
+
raise Error::InvalidPluginArgument,
|
65
|
+
"Received `#{klass}` which must be a module"
|
66
|
+
end
|
67
|
+
|
68
|
+
plugins[name] ||= {}
|
69
|
+
plugins[name][klass] = method_name
|
70
|
+
|
71
|
+
base = base_get(name)
|
72
|
+
|
73
|
+
if base
|
74
|
+
base.public_send(method_name, klass)
|
75
|
+
end
|
76
|
+
|
77
|
+
true
|
78
|
+
end
|
79
|
+
|
80
|
+
def plugins
|
81
|
+
@plugins ||= {}
|
82
|
+
end
|
83
|
+
|
84
|
+
def bases
|
85
|
+
@bases ||= {}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|