super 0.0.7 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
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