super 0.0.7 → 0.0.12

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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +0 -6
  3. data/CONTRIBUTING.md +56 -0
  4. data/README.md +49 -61
  5. data/Rakefile +16 -14
  6. data/app/assets/javascripts/super/application.js +297 -97
  7. data/app/assets/stylesheets/super/application.css +5600 -0
  8. data/app/controllers/super/application_controller.rb +20 -14
  9. data/app/helpers/super/form_builder_helper.rb +25 -0
  10. data/app/views/layouts/super/application.html.erb +23 -9
  11. data/app/views/super/application/{_super_schema_display_actions.html.erb → _display_actions.html.erb} +0 -0
  12. data/app/views/super/application/{_super_schema_display_index.html.erb → _display_index.html.erb} +6 -6
  13. data/app/views/super/application/_display_rich_text.html.erb +1 -0
  14. data/app/views/super/application/_display_show.html.erb +8 -0
  15. data/app/views/super/application/_filter.html.erb +5 -13
  16. data/app/views/super/application/_filter_type_select.html.erb +9 -19
  17. data/app/views/super/application/_filter_type_text.html.erb +7 -11
  18. data/app/views/super/application/_filter_type_timestamp.html.erb +6 -17
  19. data/app/views/super/application/_form.html.erb +15 -0
  20. data/app/views/super/application/_form_field__destroy.html.erb +1 -9
  21. data/app/views/super/application/_form_field_checkbox.html.erb +1 -0
  22. data/app/views/super/application/_form_field_rich_text_area.html.erb +1 -0
  23. data/app/views/super/application/_form_field_select.html.erb +1 -23
  24. data/app/views/super/application/_form_field_text.html.erb +1 -13
  25. data/app/views/super/application/{_super_layout.html.erb → _layout.html.erb} +7 -7
  26. data/app/views/super/application/{_super_pagination.html.erb → _pagination.html.erb} +1 -1
  27. data/app/views/super/application/{_super_panel.html.erb → _panel.html.erb} +2 -2
  28. data/app/views/super/application/_query.html.erb +18 -0
  29. data/app/views/super/application/_sort.html.erb +18 -0
  30. data/app/views/super/application/_sort_expression.html.erb +25 -0
  31. data/app/views/super/application/edit.html.erb +1 -0
  32. data/app/views/super/application/index.html.erb +1 -0
  33. data/app/views/super/application/new.html.erb +1 -0
  34. data/app/views/super/application/show.html.erb +1 -0
  35. data/app/views/super/feather/README.md +1 -0
  36. data/app/views/super/feather/_x.html +15 -0
  37. data/config/routes.rb +2 -0
  38. data/docs/cheat.md +8 -8
  39. data/frontend/super-frontend/dist/application.css +5600 -0
  40. data/frontend/super-frontend/dist/application.js +297 -97
  41. data/lib/generators/super/action_text/USAGE +23 -0
  42. data/lib/generators/super/action_text/action_text_generator.rb +32 -0
  43. data/lib/generators/super/action_text/templates/pack_super_action_text.css +23 -0
  44. data/lib/generators/super/action_text/templates/pack_super_action_text.js +4 -0
  45. data/lib/generators/super/install/install_generator.rb +18 -7
  46. data/lib/generators/super/install/templates/base_controller.rb.tt +9 -1
  47. data/lib/generators/super/install/templates/initializer.rb.tt +9 -2
  48. data/lib/generators/super/resource/resource_generator.rb +107 -30
  49. data/lib/generators/super/resource/templates/resources_controller.rb.tt +3 -39
  50. data/lib/generators/super/webpacker/USAGE +5 -4
  51. data/lib/generators/super/webpacker/webpacker_generator.rb +5 -2
  52. data/lib/super.rb +17 -0
  53. data/lib/super/action_inquirer.rb +2 -0
  54. data/lib/super/assets.rb +114 -38
  55. data/lib/super/client_error.rb +2 -0
  56. data/lib/super/compatibility.rb +2 -0
  57. data/lib/super/configuration.rb +16 -79
  58. data/lib/super/controls.rb +11 -25
  59. data/lib/super/controls/optional.rb +75 -16
  60. data/lib/super/controls/steps.rb +36 -58
  61. data/lib/super/controls/view.rb +55 -0
  62. data/lib/super/display.rb +88 -0
  63. data/lib/super/display/guesser.rb +36 -0
  64. data/lib/super/display/schema_types.rb +80 -78
  65. data/lib/super/engine.rb +5 -1
  66. data/lib/super/error.rb +21 -0
  67. data/lib/super/filter.rb +7 -130
  68. data/lib/super/filter/form_object.rb +94 -0
  69. data/lib/super/filter/guesser.rb +32 -0
  70. data/lib/super/filter/operator.rb +2 -0
  71. data/lib/super/filter/schema_types.rb +3 -7
  72. data/lib/super/form.rb +29 -40
  73. data/lib/super/form/builder.rb +206 -0
  74. data/lib/super/form/guesser.rb +29 -0
  75. data/lib/super/form/inline_errors.rb +28 -0
  76. data/lib/super/form/schema_types.rb +31 -29
  77. data/lib/super/form/strong_params.rb +31 -0
  78. data/lib/super/layout.rb +3 -1
  79. data/lib/super/link.rb +7 -0
  80. data/lib/super/navigation/automatic.rb +4 -2
  81. data/lib/super/pagination.rb +13 -17
  82. data/lib/super/panel.rb +3 -1
  83. data/lib/super/partial.rb +2 -0
  84. data/lib/super/partial/resolving.rb +2 -0
  85. data/lib/super/plugin.rb +2 -0
  86. data/lib/super/query/form_object.rb +48 -0
  87. data/lib/super/schema.rb +2 -25
  88. data/lib/super/schema/common.rb +27 -0
  89. data/lib/super/schema/guesser.rb +79 -0
  90. data/lib/super/sort.rb +110 -0
  91. data/lib/super/useful/builder.rb +25 -0
  92. data/lib/super/useful/enum.rb +63 -0
  93. data/lib/super/version.rb +3 -1
  94. data/lib/super/view_helper.rb +2 -19
  95. metadata +63 -34
  96. data/app/views/super/application/_form_inline_errors.html.erb +0 -10
  97. data/app/views/super/application/_super_schema_display_show.html.erb +0 -8
  98. data/app/views/super/application/_super_schema_form.html.erb +0 -15
  99. data/docs/README.md +0 -6
  100. data/docs/faq.md +0 -44
  101. data/docs/quick_start.md +0 -45
  102. data/docs/webpacker.md +0 -17
  103. data/docs/yard_customizations.rb +0 -41
  104. data/frontend/super-frontend/build.js +0 -36
  105. data/frontend/super-frontend/package.json +0 -21
  106. data/frontend/super-frontend/postcss.config.js +0 -6
  107. data/frontend/super-frontend/src/javascripts/super/application.ts +0 -18
  108. data/frontend/super-frontend/src/javascripts/super/apply_template_controller.ts +0 -19
  109. data/frontend/super-frontend/src/javascripts/super/rails__ujs.d.ts +0 -1
  110. data/frontend/super-frontend/src/javascripts/super/toggle_pending_destruction_controller.ts +0 -15
  111. data/frontend/super-frontend/src/stylesheets/super/application.css +0 -77
  112. data/frontend/super-frontend/tailwind.config.js +0 -15
  113. data/frontend/super-frontend/tsconfig.json +0 -13
  114. data/frontend/super-frontend/yarn.lock +0 -5448
  115. data/lib/super/controls/required.rb +0 -41
