super 0.0.8 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +0 -7
  3. data/README.md +53 -79
  4. data/app/assets/javascripts/super/application.js +2728 -96
  5. data/app/assets/stylesheets/super/application.css +6405 -0
  6. data/app/controllers/super/application_controller.rb +19 -13
  7. data/app/helpers/super/form_builder_helper.rb +25 -0
  8. data/app/views/layouts/super/application.html.erb +11 -5
  9. data/app/views/super/application/{_super_schema_display_actions.html.erb → _display_actions.html.erb} +0 -0
  10. data/app/views/super/application/{_super_schema_display_index.html.erb → _display_index.html.erb} +5 -5
  11. data/app/views/super/application/_display_rich_text.html.erb +1 -0
  12. data/app/views/super/application/_display_show.html.erb +8 -0
  13. data/app/views/super/application/_filter.html.erb +5 -13
  14. data/app/views/super/application/_filter_type_select.html.erb +9 -19
  15. data/app/views/super/application/_filter_type_text.html.erb +7 -11
  16. data/app/views/super/application/_filter_type_timestamp.html.erb +6 -17
  17. data/app/views/super/application/_form.html.erb +15 -0
  18. data/app/views/super/application/_form_field__destroy.html.erb +1 -9
  19. data/app/views/super/application/_form_field_checkbox.html.erb +1 -0
  20. data/app/views/super/application/_form_field_flatpickr_date.html.erb +8 -0
  21. data/app/views/super/application/_form_field_flatpickr_datetime.html.erb +8 -0
  22. data/app/views/super/application/_form_field_flatpickr_time.html.erb +8 -0
  23. data/app/views/super/application/_form_field_rich_text_area.html.erb +1 -0
  24. data/app/views/super/application/_form_field_select.html.erb +1 -23
  25. data/app/views/super/application/_form_field_text.html.erb +1 -13
  26. data/app/views/super/application/{_super_layout.html.erb → _layout.html.erb} +7 -7
  27. data/app/views/super/application/{_super_pagination.html.erb → _pagination.html.erb} +1 -1
  28. data/app/views/super/application/{_super_panel.html.erb → _panel.html.erb} +2 -2
  29. data/app/views/super/application/_query.html.erb +18 -0
  30. data/app/views/super/application/_sort.html.erb +18 -0
  31. data/app/views/super/application/_sort_expression.html.erb +25 -0
  32. data/app/views/super/application/edit.html.erb +1 -0
  33. data/app/views/super/application/index.html.erb +1 -0
  34. data/app/views/super/application/new.html.erb +1 -0
  35. data/app/views/super/application/show.html.erb +1 -0
  36. data/app/views/super/feather/README.md +1 -0
  37. data/app/views/super/feather/_x.html +15 -0
  38. data/config/routes.rb +2 -0
  39. data/docs/cheat.md +8 -8
  40. data/frontend/super-frontend/dist/application.css +6405 -0
  41. data/frontend/super-frontend/dist/application.js +2728 -96
  42. data/lib/generators/super/action_text/USAGE +23 -0
  43. data/lib/generators/super/action_text/action_text_generator.rb +32 -0
  44. data/lib/generators/super/action_text/templates/pack_super_action_text.css +23 -0
  45. data/lib/generators/super/action_text/templates/pack_super_action_text.js +4 -0
  46. data/lib/generators/super/install/install_generator.rb +18 -7
  47. data/lib/generators/super/install/templates/base_controller.rb.tt +9 -1
  48. data/lib/generators/super/install/templates/initializer.rb.tt +9 -2
  49. data/lib/generators/super/resource/resource_generator.rb +107 -30
  50. data/lib/generators/super/resource/templates/resources_controller.rb.tt +3 -9
  51. data/lib/generators/super/webpacker/USAGE +5 -4
  52. data/lib/generators/super/webpacker/webpacker_generator.rb +2 -0
  53. data/lib/super.rb +7 -1
  54. data/lib/super/action_inquirer.rb +2 -0
  55. data/lib/super/assets.rb +6 -0
  56. data/lib/super/client_error.rb +2 -0
  57. data/lib/super/compatibility.rb +2 -0
  58. data/lib/super/configuration.rb +16 -24
  59. data/lib/super/controls.rb +11 -2
  60. data/lib/super/controls/optional.rb +35 -1
  61. data/lib/super/controls/steps.rb +27 -35
  62. data/lib/super/controls/view.rb +55 -0
  63. data/lib/super/display.rb +29 -13
  64. data/lib/super/display/guesser.rb +4 -0
  65. data/lib/super/display/schema_types.rb +74 -28
  66. data/lib/super/engine.rb +4 -0
  67. data/lib/super/error.rb +21 -0
  68. data/lib/super/filter.rb +2 -0
  69. data/lib/super/filter/form_object.rb +5 -8
  70. data/lib/super/filter/guesser.rb +2 -0
  71. data/lib/super/filter/operator.rb +2 -0
  72. data/lib/super/filter/schema_types.rb +2 -0
  73. data/lib/super/form.rb +3 -1
  74. data/lib/super/form/builder.rb +289 -39
  75. data/lib/super/form/guesser.rb +12 -1
  76. data/lib/super/form/inline_errors.rb +28 -0
  77. data/lib/super/form/schema_types.rb +25 -0
  78. data/lib/super/form/strong_params.rb +2 -0
  79. data/lib/super/layout.rb +3 -1
  80. data/lib/super/link.rb +7 -0
  81. data/lib/super/navigation/automatic.rb +4 -2
  82. data/lib/super/pagination.rb +3 -1
  83. data/lib/super/panel.rb +3 -1
  84. data/lib/super/partial.rb +2 -0
  85. data/lib/super/partial/resolving.rb +2 -0
  86. data/lib/super/plugin.rb +2 -0
  87. data/lib/super/query/form_object.rb +48 -0
  88. data/lib/super/schema.rb +2 -0
  89. data/lib/super/schema/common.rb +2 -0
  90. data/lib/super/schema/guesser.rb +2 -0
  91. data/lib/super/sort.rb +110 -0
  92. data/lib/super/useful/builder.rb +25 -0
  93. data/lib/super/useful/enum.rb +63 -0
  94. data/lib/super/version.rb +3 -1
  95. data/lib/super/view_helper.rb +2 -19
  96. metadata +56 -38
  97. data/CONTRIBUTING.md +0 -56
  98. data/Rakefile +0 -34
  99. data/STABILITY.md +0 -50
  100. data/app/views/super/application/_form_inline_errors.html.erb +0 -10
  101. data/app/views/super/application/_super_schema_display_show.html.erb +0 -8
  102. data/app/views/super/application/_super_schema_form.html.erb +0 -15
  103. data/docs/README.md +0 -6
  104. data/docs/faq.md +0 -44
  105. data/docs/quick_start.md +0 -45
  106. data/docs/webpacker.md +0 -17
  107. data/docs/yard_customizations.rb +0 -41
  108. data/frontend/super-frontend/build.js +0 -36
  109. data/frontend/super-frontend/package.json +0 -21
  110. data/frontend/super-frontend/postcss.config.js +0 -6
  111. data/frontend/super-frontend/src/javascripts/super/application.ts +0 -15
  112. data/frontend/super-frontend/src/javascripts/super/apply_template_controller.ts +0 -19
  113. data/frontend/super-frontend/src/javascripts/super/rails__ujs.d.ts +0 -1
  114. data/frontend/super-frontend/src/javascripts/super/toggle_pending_destruction_controller.ts +0 -15
  115. data/frontend/super-frontend/src/stylesheets/super/application.css +0 -77
  116. data/frontend/super-frontend/tailwind.config.js +0 -15
  117. data/frontend/super-frontend/tsconfig.json +0 -13
  118. data/frontend/super-frontend/yarn.lock +0 -5448
  119. data/lib/super/controls/required.rb +0 -13
  120. data/lib/super/filter/plugin.rb +0 -47
