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
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class Form
5
+ class Guesser
6
+ def initialize(model:, fields:, type:)
7
+ @model = model
8
+ @fields = fields
9
+ @type = type
10
+ end
11
+
12
+ def call
13
+ Schema::Guesser
14
+ .new(model: @model, fields: @fields, type: @type)
15
+ .assign_type { |attribute_name| attribute_type_for(attribute_name) }
16
+ .reject { |attribute_name| attribute_name == "id" }
17
+ .reject { |attribute_name| attribute_name == "created_at" }
18
+ .reject { |attribute_name| attribute_name == "updated_at" }
19
+ .call
20
+ end
21
+
22
+ private
23
+
24
+ def attribute_type_for(attribute_name)
25
+ @type.string
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class Form
5
+ module InlineErrors
6
+ module_function
7
+
8
+ def error_messages(model_instance, column_or_association)
9
+ errable_fields(model_instance, column_or_association)
10
+ .flat_map { |field| Compatability.errable_fields(field) }
11
+ .flat_map { |field| model_instance.errors.full_messages_for(field) }
12
+ .uniq
13
+ end
14
+
15
+ def errable_fields(model_instance, column_or_association)
16
+ column_or_association = column_or_association.to_s
17
+ reflection = model_instance.class.reflect_on_association(column_or_association)
18
+ reflection ||= model_instance.class.reflections.values.find { |r| r.foreign_key == column_or_association }
19
+
20
+ if reflection
21
+ [reflection.name.to_s, reflection.foreign_key.to_s]
22
+ else
23
+ [column_or_association]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,26 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Form
3
- # This schema type is used on your +#edit+ and +#new+ forms
4
- #
5
- # ```ruby
6
- # class MembersController::Controls
7
- # # ...
8
- #
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
- # )
18
- # end
19
- # end
20
- #
21
- # # ...
22
- # end
23
- # ```
24
5
  class SchemaTypes
25
6
  class Generic
26
7
  def initialize(partial_path:, extras:, nested:)
@@ -31,6 +12,16 @@ module Super
31
12
 
32
13
  attr_reader :nested_fields
33
14
 
15
+ def each_attribute
16
+ if block_given?
17
+ @nested_fields.each do |key, value|
18
+ yield(key, value)
19
+ end
20
+ end
21
+
22
+ enum_for(:each_attribute)
23
+ end
24
+
34
25
  # This takes advantage of a feature of Rails. If the value of
35
26
  # `#to_partial_path` is `my_form_field`, Rails renders
36
27
  # `app/views/super/application/_my_form_field.html.erb`, and this
@@ -69,17 +60,32 @@ module Super
69
60
  end
70
61
  end
71
62
 
72
- def before_yield(fields:)
63
+ def initialize(fields:)
73
64
  @fields = fields
74
65
  end
75
66
 
76
- def after_yield
77
- end
78
-
79
67
  def generic(partial_path, **extras)
80
68
  Generic.new(partial_path: partial_path, extras: extras, nested: {})
81
69
  end
82
70
 
71
+ def select(**extras)
72
+ Generic.new(partial_path: "form_field_select", extras: extras, nested: {})
73
+ end
74
+
75
+ def string(**extras)
76
+ Generic.new(partial_path: "form_field_text", extras: extras, nested: {})
77
+ end
78
+
79
+ alias text string
80
+
81
+ def rich_text_area(**extras)
82
+ Generic.new(partial_path: "form_field_rich_text_area", extras: extras, nested: {})
83
+ end
84
+
85
+ def checkbox(**extras)
86
+ Generic.new(partial_path: "form_field_checkbox", extras: extras, nested: {})
87
+ end
88
+
83
89
  def has_many(reader, **extras)
84
90
  nested = @fields.nested do
85
91
  yield
@@ -113,10 +119,6 @@ module Super
113
119
  nested: {}
114
120
  )
115
121
  end
116
-
117
- def to_partial_path
118
- "super_schema_form"
119
- end
120
122
  end
121
123
  end
122
124
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ class Form
5
+ class StrongParams
6
+ def initialize(form_schema)
7
+ @form_schema = form_schema
8
+ end
9
+
10
+ def require(model)
11
+ model.model_name.singular
12
+ end
13
+
14
+ def permit
15
+ unfurl(@form_schema)
16
+ end
17
+
18
+ private
19
+
20
+ def unfurl(responds_to_each_attribute)
21
+ responds_to_each_attribute.each_attribute.map do |name, type|
22
+ if type.nested_fields&.any?
23
+ { name => [:id, *unfurl(type)] }
24
+ else
25
+ name
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/super/layout.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "super/partial/resolving"
2
4
 