data/lib/super/assets.rb CHANGED
@@ -1,8 +1,66 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # Utilities for determining whether to use Sprockets or Webpacker
3
5
  class Assets
4
- def self.sprockets_available?
5
- Gem::Dependency.new("sprockets").matching_specs.any?
6
+ def self.webpacker(path, **arguments)
7
+ Asset.new(handler: Handler.webpacker, path: path, arguments: arguments)
8
+ end
9
+
10
+ def self.sprockets(path, **arguments)
11
+ Asset.new(handler: Handler.sprockets, path: path, arguments: arguments)
12
+ end
13
+
14
+ def self.auto(path, **arguments)
15
+ Asset.new(handler: Handler.auto, path: path, arguments: arguments)
16
+ end
17
+
18
+ def self.use_webpacker(assets, grep: nil)
19
+ assets = [assets] if !assets.kind_of?(Array)
20
+
21
+ assets.map do |asset|
22
+ grep_matches = grep && asset === grep
23
+ if grep_matches || !grep
24
+ asset.instance_variable_set(:@handler, Handler.webpacker)
25
+ end
26
+
27
+ asset
28
+ end
29
+ end
30
+
31
+ def self.use_sprockets(assets, grep: nil)
32
+ assets = [assets] if !assets.kind_of?(Array)
33
+
34
+ assets.map do |asset|
35
+ grep_matches = grep && asset === grep
36
+ if grep_matches || !grep
37
+ asset.instance_variable_set(:@asset_handler, Handler.sprockets)
38
+ end
39
+
40
+ asset
41
+ end
42
+ end
43
+
44
+ class Asset
45
+ def initialize(handler:, path:, arguments:)
46
+ @handler = handler
47
+ @path = path
48
+ @arguments = arguments
49
+ end
50
+
51
+ attr_reader :handler
52
+ attr_reader :path
53
+ attr_reader :arguments
54
+
55
+ def ===(other)
56
+ return true if path == other
57
+ return true if other.is_a?(Regexp) && path.match?(other)
58
+ return true if handler == other
59
+ return true if handler.to_sym == other
60
+ return true if handler.to_s == other
61
+
62
+ false
63
+ end
6
64
  end