data/lib/super/engine.rb CHANGED
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # Configures the host Rails app to work with Super
3
5
  class Engine < ::Rails::Engine
6
+ isolate_namespace Super
7
+
4
8
  initializer "super.assets.precompile" do |app|
5
9
  if Super::Assets::Handler.sprockets_available?
6
10
  app.config.assets.precompile << "config/super_manifest.js"
data/lib/super/error.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # A container class for all internal errors thrown by this library
3
5
  #
@@ -13,5 +15,24 @@ module Super
13
15
  class ActionInquirerError < Error; end
14
16
  # Error raised when a `Super::Link` couldn't be found
15
17
  class LinkNotRegistered < Error; end
18
+ # Error raised when rendering if `@view` wasn't set by the controller
19
+ class NothingToRender < Error
20
+ def initialize(basename)
21
+ super(
22
+ "Super's built-in `#{basename}.html.erb` requires `@view` to be set " \
23
+ "by the controller, but it wasn't set"
24
+ )
25
+ end
26
+ end
27
+ # Error raised when something wasn't initalized correctly, and if there isn't
28
+ # a more specific error
29
+ class Initalization < Error; end
30
+ class ArgumentError < Error; end
31
+
32
+ class Enum < Error
33
+ class ImpossibleValue < Enum; end
34
+ class ArgumentError < Enum; end
35
+ class UndefinedCase < Enum; end
36
+ end
16
37
  end
