super 0.0.11 → 0.0.16

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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +0 -9
  3. data/README.md +42 -54
  4. data/app/assets/javascripts/super/application.js +5617 -3806
  5. data/app/assets/stylesheets/super/application.css +114687 -71486
  6. data/app/controllers/super/application_controller.rb +41 -47
  7. data/app/controllers/super/substructure_controller.rb +265 -0
  8. data/app/helpers/super/form_builder_helper.rb +7 -0
  9. data/app/views/layouts/super/application.html.erb +4 -21
  10. data/app/views/super/application/_collection_header.html.erb +2 -2
  11. data/app/views/super/application/{_super_schema_display_actions.html.erb → _display_actions.html.erb} +1 -1
  12. data/app/views/super/application/{_super_schema_display_index.html.erb → _display_index.html.erb} +5 -5
  13. data/app/views/super/application/_display_show.html.erb +8 -0
  14. data/app/views/super/application/_filter_type_select.html.erb +1 -1
  15. data/app/views/super/application/_filter_type_text.html.erb +1 -1
  16. data/app/views/super/application/_filter_type_timestamp.html.erb +3 -3
  17. data/app/views/super/application/{_super_schema_form.html.erb → _form.html.erb} +2 -2
  18. data/app/views/super/application/_form_field.html.erb +5 -0
  19. data/app/views/super/application/{_super_layout.html.erb → _layout.html.erb} +8 -8
  20. data/app/views/super/application/_member_header.html.erb +2 -2
  21. data/app/views/super/application/{_super_pagination.html.erb → _pagination.html.erb} +1 -1
  22. data/app/views/super/application/{_super_panel.html.erb → _panel.html.erb} +2 -2
  23. data/app/views/super/application/_site_footer.html.erb +3 -0
  24. data/app/views/super/application/_site_header.html.erb +17 -0
  25. data/app/views/super/feather/README.md +0 -1
  26. data/frontend/super-frontend/dist/application.css +114687 -71486
  27. data/frontend/super-frontend/dist/application.js +5617 -3806
  28. data/lib/generators/super/install/install_generator.rb +16 -23
  29. data/lib/generators/super/install/templates/base_controller.rb.tt +1 -1
  30. data/lib/generators/super/install/templates/initializer.rb.tt +9 -2
  31. data/lib/generators/super/resource/resource_generator.rb +105 -30
  32. data/lib/generators/super/resource/templates/resources_controller.rb.tt +4 -10
  33. data/lib/generators/super/webpacker/webpacker_generator.rb +9 -5
  34. data/lib/super.rb +6 -2
  35. data/lib/super/action_inquirer.rb +18 -3
  36. data/lib/super/assets.rb +44 -23
  37. data/lib/super/badge.rb +60 -0
  38. data/lib/super/cheat.rb +17 -0
  39. data/lib/super/compatibility.rb +19 -0
  40. data/lib/super/configuration.rb +14 -23
  41. data/lib/super/display.rb +16 -8
  42. data/lib/super/display/guesser.rb +2 -0
  43. data/lib/super/display/schema_types.rb +116 -29
  44. data/lib/super/error.rb +7 -0
  45. data/lib/super/form.rb +1 -1
  46. data/lib/super/form/builder.rb +107 -27
  47. data/lib/super/form/guesser.rb +10 -1
  48. data/lib/super/form/schema_types.rb +73 -7
  49. data/lib/super/layout.rb +1 -1
  50. data/lib/super/link.rb +42 -31
  51. data/lib/super/link_builder.rb +58 -0
  52. data/lib/super/navigation.rb +164 -0
  53. data/lib/super/pagination.rb +3 -45
  54. data/lib/super/panel.rb +1 -1
  55. data/lib/super/reset.rb +22 -0
  56. data/lib/super/useful/builder.rb +25 -0
  57. data/lib/super/useful/enum.rb +63 -0
  58. data/lib/super/version.rb +1 -1
  59. data/lib/tasks/super/cheat.rake +9 -0
  60. metadata +27 -31
  61. data/CONTRIBUTING.md +0 -56
  62. data/Rakefile +0 -36
  63. data/STABILITY.md +0 -50
  64. data/app/views/super/application/_form_field_checkbox.html.erb +0 -1
  65. data/app/views/super/application/_form_field_rich_text_area.html.erb +0 -1
  66. data/app/views/super/application/_form_field_text.html.erb +0 -1
  67. data/app/views/super/application/_super_schema_display_show.html.erb +0 -8
  68. data/app/views/super/feather/_chevron_down.html +0 -1
  69. data/docs/README.md +0 -8
  70. data/docs/action_text.md +0 -48
  71. data/docs/cheat.md +0 -41
  72. data/docs/faq.md +0 -44
  73. data/docs/installation.md +0 -21
  74. data/docs/quick_start.md +0 -30
  75. data/docs/webpacker.md +0 -25
  76. data/docs/yard_customizations.rb +0 -43
  77. data/lib/super/controls.rb +0 -17
  78. data/lib/super/controls/optional.rb +0 -112
  79. data/lib/super/controls/required.rb +0 -15
  80. data/lib/super/controls/steps.rb +0 -106
  81. data/lib/super/controls/view.rb +0 -55
  82. data/lib/super/navigation/automatic.rb +0 -73