7
65
 
8
66
  def self.dist(gem_name, package_name)
@@ -15,49 +73,67 @@ module Super
15
73
  gem_path.join("frontend", package_name, "dist")
16
74
  end
17
75
 
18
- def self.auto
19
- @auto ||=
20
- if Gem::Dependency.new("sprockets", "~> 4.0").matching_specs.any?
21
- sprockets
22
- elsif Gem::Dependency.new("sprockets", "~> 3.0").matching_specs.any?
23
- sprockets
24
- elsif Gem::Dependency.new("sprockets", "~> 2.0").matching_specs.any?
25
- sprockets
26
- elsif Gem::Dependency.new("webpacker", "~> 4.0").matching_specs.any?
27
- webpacker
28
- elsif Gem::Dependency.new("webpacker", "~> 3.0").matching_specs.any?
29
- webpacker
30
- else
31
- none
32
- end
33
- end
76
+ class Handler
77
+ def self.auto
78
+ @auto ||=
79
+ if Gem::Dependency.new("sprockets", "~> 4.0").matching_specs.any?
80
+ sprockets
81
+ elsif Gem::Dependency.new("sprockets", "~> 3.0").matching_specs.any?
82
+ sprockets
83
+ elsif Gem::Dependency.new("sprockets", "~> 2.0").matching_specs.any?
84
+ sprockets
85
+ elsif Gem::Dependency.new("webpacker", "~> 6.0").matching_specs.any?
86
+ webpacker
87
+ elsif Gem::Dependency.new("webpacker", "~> 5.0").matching_specs.any?
88
+ webpacker
89
+ elsif Gem::Dependency.new("webpacker", "~> 4.0").matching_specs.any?
90
+ webpacker
91
+ elsif Gem::Dependency.new("webpacker", "~> 3.0").matching_specs.any?
92
+ webpacker
93
+ else
94
+ none
95
+ end
96
+ end
34
97
 
35
- def self.sprockets
36
- new(:sprockets)
37
- end
98
+ def self.sprockets_available?
99
+ Gem::Dependency.new("sprockets").matching_specs.any? && defined?(Sprockets)
100
+ end
38
101
 
39
- def self.webpacker
40
- new(:webpacker)
41
- end
102
+ def self.sprockets
103
+ @sprockets ||= new(:sprockets)
104
+ end
42
105
 
43
- def self.none
44
- new(:none)
45
- end
106
+ def self.webpacker
107
+ @webpacker ||= new(:webpacker)
108
+ end
46
109
 
47
- def initialize(asset_handler)
48
- @asset_handler = asset_handler
49
- end
110
+ def self.none
111
+ @none ||= new(:none)
112
+ end
50
113
 
51
- def sprockets?
52
- @asset_handler == :sprockets
53
- end
114
+ def initialize(asset_handler)
115
+ @asset_handler = asset_handler
116
+ end
54
117
 
55
- def webpacker?
56
- @asset_handler == :webpacker
57
- end
118
+ def sprockets?
119
+ @asset_handler == :sprockets
120
+ end
121
+
122
+ def webpacker?
123
+ @asset_handler == :webpacker
124
+ end
125
+
126
+ def none?
127
+ @asset_handler == :none
128
+ end
129
+
130
+ def to_sym
131
+ @asset_handler
132
+ end
58
133
 
59
- def none?
60
- @asset_handler == :none
134
+ def to_s
135
+ @asset_handler.to_s
136
+ end
61
137
  end
62
138
  end