3
5
  module Super
@@ -17,7 +19,7 @@ module Super
17
19
  attr_reader :footers
18
20
 
19
21
  def to_partial_path
20
- "super_layout"
22
+ "layout"
21
23
  end
22
24
 
23
25
  def resolve(template)
data/lib/super/link.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # Links have three required attributes that are passed directly into Rails'
3
5
  # `link_to` helper
@@ -78,6 +80,11 @@ module Super
78
80
  }
79
81
  end
80
82
 
83
+ def self.polymorphic_parts(*parts_tail)
84
+ parts_head = Super.configuration.path.strip.gsub(%r{\A/+}, "").gsub(%r{/+\z}, "").strip.split("/")
85
+ parts_head + parts_tail
86
+ end
87
+
81
88
  def initialize(text, href, **options)
82
89
  @text = text
83
90
  @href = href
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Navigation
3
5
  # Traverses the defined Rails Routes and attempts to build a list of links.
4
6
  # This is used for building the nav bar on each admin page.
5
7
  class Automatic
6
- def initialize(route_namespace:)
7
- route_namespace = route_namespace.to_s
8
+ def initialize(route_namespace: Super.configuration.path)
9
+ route_namespace = route_namespace.strip.gsub(%r{\A/+}, "").gsub(%r{/+\z}, "").strip
8
10
 
9
11
  if route_namespace.include?("/")
10
12
  raise "Can't be nested namespace"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Pagination
3
5
  include Enumerable
@@ -53,7 +55,7 @@ module Super
53
55
  end
54
56
 
55
57
  def to_partial_path
56
- "super_pagination"
58
+ "pagination"
57
59
  end
58
60
 
59
61
  private
@@ -89,9 +91,7 @@ module Super
89
91
  # @param query_params [Hash]
90
92
  # @return [ActiveRecord::Relation]
91
93
  def records_per_page(action:, query_params:)
92
- default_for(:records_per_page, action: action, query_params: query_params) do
93
- Super.configuration.index_records_per_page
94
- end
94
+ Super.configuration.index_records_per_page
95
95
  end
96
96
  end
97
97
 
@@ -103,14 +103,12 @@ module Super
103
103
  # @param query_params [Hash]
104
104
  # @return [Pagination]
105
105
  def initialize_pagination(action:, records:, query_params:)
106
- default_for(:initialize_pagination, action: action, records: records, query_params: query_params) do
107
- Pagination.new(
108
- total_count: records.size,
109
- limit: records_per_page(action: action, query_params: query_params),
110
- query_params: query_params,
111
- page_query_param: :page
112
- )
113
- end
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
+ )
114
112
  end
115
113
 
116
114
  # Paginates
@@ -120,11 +118,9 @@ module Super
120
118
  # @param pagination [Pagination]
121
119
  # @return [ActiveRecord::Relation]
122
120
  def paginate_records(action:, records:, pagination:)
123
- default_for(:paginate_records, action: action, records: records, pagination: pagination) do
124
- records
125
- .limit(pagination.limit)
126
- .offset(pagination.offset)
127
- end
121
+ records
122
+ .limit(pagination.limit)
123
+ .offset(pagination.offset)
128
124
  end
129
125
  end
130
126
  end
data/lib/super/panel.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "super/partial/resolving"
2
4
 
3
5
  module Super
@@ -24,7 +26,7 @@ module Super
24
26
  end
25
27
 
26
28
  def to_partial_path
27
- "super_panel"
29
+ "panel"
28
30
  end
29
31
  end
30
32
  end
data/lib/super/partial.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Partial
3
5
  def self.render(partialish, template:)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Partial
3
5
  module Resolving
data/lib/super/plugin.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  module Plugin
3
5
  class Registry
@@ -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,31 +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
- attr_reader :schema_type
24
-
25
- def field_keys
26
- fields.keys
27
- end
28
-
29
- def to_partial_path
30
- @schema_type.to_partial_path
31
- end
32
-
33
10
  # This class can be thought of as a Hash, where the keys usually refer to
34
11
  # the model's column name and the value refers to the column type. Note
35
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