@@ -2,100 +2,94 @@
2
2
 
3
3
  module Super
4
4
  # Provides a default implementation for each of the resourceful actions
5
- class ApplicationController < ActionController::Base
5
+ class ApplicationController < SubstructureController
6
6
  include ClientError::Handling
7
7
 
8
- helper_method :action_inquirer
9
- helper_method :controls
8
+ helper_method :current_action
10
9
 
11
10
  # Displays a list of records to the user
12
11
  def index
13
- @records = controls.load_records(action: action_inquirer, params: params)
14
- @display = controls.display_schema(action: action_inquirer).apply(action: action_inquirer)
15
- @view = controls.index_view
16
- @query_form = controls.initialize_query_form(params: params, current_path: request.path)
17
- controls.initialize_filter_form(query_form: @query_form)
18
- controls.initialize_sort_form(query_form: @query_form)
19
- @records = controls.apply_queries(query_form: @query_form, records: @records)
12
+ @records = load_records
13
+ @display = display_schema.apply(action: current_action)
14
+ @view = index_view
15
+ @query_form = initialize_query_form
16
+ initialize_filter_form
17
+ initialize_sort_form
18
+ @records = apply_queries
20
19
  end
21
20
 
22
21
  # Displays a specific record to the user
23
22
  def show
24
- @record = controls.load_record(action: action_inquirer, params: params)
25
- @display = controls.display_schema(action: action_inquirer).apply(action: action_inquirer)
26
- @view = controls.show_view
23
+ @record = load_record
24
+ @display = display_schema.apply(action: current_action)
25
+ @view = show_view
27
26
  end
28
27
 
29
28
  # Displays a form to allow the user to create a new record
30
29
  def new
31
- @record = controls.build_record(action: action_inquirer)
32
- @form = controls.form_schema(action: action_inquirer)
33
- @view = controls.new_view
30
+ @record = build_record
31
+ @form = form_schema
32
+ @view = new_view
34
33
  end
35
34
 
36
35
  # Creates a record, or shows the validation errors
37
36
  def create
38
- @record = controls.build_record_with_params(action: action_inquirer, params: params)
37
+ @record = build_record_with_params
39
38
 
40
- if controls.save_record(action: action_inquirer, record: @record, params: params)
41
- redirect_to polymorphic_path(Super.configuration.path_parts(@record))
39
+ if save_record
40
+ redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
42
41
  else
43
- @form = controls.form_schema(action: action_inquirer_for("new"))
44
- @view = controls.new_view
42
+ @current_action = ActionInquirer.new!
43
+ @form = form_schema
44
+ @view = new_view
45
45
  render :new, status: :bad_request
46
46
  end
47
47
  end
48
48
 
49
49
  # Displays a form to allow the user to update an existing record
50
50
  def edit
51
- @record = controls.load_record(action: action_inquirer, params: params)
52
- @form = controls.form_schema(action: action_inquirer)
53
- @view = controls.edit_view
51
+ @record = load_record
52
+ @form = form_schema
53
+ @view = edit_view
54
54
  end
55
55
 
56
56
  # Updates a record, or shows validation errors
57
57
  def update