63
139
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # A container class for all user-facing (4xx) errors thrown by this library.
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  module Compatability
3
5
  module_function
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # @yield [Configuration]
3
5
  # @return [Configuration]
@@ -19,92 +21,27 @@ module Super
19
21
  # end
20
22
  # ```
21
23
  class Configuration
22
- module ConfigurationLogic # @api private
23
- def self.included(base)
24
- base.extend(ClassMethods)
25
- end
26
-
27
- def initialize
28
- self.class.defaults.each do |key, value|
29
- if value.respond_to?(:call)
30
- value = value.call
31
- end
32
-
33
- public_send("#{key}=", value)
34
- end
35
-
36
- Plugin::Registry.controller.use(prepend: Super::Filter::ControllerMethods)
37
- Plugin::Registry.controller.use(prepend: Super::Pagination::ControllerMethods)
38
- end
39
-
40
- def configured?(attr)
41
- instance_variable_defined?("@#{attr}")
42
- end
43
-
44
- module ClassMethods
45
- def defaults
46
- @defaults ||= {}
47
- end
48
-
49
- def wraps
50
- @wraps ||= {}
51
- end
52
-
53
- def configure(attr, wrap: nil, enum: nil, **kwargs)
54
- if kwargs.key?(:default)
55
- defaults[attr] = kwargs[:default]
56
- end
24
+ include ActiveSupport::Configurable
57
25
 
58
- define_method(attr) do
59
- if !configured?(attr)
60
- raise Error::UnconfiguredConfiguration, "unconfigured: #{attr}"
61
- end
62
-
63
- result = instance_variable_get("@#{attr}")
64
-
65
- if wrap.nil?
66
- result
67
- else
68
- wrap.call(result)
69
- end
70
- end
71
-
72
- define_method("#{attr}=") do |value|
73
- if enum.is_a?(Array)
74
- if !enum.include?(value)
75
- raise Error::InvalidConfiguration,
76
- "tried to set `#{attr}` to `#{value.inspect}`, " \
77
- "expected: #{enum.join(", ")}"
78
- end
79
- end
80
-
81
- instance_variable_set("@#{attr}", value)
82
- value
83
- end
84
- end
85
- end
26
+ config_accessor(:title) { "Super Admin" }
27
+ config_accessor(:index_records_per_page) { 100 }
28
+ config_accessor(:javascripts) do
29
+ [Super::Assets.auto("super/application")]
30
+ end
31
+ config_accessor(:stylesheets) do
32
+ [Super::Assets.auto("super/application")]
86
33
  end
87
34
 
88
- include ConfigurationLogic
35
+ config_accessor(:path) { "/admin" }
36
+ config_accessor(:generator_module) { "admin" }
37
+ config_accessor(:generator_as) { "admin" }
89
38
 
90
- # @!attribute [rw]
91
- configure :title
92
- # @!attribute [rw]
93
- configure :index_records_per_page, default: 20
94
- # @!attribute [rw]
95
- configure :controller_namespace, default: "admin"
96
- # @!attribute [rw]
97
- configure :route_namespace, default: :admin, wrap: -> (val) { [val].flatten }
98
- # @!attribute [rw]
99
- configure :asset_handler, default: -> { Super::Assets.auto }
39
+ def initialize
40
+ controller_plugins.use(prepend: Super::Pagination::ControllerMethods)
41
+ end
100
42
 
101
43
  def controller_plugins
102
44
  Plugin::Registry.controller
103
45
  end
104
-
105
- # @api private
106
- def path_parts(*parts)
107
- route_namespace + parts
108
- end
109
46
  end
110
47
  end
@@ -1,36 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "super/controls/optional"
2
- require "super/controls/required"
3
4
  require "super/controls/steps"
5
+ require "super/controls/view"
4
6
 
5
7
  module Super
6
- # A wrapper around the per-controller Controls classes. This class often
7
- # directly delegates to the per-controller classes, but it can also provide
8
- # some default implementation.
8
+ # The base Controls class. Most parts of Super can be configured by
9
+ # customizing its methods.
9
10
  class Controls
10
- include Required
11
11
  include Optional
12
12
  include Steps
13
+ include View
13
14
 