17
38
  end
data/lib/super/filter.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Filter
3
5
  def initialize
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Filter
3
5
  class FormObject
@@ -42,11 +44,10 @@ module Super
42
44
  end
43
45
  end
44
46
 
45
- def initialize(model:, url:, schema:, params:)
47
+ def initialize(model:, params:, schema:)
46
48
  @model = model
47
- @url = url
48
- @schema = schema
49
49
  @params = params
50
+ @schema = schema
50
51
 
51
52
  @form_fields = {}
52
53
  end
@@ -57,15 +58,11 @@ module Super
57
58
  end
58
59
  end
59
60
 
60
- def url
61
- @url
62
- end
63
-
64
61
  def to_partial_path
65
62
  "filter"
66
63
  end
67
64
 
68
- def to_search_query(relation)
65
+ def apply_changes(relation)
69
66
  each_field do |form_field|
70
67
  next if form_field.specified_values.values.map(&:to_s).map(&:strip).all? { |specified_value| specified_value == "" }
71
68
  next if !Super::Filter::Operator.registry.key?(form_field.op)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Filter
3
5
  class Guesser
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Filter
3
5
  module Operator
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Filter
3
5
  # This schema type is used to configure the filtering form on your +#index+
data/lib/super/form.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  # This schema type is used on your +#edit+ and +#new+ forms
3
5
  #
@@ -29,7 +31,7 @@ module Super
29
31
  end
30
32
 
31
33
  def to_partial_path
32
- "super_schema_form"
34
+ "form"
33
35
  end
34
36
  end
35
37
  end
@@ -1,48 +1,298 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Super
2
4
  class Form
3
- module FieldErrorProc
4
- def error_wrapping(html_tag)
5
- if Thread.current[:super_form_builder]
6
- return html_tag
7
- end
5
+ # Example
6
+ #
7
+ # ```ruby
8
+ # super_form_for([:admin, @member]) do |f|
9
+ # # the long way
10
+ # f.super.label :name
11
+ # f.super.text_field :name
12
+ # f.super.inline_errors :name
13
+ #
14
+ # # the short way (slightly different from the long way, for alignment)
15
+ # f.super.text_field! :position
16
+ # end
17
+ # ```
18
+ #
19
+ # Refer to the Rails docs:
20
+ # https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html
21
+ class Builder < ActionView::Helpers::FormBuilder
22
+ FIELD_ERROR_PROC = proc { |html_tag, instance| html_tag }
23
+ FORM_BUILDER_DEFAULTS = { builder: self }.freeze
8
24
 
9
- super
25
+ def super(**options)
26
+ @super_wrappers ||= Wrappers.new(self, @template)
10
27
  end
11
- end
12
28
 
13
- class Builder < ActionView::Helpers::FormBuilder
14
- # These methods were originally defined in the following files
15
- #
16
- # * actionview/lib/action_view/helpers/form_helper.rb
17
- # * actionview/lib/action_view/helpers/form_options_helper.rb
18
- # * actionview/lib/action_view/helpers/date_helper.rb
19
- %w[
20
- label text_field password_field hidden_field file_field text_area
21
- check_box radio_button color_field search_field telephone_field
22
- date_field time_field datetime_field month_field week_field url_field
23
- email_field number_field range_field
24
-
25
- select collection_select grouped_collection_select time_zone_select
26
- collection_radio_buttons collection_check_boxes
27
-
28
- time_select datetime_select date_select
29
- ].each do |field_type_method|
30
- class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
31
- def #{field_type_method}(*)
32
- Thread.current[:super_form_builder] = true
33
- super
34
- ensure
35
- Thread.current[:super_form_builder] = nil
36
- end
37
- RUBY
38
- end
29
+ class Wrappers
30
+ def initialize(builder, template)
31
+ @builder = builder
32
+ @template = template
33
+ end
34
+
35
+ def inline_errors(attribute)
36
+ if @builder.object
37
+ messages = InlineErrors.error_messages(@builder.object, attribute).map do |msg|
38
+ error_content_tag(msg)
39
+ end
40
+
41
+ @template.safe_join(messages)
42
+ else
43
+ error_content_tag(<<~MSG.html_safe)
44
+ This form doesn't have an object, so something is probably wrong.
45
+ Maybe <code>accepts_nested_attributes_for</code> isn't set up?
46
+ MSG
47
+ end
48
+ end
49
+
50
+ def label(attribute, text = nil, options = {}, &block)
51
+ options, defaults = split_defaults(options, class: "block")
52
+ options[:class] = join_classes(defaults[:class], options[:class])
53
+
54
+ @builder.label(attribute, text, options, &block)
55
+ end
56
+
57
+ def check_box(attribute, options = {}, checked_value = "1", unchecked_value = "0")
58
+ @builder.check_box(attribute, options, checked_value, unchecked_value)
59
+ end
60
+
61
+ def flatpickr_date(attribute, options = {})
62
+ options, defaults = split_defaults(
63
+ options,
64
+ class: "super-input w-full",
65
+ data: {
66
+ controller: "flatpickr",
67
+ flatpickr_options_value: {
68
+ dateFormat: "Y-m-d",
69
+ }
70
+ }
71
+ )
72
+ options[:class] = join_classes(defaults[:class], options[:class])
73
+ options[:data] = defaults[:data].deep_merge(options[:data] || {})
74
+
75
+ @builder.text_field(attribute, options)
76
+ end
77
+
78
+ def flatpickr_datetime(attribute, options = {})
79
+ options, defaults = split_defaults(
80
+ options,
81
+ class: "super-input w-full",
82
+ data: {
83
+ controller: "flatpickr",
84
+ flatpickr_options_value: {
85
+ enableSeconds: true,
86
+ enableTime: true,
87
+ dateFormat: "Z",
88
+ }
89
+ }
90
+ )
91
+ options[:class] = join_classes(defaults[:class], options[:class])
92
+ options[:data] = defaults[:data].deep_merge(options[:data] || {})
39
93
 