58
- @record = controls.load_record(action: action_inquirer, params: params)
58
+ @record = load_record
59
59
 
60
- if controls.update_record(action: action_inquirer, record: @record, params: params)
61
- redirect_to polymorphic_path(Super.configuration.path_parts(@record))
60
+ if update_record
61
+ redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
62
62
  else
63
- @form = controls.form_schema(action: action_inquirer_for("edit"))
64
- @view = controls.edit_view
63
+ @current_action = ActionInquirer.edit!
64
+ @form = form_schema
65
+ @view = edit_view
65
66
  render :edit, status: :bad_request
66
67
  end
67
68
  end
68
69
 
69
70
  # Deletes a record, or shows validation errors
70
71
  def destroy
71
- @record = controls.load_record(action: action_inquirer, params: params)
72
+ @record = load_record
72
73
 
73
- if controls.destroy_record(action: action_inquirer, record: @record, params: params)
74
- redirect_to polymorphic_path(Super.configuration.path_parts(controls.model))
74
+ if destroy_record
75
+ redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
75
76
  else
76
77
  flash.alert = "Couldn't delete record"
77
- redirect_to polymorphic_path(Super.configuration.path_parts(@record))
78
+ redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
78
79
  end
79
80
  rescue ActiveRecord::InvalidForeignKey => e
80
81
  flash.alert = "Couldn't delete record: #{e.class}"
81
- redirect_to polymorphic_path(Super.configuration.path_parts(@record))
82
+ redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
82
83
  end
83
84
 
84
85
  private
85
86
 
86
- def controls
87
- @controls ||= new_controls
88
- end
89
-
90
- def action_inquirer
91
- @action_inquirer ||= action_inquirer_for(params[:action])
92
- end
93
-
94
- def action_inquirer_for(action)
95
- ActionInquirer.new(
96
- ActionInquirer.default_for_resources,
97
- action
98
- )
87
+ def current_action
88
+ @current_action ||=
89
+ ActionInquirer.new(
90
+ ActionInquirer.default_for_resources,
91
+ params[:action]
92
+ )
99
93
  end
100
94
  end
101
95
  end