14
- def initialize(actual)
15
- @actual = actual
16
- end
17
-
18
- attr_reader :actual
19
-
20
- private
21
-
22
- def default_for(method_name, *args, **kwargs)
23
- if @actual.respond_to?(method_name)
24
- if args.empty? && kwargs.empty?
25
- return @actual.public_send(method_name)
26
- elsif args.empty?
27
- return @actual.public_send(method_name, **kwargs)
28
- else
29
- return @actual.public_send(method_name, *args)
30
- end
31
- end
32
-
33
- yield
15
+ # Specifies the model. This is a required method
16
+ #
17
+ # @return [ActiveRecord::Base]
18
+ def model
19
+ raise NotImplementedError
34
20
  end
35
21
  end
36
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Controls
3
5
  # Methods for `Controls` that have a sane default implementation
@@ -6,9 +8,7 @@ module Super
6
8
  #
7
9
  # @return [String]
8
10
  def title
9
- default_for(:title) do
10
- model.name.pluralize
11
- end
11
+ model.name.pluralize
12
12
  end
13
13
 
14
14
  # Configures what database records are visible on load. This is an optional
@@ -17,20 +17,49 @@ module Super
17
17
  # @param action [ActionInquirer]
18
18
  # @return [ActiveRecord::Relation]
19
19
  def scope(action:)
20
- default_for(:scope, action: action) do
21
- model.all
20
+ model.all
21
+ end
22
+
23
+ # Configures the fields that are displayed on the index and show actions.
24
+ # This is a required method
25
+ #
26
+ # @param action [ActionInquirer]
27
+ # @return [Display]
28
+ def display_schema(action:)
29
+ Display.new do |fields, type|
30
+ Display::Guesser.new(model: model, action: action, fields: fields, type: type).call
22
31
  end
23
32
  end
24
33
 
34
+ # Configures the editable fields on the new and edit actions. This is a
35
+ # required method
36
+ #
37
+ # @param action [ActionInquirer]
38
+ # @return [Form]
39
+ def form_schema(action:)
40
+ Form.new do |fields, type|
41
+ Form::Guesser.new(model: model, fields: fields, type: type).call
42
+ end
43
+ end
44
+
45
+ # Configures which parameters could be written to the database. This is a
46
+ # required method
47
+ #
48
+ # @param params [ActionController::Parameters]
49
+ # @param action [ActionInquirer]
50
+ # @return [ActionController::Parameters]
51
+ def permitted_params(params, action:)
52
+ strong_params = Super::Form::StrongParams.new(form_schema(action: action))
53
+ params.require(strong_params.require(model)).permit(strong_params.permit)
54
+ end
55
+
25
56
  # Configures the actions linked to on the index page. This is an optional
26
57
  # method
27
58
  #
28
59
  # @param action [ActionInquirer]
29
60
  # @return [Array<Link>]
30
61
  def collection_actions(action:)
31
- default_for(:collection_actions, action: action) do
32
- Super::Link.find_all(:new)
33
- end
62
+ Super::Link.find_all(:new)
34
63
  end
35
64
 
36
65
  # Configures the actions linked to on the show page as well as each row of
@@ -39,16 +68,46 @@ module Super
39
68
  # @param action [ActionInquirer]
40
69
  # @return [Array<Link>]
41
70
  def member_actions(action:)
42
- default_for(:member_actions, action: action) do
43
- if action.show?
44
- Super::Link.find_all(:edit, :destroy)
45
- elsif action.edit?
46
- Super::Link.find_all(:show, :destroy)
47
- else
48
- Super::Link.find_all(:show, :edit, :destroy)
49
- end
71
+ if action.show?
72
+ Super::Link.find_all(:edit, :destroy)
73
+ elsif action.edit?
74
+ Super::Link.find_all(:show, :destroy)
75
+ else
76
+ Super::Link.find_all(:show, :edit, :destroy)
77
+ end
78
+ end
79
+
80
+ def filters_enabled?
81
+ true
82
+ end
83
+
84
+ def filter_schema
85
+ Super::Filter.new do |fields, type|
86
+ Super::Filter::Guesser.new(model: model, fields: fields, type: type).call
50
87
  end
51
88
  end
89
+
90
+ def sort_enabled?
91
+ true
92
+ end
93
+
94
+ def sortable_columns
95
+ action = ActionInquirer.new(
96
+ ActionInquirer.default_for_resources,
97
+ "index"
98
+ )
99
+ attribute_names =
100
+ display_schema(action: action).each_attribute.map do |key, val|
101
+ val = val.build if val.respond_to?(:build)
102
+ key if val.real?
103
+ end
104
+
105
+ attribute_names.compact
106
+ end
107
+
108
+ def default_sort
109
+ { id: :desc }
110
+ end
52
111
  end
53
112
  end
54
113
  end