40
- alias datetime_local_field datetime_field
41
- alias phone_field telephone_field
94
+ @builder.text_field(attribute, options)
95
+ end
96
+
97
+ def flatpickr_time(attribute, options = {})
98
+ options, defaults = split_defaults(
99
+ options,
100
+ class: "super-input w-full",
101
+ data: {
102
+ controller: "flatpickr",
103
+ flatpickr_options_value: {
104
+ enableSeconds: true,
105
+ enableTime: true,
106
+ noCalendar: true,
107
+ dateFormat: "H:i:S",
108
+ }
109
+ }
110
+ )
111
+ options[:class] = join_classes(defaults[:class], options[:class])
112
+ options[:data] = defaults[:data].deep_merge(options[:data] || {})
113
+
114
+ @builder.text_field(attribute, options)
115
+ end
116
+
117
+ def password_field(attribute, options = {})
118
+ options, defaults = split_defaults(options, class: "super-input w-full")
119
+ options[:class] = join_classes(defaults[:class], options[:class])
120
+
121
+ @builder.password_field(attribute, options)
122
+ end
123
+
124
+ def rich_text_area(attribute, options = {})
125
+ options, defaults = split_defaults(options, class: "trix-content super-input w-full")
126
+ options[:class] = join_classes(defaults[:class], options[:class])
127
+
128
+ @builder.rich_text_area(attribute, options)
129
+ end
130
+
131
+ def select(attribute, choices, options = {}, html_options = {}, &block)
132
+ options, defaults = split_defaults(options, include_blank: true)
133
+ options = defaults.merge(options)
134
+ html_options, html_defaults = split_defaults(html_options, class: "super-input super-input-select-field")
135
+ html_options[:class] = join_classes(html_defaults[:class], html_options[:class])
136
+
137
+ parts = [
138
+ %(<div class="super-input-select">).html_safe,
139
+ @builder.select(attribute, choices, options, html_options, &block),
140
+ <<~HTML.html_safe,
141
+ <div class="super-input-select-icon text-blue-700">
142
+ <span class="h-4 w-4">
143
+ HTML
144
+ @template.render("super/feather/chevron_down"),
145
+ <<~HTML.html_safe,
146
+ </span>
147
+ </div>
148
+ HTML
149
+ %(</div>).html_safe,
150
+ ]
151
+
152
+ @template.safe_join(parts)
153
+ end
154
+
155
+ def submit(value = nil, options = {})
156
+ value, options = nil, value if value.is_a?(Hash)
157
+ options, defaults = split_defaults(options, class: "super-button")
158
+ options[:class] = join_classes(defaults[:class], options[:class])
159
+
160
+ @builder.submit(value, options)
161
+ end
162
+
163
+ def text_field(attribute, options = {})
164
+ options, defaults = split_defaults(options, class: "super-input w-full")
165
+ options[:class] = join_classes(defaults[:class], options[:class])
166
+
167
+ @builder.text_field(attribute, options)
168
+ end
169
+
170
+ def container(&block)
171
+ @template.content_tag(:div, class: "super-field-group", &block)
172
+ end
173
+
174
+ def check_box!(attribute, checked_value = "1", unchecked_value = "0", label: {}, field: {}, show_errors: true)
175
+ label[:super] ||= {}
176
+ label[:super] = { class: "select-none ml-1" }.merge(label[:super])
177
+ container do
178
+ compact_join([
179
+ "<div>".html_safe,
180
+ public_send(:check_box, attribute, field, checked_value, unchecked_value),
181
+ public_send(:label, attribute, nil, label),
182
+ "</div>".html_safe,
183
+ show_errors && inline_errors(attribute),
184
+ ])
185
+ end
186
+ end
187
+
188
+ def flatpickr_date!(attribute, label: {}, field: {}, show_errors: true)
189
+ container do
190
+ compact_join([
191
+ public_send(:label, attribute, label),
192
+ %(<div class="mt-1">).html_safe,
193
+ public_send(:flatpickr_date, attribute, field),
194
+ show_errors && inline_errors(attribute),
195
+ %(</div>).html_safe,
196
+ ])
197
+ end
198
+ end
199
+
200
+ def flatpickr_datetime!(attribute, label: {}, field: {}, show_errors: true)
201
+ container do
202
+ compact_join([
203
+ public_send(:label, attribute, label),
204
+ %(<div class="mt-1">).html_safe,
205
+ public_send(:flatpickr_datetime, attribute, field),
206
+ show_errors && inline_errors(attribute),
207
+ %(</div>).html_safe,
208
+ ])
209
+ end
210
+ end
211
+
212
+ def flatpickr_time!(attribute, label: {}, field: {}, show_errors: true)
213
+ container do
214
+ compact_join([
215
+ public_send(:label, attribute, label),
216
+ %(<div class="mt-1">).html_safe,
217
+ public_send(:flatpickr_time, attribute, field),
218
+ show_errors && inline_errors(attribute),
219
+ %(</div>).html_safe,
220
+ ])
221
+ end
222
+ end
223
+
224
+ def password_field!(attribute, label: {}, field: {}, show_errors: true)
225
+ container do
226
+ compact_join([
227
+ public_send(:label, attribute, label),
228
+ %(<div class="mt-1">).html_safe,
229
+ public_send(:password_field, attribute, field),
230
+ show_errors && inline_errors(attribute),
231
+ %(</div>).html_safe,
232
+ ])
233
+ end
234
+ end
235
+
236
+ def rich_text_area!(attribute, label: {}, field: {}, show_errors: true)
237
+ container do
238
+ compact_join([
239
+ public_send(:label, attribute, label),
240
+ %(<div class="mt-1">).html_safe,
241
+ public_send(:rich_text_area, attribute, field),
242
+ show_errors && inline_errors(attribute),
243
+ %(</div>).html_safe,
244
+ ])
245
+ end
246
+ end
247
+
248
+ def select!(attribute, collection, label: {}, field: {}, show_errors: true)
249
+ container do
250
+ compact_join([
251
+ public_send(:label, attribute, label),
252
+ %(<div class="mt-1">).html_safe,
253
+ public_send(:select, attribute, collection, field),
254
+ show_errors && inline_errors(attribute),
255
+ %(</div>).html_safe,
256
+ ])
257
+ end
258
+ end
259
+
260
+ def text_field!(attribute, label: {}, field: {}, show_errors: true)
261
+ container do
262
+ compact_join([
263
+ public_send(:label, attribute, label),
264
+ %(<div class="mt-1">).html_safe,
265
+ public_send(:text_field, attribute, field),
266
+ show_errors && inline_errors(attribute),
267
+ %(</div>).html_safe,
268
+ ])
269
+ end
270
+ end
271
+
272
+ private
273
+
274
+ def split_defaults(options, **internal_defaults)
275
+ defaults = options.delete(:super) || {}
276
+ # prefer options set in `defaults`, since they are user overrides
277
+ defaults = internal_defaults.merge(defaults)
278
+
279
+ [options, defaults]
280
+ end
281
+
282
+ def join_classes(*class_lists)
283
+ class_lists.flatten.map(&:presence).compact
284
+ end
285
+
286
+ def error_content_tag(content)
287
+ @template.content_tag(:p, content, class: "text-red-400 text-xs italic pt-1")
288
+ end
289
+
290
+ def compact_join(*parts)
291
+ @template.safe_join(
292
+ parts.flatten.map(&:presence).compact
293
+ )
294
+ end
295
+ end
42
296
  end
43
297
  end
44
298
  end
45
-
46
- ActionView::Helpers::Tags::Base.class_eval do
47
- prepend Super::Form::FieldErrorProc
48
- end