@@ -0,0 +1,265 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Super
4
+ # Various methods that determine the behavior of your controllers. These
5
+ # methods can and should be overridden.
6
+ class SubstructureController < ActionController::Base
7
+ private
8
+
9
+ helper_method def model
10
+ raise NotImplementedError
11
+ end
12
+
13
+ # This is an optional method
14
+ #
15
+ # @return [String]
16
+ helper_method def title
17
+ model.name.pluralize
18
+ end
19
+
20
+ # Configures what database records are visible on load. This is an optional
21
+ # method, it defaults to "`all`" methods
22
+ #
23
+ # @return [ActiveRecord::Relation]
24
+ helper_method def base_scope
25
+ model.all
26
+ end
27
+
28
+ # Configures the fields that are displayed on the index and show actions.
29
+ # This is a required method
30
+ #
31
+ # @return [Display]
32
+ helper_method def display_schema
33
+ Display.new do |fields, type|
34
+ Display::Guesser.new(model: model, action: current_action, fields: fields, type: type).call
35
+ end
36
+ end
37
+
38
+ # Configures the editable fields on the new and edit actions. This is a
39
+ # required method
40
+ #
41
+ # @return [Form]
42
+ helper_method def form_schema
43
+ Form.new do |fields, type|
44
+ Form::Guesser.new(model: model, fields: fields, type: type).call
45
+ end
46
+ end
47
+
48
+ # Configures which parameters could be written to the database. This is a
49
+ # required method
50
+ #
51
+ # @return [ActionController::Parameters]
52
+ helper_method def permitted_params
53
+ strong_params = Super::Form::StrongParams.new(form_schema)
54
+ params.require(strong_params.require(model)).permit(strong_params.permit)
55
+ end
56
+
57
+ # Configures the actions linked to on the index page. This is an optional
58
+ # method
59
+ #
60
+ # @return [Array<Link>]
61
+ helper_method def collection_actions
62
+ Super::Link.find_all(:new)
63
+ end
64
+
65
+ # Configures the actions linked to on the show page as well as each row of
66
+ # the table on the index page. This is an optional method
67
+ #
68
+ # @return [Array<Link>]
69
+ helper_method def member_actions
70
+ if current_action.show?
71
+ Super::Link.find_all(:edit, :destroy)
72
+ elsif current_action.edit?
73
+ Super::Link.find_all(:show, :destroy)
74
+ else
75
+ Super::Link.find_all(:show, :edit, :destroy)
76
+ end
77
+ end
78
+
79
+ helper_method def filters_enabled?
80
+ true
81
+ end
82
+
83
+ helper_method def filter_schema
84
+ Super::Filter.new do |fields, type|
85
+ Super::Filter::Guesser.new(model: model, fields: fields, type: type).call
86
+ end
87
+ end
88
+
89
+ helper_method def sort_enabled?
90
+ true
91
+ end
92
+
93
+ helper_method def sortable_columns
94
+ action = ActionInquirer.new(
95
+ ActionInquirer.default_for_resources,
96
+ "index"
97
+ )
98
+ attribute_names =
99
+ display_schema.each_attribute.map do |key, val|
100
+ val = val.build if val.respond_to?(:build)
101
+ key if val.real?
102
+ end
103
+
104
+ attribute_names.compact
105
+ end
106
+
107
+ helper_method def default_sort
108
+ { id: :desc }
109
+ end
110
+
111
+ # Specifies how many records to show per page
112
+ #
113
+ # @return [ActiveRecord::Relation]
114
+ helper_method def records_per_page
115
+ Super.configuration.index_records_per_page
116
+ end
117
+
118
+ def load_records
119
+ base_scope
120
+ end
121
+
122
+ def load_record
123
+ base_scope.find(params[:id])
124
+ end
125
+
126
+ def build_record
127
+ base_scope.build
128
+ end
129
+
130
+ def build_record_with_params
131
+ base_scope.build(permitted_params)
132
+ end
133
+
134
+ def save_record
135
+ @record.save
136
+ end
137
+
138
+ def update_record
139
+ @record.update(permitted_params)
140
+ end
141
+
142
+ def destroy_record
143
+ @record.destroy
144
+ end
145
+
146
+ def initialize_query_form
147
+ Super::Query::FormObject.new(
148
+ model: model,
149
+ params: params,
150
+ namespace: :q,
151
+ current_path: request.path,
152
+ )
153
+ end
154
+
155
+ def apply_queries
156
+ @query_form.apply_changes(@records)
157
+ end
158
+
159
+ def initialize_filter_form
160
+ if filters_enabled?
161
+ @query_form.add(
162
+ Super::Filter::FormObject,
163
+ namespace: :f,
164
+ schema: filter_schema
165
+ )
166
+ end
167
+ end
168
+
169
+ def initialize_sort_form
170
+ if sort_enabled?
171
+ @query_form.add(
172
+ Super::Sort::FormObject,
173
+ namespace: :s,
174
+ default: default_sort,
175
+ sortable_columns: sortable_columns
176
+ )
177
+ end
178
+ end
179
+
180
+ # Sets up pagination
181
+ #
182
+ # @return [Pagination]
183
+ def initialize_pagination
184
+ Pagination.new(
185
+ total_count: @records.size,
186
+ limit: records_per_page,
187
+ query_params: request.GET,
188
+ page_query_param: :page
189
+ )
190
+ end
191
+
192
+ # Paginates
193
+ #
194
+ # @return [ActiveRecord::Relation]
195
+ def paginate_records
196
+ @records
197
+ .limit(@pagination.limit)
198
+ .offset(@pagination.offset)
199
+ end
200
+
201
+ def index_view
202
+ Super::Layout.new(
203
+ mains: [
204
+ Super::Panel.new(
205
+ Super::Partial.new("collection_header"),
206
+ :@display
207
+ ),
208
+ ],
209
+ asides: [
210
+ :@query_form,
211
+ ]
212
+ )
213
+ end
214
+
215
+ def show_view
216
+ Super::Layout.new(
217
+ mains: [
218
+ Super::Panel.new(
219
+ Super::Partial.new("member_header"),
220
+ :@display
221
+ ),
222
+ ]
223
+ )
224
+ end
225
+
226
+ def new_view
227
+ Super::Layout.new(
228
+ mains: [
229
+ Super::Panel.new(
230
+ Super::Partial.new("collection_header"),
231
+ :@form
232
+ ),
233
+ ]
234
+ )
235
+ end
236
+
237
+ def edit_view
238
+ Super::Layout.new(
239
+ mains: [
240
+ Super::Panel.new(
241
+ Super::Partial.new("member_header"),
242
+ :@form
243
+ ),
244
+ ]
245
+ )
246
+ end
247
+
248
+ concerning :Sitewide do
249
+ included do
250
+ helper_method :site_title
251
+ helper_method :site_navigation
252
+ end
253
+
254
+ private
255
+
256
+ def site_title
257
+ Super.configuration.title
258
+ end
259
+
260
+ def site_navigation
261
+ Super::Navigation.new(&:all)
262
+ end
263
+ end
264
+ end
265
+ end
@@ -1,7 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Super
4
+ # These are form builder view helpers. They are similar to what Rails ships
5
+ # out of the box but adds some styling and functionality.
6
+ #
7
+ # These helpers are available both in Super views and in your application's
8
+ # views.
4
9
  module FormBuilderHelper
10
+ # Super's version of `#form_for`
5
11
  def super_form_for(record, options = {}, &block)
6
12
  original = ActionView::Base.field_error_proc
7
13
  ActionView::Base.field_error_proc = Form::Builder::FIELD_ERROR_PROC
@@ -12,6 +18,7 @@ module Super
12
18
  ActionView::Base.field_error_proc = original
13
19
  end
14
20
 
21
+ # Super's version of `#form_with`
15
22
  def super_form_with(**options, &block)
16
23
  original = ActionView::Base.field_error_proc
17
24
  ActionView::Base.field_error_proc = Form::Builder::FIELD_ERROR_PROC
@@ -13,11 +13,7 @@
13
13
  <% if stylesheet.handler.sprockets? %>
14
14
  <%= stylesheet_link_tag(stylesheet.path, **stylesheet.arguments) %>
15
15
  <% elsif stylesheet.handler.webpacker? %>
16
- <% if Gem::Dependency.new("webpacker", "> 5.99", "< 7").matching_specs.any? %>
17
- <%= stylesheet_packs_with_chunks_tag(stylesheet.path) %>
18
- <% else %>
19
- <%= stylesheet_pack_tag(stylesheet.path, **stylesheet.arguments) %>
20
- <% end %>
16
+ <%= stylesheet_pack_tag(stylesheet.path, **stylesheet.arguments) %>
21
17
  <% end %>
22
18
  <% end %>
23
19
 
@@ -25,25 +21,14 @@
25
21
  <% if javascript.handler.sprockets? %>
26
22
  <%= javascript_include_tag(javascript.path) %>
27
23
  <% elsif javascript.handler.webpacker? %>
28
- <% if Gem::Dependency.new("webpacker", "> 5.99", "< 7").matching_specs.any? %>
29
- <%= javascript_packs_with_chunks_tag(javascript.path) %>
30
- <% else %>
31
- <%= javascript_pack_tag(javascript.path) %>
32
- <% end %>
24
+ <%= javascript_pack_tag(javascript.path) %>
33
25
  <% end %>
34
26
  <% end %>
35
27
  </head>
36
28
 
37
29
  <body class="font-sans pb-4">
38
30
  <div class="px-4">
39
- <header class="pt-4">
40
- <h1 class="text-lg font-bold mr-6 mb-1"><%= Super.configuration.title %></h1>
41
- <%
42
- route_namespace = Super.configuration.route_namespace.map(&:to_s).join("/")
43
- Super::Navigation::Automatic.new(route_namespace: route_namespace).each do |text, href| %>
44
- <%= link_to(text, href, class: "inline-block mr-6") %>
45
- <% end %>
46
- </header>
31
+ <%= render "site_header" %>
47
32
 
48
33
  <%= render "flash" %>
49
34
 
@@ -51,9 +36,7 @@
51
36
 
52
37
  <%= yield %>
53
38
 
54
- <div class="pt-8 text-sm text-gray-800">
55
- <%= t("super.layout.powered_by", env: Rails.env.capitalize, version: Super::VERSION) %>
56
- </div>
39
+ <%= render "site_footer" %>
57
40
  </div>
58
41
  </body>
59
42
  </html>