super 0.0.15 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/app/assets/javascripts/super/application.js +2 -2
  4. data/app/assets/stylesheets/super/application.css +11 -5
  5. data/app/controllers/super/application_controller.rb +32 -42
  6. data/app/controllers/super/substructure_controller.rb +265 -0
  7. data/app/helpers/super/form_builder_helper.rb +7 -0
  8. data/app/views/layouts/super/application.html.erb +2 -20
  9. data/app/views/super/application/_collection_header.html.erb +2 -2
  10. data/app/views/super/application/_display_actions.html.erb +1 -1
  11. data/app/views/super/application/_display_index.html.erb +1 -1
  12. data/app/views/super/application/_display_show.html.erb +1 -1
  13. data/app/views/super/application/_member_header.html.erb +2 -2
  14. data/app/views/super/application/_pagination.html.erb +1 -1
  15. data/app/views/super/application/_site_footer.html.erb +3 -0
  16. data/app/views/super/application/_site_header.html.erb +17 -0
  17. data/frontend/super-frontend/dist/application.css +11 -5
  18. data/frontend/super-frontend/dist/application.js +2 -2
  19. data/lib/generators/super/install/templates/base_controller.rb.tt +0 -8
  20. data/lib/generators/super/resource/templates/resources_controller.rb.tt +4 -4
  21. data/lib/super.rb +0 -1
  22. data/lib/super/action_inquirer.rb +7 -0
  23. data/lib/super/badge.rb +0 -1
  24. data/lib/super/cheat.rb +6 -6
  25. data/lib/super/link.rb +1 -1
  26. data/lib/super/pagination.rb +2 -2
  27. data/lib/super/reset.rb +5 -0
  28. data/lib/super/version.rb +1 -1
  29. data/lib/tasks/super/cheat.rake +1 -1
  30. metadata +5 -6
  31. data/lib/super/controls.rb +0 -22
  32. data/lib/super/controls/optional.rb +0 -122
  33. data/lib/super/controls/steps.rb +0 -133
  34. data/lib/super/controls/view.rb +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b7ba12321fd5d2a62b2aa9d81a832df2741a25adb997fa393c1aaab49d29946
4
- data.tar.gz: 2251cbc956d77d0e96b6904706c1ec3af8f3ae7edfcc8e5352268554a2296d27
3
+ metadata.gz: 14981d8658b6c65e32ead25ed20481ab4f675928239f72454ed0fc8d2dcd8795
4
+ data.tar.gz: 124dc8f187b220e30d171bf4a2dda7f778b52a70088df3ffce5ea15bdfa93196
5
5
  SHA512:
6
- metadata.gz: b515c1e2f3b9b382eb8244793e453af79303618612f06536b6167aed55bc713807857fd6a0bbed30e45af84b5338b5edd53d84246bf5cc79737e3674d24074aa
7
- data.tar.gz: 55623dc8472f95d6179073399478f452c3854f7c49791e1adf3e8371676bef3f443f3601ad3786fae36105c9988c160a14bf9c0f83d0ed7dc0dee2af3ecd030e
6
+ metadata.gz: '0780127899eadf34022440f92166258941a8794a72098af5694b4df28da8b3c7a9f7c91ef8f140c0bc5fdd7154d539d197061229402ad9500c4510928ff0be03'
7
+ data.tar.gz: 9025a0591386f938da8dc65a3d3dca846f76093c1d1c529b9df97a3cd0aa14b543dd2b32854273cbe23fd97358fce5dcef0712b96b5b29c09d0b7b0dda2b2b90
data/README.md CHANGED
@@ -14,8 +14,8 @@ application. It does this by having zero dependencies—this lets you update you
14
14
  app's dependencies without worrying about breaking your admin pages, and vice
15
15
  versa, update your admin pages without breaking your app.
16
16
 
17
- Note: There may be lots of breaking changes since Super is still fairly young.
18
- See the [stability doc](./STABILITY.md) for an idea of what might be changed.
17
+ Note: Super is under active development and will likely have a few more breaking
18
+ changes before 1.0.
19
19
 
20
20
 
21
21
  ## Features
@@ -237,7 +237,7 @@ var Super = (function (exports) {
237
237
 
238
238
  /*
239
239
  Unobtrusive JavaScript
240
- https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts
240
+ https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts
241
241
  Released under the MIT license
242
242
  */
243
243
  createCommonjsModule(function (module) {
@@ -489,9 +489,9 @@ var Super = (function (exports) {
489
489
 
490
490
  if (!options.crossDomain) {
491
491
  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
492
+ CSRFProtection(xhr);
492
493
  }
493
494
 
494
- CSRFProtection(xhr);
495
495
  xhr.withCredentials = !!options.withCredentials;
496
496
 
497
497
  xhr.onreadystatechange = function () {
@@ -1,6 +1,6 @@
1
- /*! tailwindcss v2.1.1 | MIT License | https://tailwindcss.com */
1
+ /*! tailwindcss v2.1.2 | MIT License | https://tailwindcss.com */
2
2
 
3
- /*! modern-normalize v1.0.0 | MIT License | https://github.com/sindresorhus/modern-normalize */
3
+ /*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */
4
4
 
5
5
  /*
6
6
  Document
@@ -12,8 +12,8 @@ Use a better box model (opinionated).
12
12
  */
13
13
 
14
14
  *,
15
- *::before,
16
- *::after {
15
+ ::before,
16
+ ::after {
17
17
  box-sizing: border-box;
18
18
  }
19
19
 
@@ -21,7 +21,7 @@ Use a better box model (opinionated).
21
21
  Use a more readable tab size (opinionated).
22
22
  */
23
23
 
24
- :root {
24
+ html {
25
25
  -moz-tab-size: 4;
26
26
  -o-tab-size: 4;
27
27
  tab-size: 4;
@@ -1479,6 +1479,12 @@ span.flatpickr-day.selected {
1479
1479
  outline-offset: 2px;
1480
1480
  }
1481
1481
 
1482
+ .super-input:disabled {
1483
+ opacity: 0.5;
1484
+ --tw-bg-opacity: 1;
1485
+ background-color: rgba(247, 250, 252, var(--tw-bg-opacity));
1486
+ }
1487
+
1482
1488
  .super-input-select {
1483
1489
  padding-right: 2rem;
1484
1490
  width: 100%;
@@ -2,78 +2,76 @@
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
10
- helper_method :navigation
8
+ helper_method :current_action
11
9
 
12
10
  # Displays a list of records to the user
13
11
  def index
14
- @records = controls.load_records(action: action_inquirer, params: params)
15
- @display = controls.display_schema(action: action_inquirer).apply(action: action_inquirer)
16
- @view = controls.index_view
17
- @query_form = controls.initialize_query_form(params: params, current_path: request.path)
18
- controls.initialize_filter_form(query_form: @query_form)
19
- controls.initialize_sort_form(query_form: @query_form)
20
- @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
21
19
  end
22
20
 
23
21
  # Displays a specific record to the user
24
22
  def show
25
- @record = controls.load_record(action: action_inquirer, params: params)
26
- @display = controls.display_schema(action: action_inquirer).apply(action: action_inquirer)
27
- @view = controls.show_view
23
+ @record = load_record
24
+ @display = display_schema.apply(action: current_action)
25
+ @view = show_view
28
26
  end
29
27
 
30
28
  # Displays a form to allow the user to create a new record
31
29
  def new
32
- @record = controls.build_record(action: action_inquirer)
33
- @form = controls.form_schema(action: action_inquirer)
34
- @view = controls.new_view
30
+ @record = build_record
31
+ @form = form_schema
32
+ @view = new_view
35
33
  end
36
34
 
37
35
  # Creates a record, or shows the validation errors
38
36
  def create
39
- @record = controls.build_record_with_params(action: action_inquirer, params: params)
37
+ @record = build_record_with_params
40
38
 
41
- if controls.save_record(action: action_inquirer, record: @record, params: params)
39
+ if save_record
42
40
  redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
43
41
  else
44
- @action_inquirer = ActionInquirer.new!
45
- @form = controls.form_schema(action: action_inquirer)
46
- @view = controls.new_view
42
+ @current_action = ActionInquirer.new!
43
+ @form = form_schema
44
+ @view = new_view
47
45
  render :new, status: :bad_request
48
46
  end
49
47
  end
50
48
 
51
49
  # Displays a form to allow the user to update an existing record
52
50
  def edit
53
- @record = controls.load_record(action: action_inquirer, params: params)
54
- @form = controls.form_schema(action: action_inquirer)
55
- @view = controls.edit_view
51
+ @record = load_record
52
+ @form = form_schema
53
+ @view = edit_view
56
54
  end
57
55
 
58
56
  # Updates a record, or shows validation errors
59
57
  def update
60
- @record = controls.load_record(action: action_inquirer, params: params)
58
+ @record = load_record
61
59
 
62
- if controls.update_record(action: action_inquirer, record: @record, params: params)
60
+ if update_record
63
61
  redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
64
62
  else
65
- @action_inquirer = ActionInquirer.edit!
66
- @form = controls.form_schema(action: action_inquirer)
67
- @view = controls.edit_view
63
+ @current_action = ActionInquirer.edit!
64
+ @form = form_schema
65
+ @view = edit_view
68
66
  render :edit, status: :bad_request
69
67
  end
70
68
  end
71
69
 
72
70
  # Deletes a record, or shows validation errors
73
71
  def destroy
74
- @record = controls.load_record(action: action_inquirer, params: params)
72
+ @record = load_record
75
73
 
76
- if controls.destroy_record(action: action_inquirer, record: @record, params: params)
74
+ if destroy_record
77
75
  redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
78
76
  else
79
77
  flash.alert = "Couldn't delete record"
@@ -86,20 +84,12 @@ module Super
86
84
 
87
85
  private
88
86
 
89
- def controls
90
- @controls ||= new_controls
91
- end
92
-
93
- def action_inquirer
94
- @action_inquirer ||=
87
+ def current_action
88
+ @current_action ||=
95
89
  ActionInquirer.new(
96
90
  ActionInquirer.default_for_resources,
97
91
  params[:action]
98
92
  )
99
93
  end
100
-
101
- def navigation
102
- Navigation.new(&:all)
103
- end
104
94
  end
105
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
@@ -28,23 +28,7 @@
28
28
 
29
29
  <body class="font-sans pb-4">
30
30
  <div class="px-4">
31
- <header class="pt-4">
32
- <h1 class="text-lg font-bold mr-6 mb-1"><%= Super.configuration.title %></h1>
33
- <% navigation.definition.each do |link_or_menu| %>
34
- <% if link_or_menu.is_a?(Super::Link) %>
35
- <%= link_or_menu.to_s(default_options: { class: "inline-block mr-6" }) %>
36
- <% else %>
37
- <details class="details-reset select-none inline-block mr-6" data-controller="click-outside-to-close" data-action="click@window->click-outside-to-close#close">
38
- <summary class="text-blue-700"><%= link_or_menu.title %></summary>
39
- <ul class="absolute bg-white shadow-md px-4 py-3">
40
- <% link_or_menu.links.each do |link| %>
41
- <li><%= link.to_s(default_options: { class: "" }) %></li>
42
- <% end %>
43
- </ul>
44
- </details>
45
- <% end %>
46
- <% end %>
47
- </header>
31
+ <%= render "site_header" %>
48
32
 
49
33
  <%= render "flash" %>
50
34
 
@@ -52,9 +36,7 @@
52
36
 
53
37
  <%= yield %>
54
38
 
55
- <div class="pt-8 text-sm text-gray-800">
56
- <%= t("super.layout.powered_by", env: Rails.env.capitalize, version: Super::VERSION) %>
57
- </div>
39
+ <%= render "site_footer" %>
58
40
  </div>
59
41
  </body>
60
42
  </html>
@@ -1,9 +1,9 @@
1
1
  <header class="flex justify-between content-end">
2
2
  <h1 class="text-xl">
3
- <%= controls.title %>
3
+ <%= title %>
4
4
  </h1>
5
5
  <div>
6
- <% controls.collection_actions(action: action_inquirer).each do |link| %>
6
+ <% collection_actions.each do |link| %>
7
7
  <%= link.to_s(
8
8
  default_options: {
9
9
  class: "super-button super-button--border-blue super-button-sm inline-block ml-2"
@@ -1,5 +1,5 @@
1
1
  <div>
2
- <% controls.member_actions(action: action_inquirer).each do |link| %>
2
+ <% member_actions.each do |link| %>
3
3
  <span class="pr-2 last:pr-0"><%= link.to_s(record: record, params: params) %></span>
4
4
  <% end %>
5
5
  </div>
@@ -4,7 +4,7 @@
4
4
  <tr class="">
5
5
  <% display_index.each_attribute_name do |attribute_name| %>
6
6
  <th class="p-2 first:pl-6 border-b border-b-2 border-gray-400 text-gray-600 text-left text-sm font-normal bg-white top-0 z-10">
7
- <%= controls.model.human_attribute_name(attribute_name) %>
7
+ <%= model.human_attribute_name(attribute_name) %>
8
8
  </th>
9
9
  <% end %>
10
10
  </tr>
@@ -1,7 +1,7 @@
1
1
  <table class="max-w-full mt-4">
2
2
  <% display_show.each_attribute_name do |attribute_name| %>
3
3
  <tr>
4
- <th class="py-1 align-baseline text-right px-4"><%= controls.model.human_attribute_name(attribute_name) %></th>
4
+ <th class="py-1 align-baseline text-right px-4"><%= model.human_attribute_name(attribute_name) %></th>
5
5
  <td class="py-1 align-baseline"><%= display_show.render_attribute(template: self, record: @record, column: attribute_name) %></td>
6
6
  </tr>
7
7
  <% end %>
@@ -1,9 +1,9 @@
1
1
  <header class="flex justify-between content-end">
2
2
  <h1 class="text-xl">
3
- <%= controls.title %>
3
+ <%= title %>
4
4
  </h1>
5
5
  <div>
6
- <% controls.member_actions(action: action_inquirer).each do |link| %>
6
+ <% member_actions.each do |link| %>
7
7
  <%= link.to_s(
8
8
  default_options: {
9
9
  class: "super-button super-button--border-blue super-button-sm inline-block ml-2"
@@ -5,7 +5,7 @@
5
5
  <%= link_to(
6
6
  display,
7
7
  polymorphic_path(
8
- Super::Link.polymorphic_parts(controls.model),
8
+ Super::Link.polymorphic_parts(model),
9
9
  page_query_params
10
10
  ),
11
11
  class: "inline-block ml-2 text-lg #{is_current_page ? " text-gray-900" : ""}"
@@ -0,0 +1,3 @@
1
+ <div class="pt-8 text-sm text-gray-800">
2
+ <%= t("super.layout.powered_by", env: Rails.env.capitalize, version: Super::VERSION) %>
3
+ </div>
@@ -0,0 +1,17 @@
1
+ <header class="pt-4">
2
+ <h1 class="text-lg font-bold mr-6 mb-1"><%= site_title %></h1>
3
+ <% site_navigation.definition.each do |link_or_menu| %>
4
+ <% if link_or_menu.is_a?(Super::Link) %>
5
+ <%= link_or_menu.to_s(default_options: { class: "inline-block mr-6" }) %>
6
+ <% else %>
7
+ <details class="details-reset select-none inline-block mr-6" data-controller="click-outside-to-close" data-action="click@window->click-outside-to-close#close">
8
+ <summary class="text-blue-700"><%= link_or_menu.title %></summary>
9
+ <ul class="absolute bg-white shadow-md px-4 py-3">
10
+ <% link_or_menu.links.each do |link| %>
11
+ <li><%= link.to_s(default_options: { class: "" }) %></li>
12
+ <% end %>
13
+ </ul>
14
+ </details>
15
+ <% end %>
16
+ <% end %>
17
+ </header>
@@ -1,6 +1,6 @@
1
- /*! tailwindcss v2.1.1 | MIT License | https://tailwindcss.com */
1
+ /*! tailwindcss v2.1.2 | MIT License | https://tailwindcss.com */
2
2
 
3
- /*! modern-normalize v1.0.0 | MIT License | https://github.com/sindresorhus/modern-normalize */
3
+ /*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */
4
4
 
5
5
  /*
6
6
  Document
@@ -12,8 +12,8 @@ Use a better box model (opinionated).
12
12
  */
13
13
 
14
14
  *,
15
- *::before,
16
- *::after {
15
+ ::before,
16
+ ::after {
17
17
  box-sizing: border-box;
18
18
  }
19
19
 
@@ -21,7 +21,7 @@ Use a better box model (opinionated).
21
21
  Use a more readable tab size (opinionated).
22
22
  */
23
23
 
24
- :root {
24
+ html {
25
25
  -moz-tab-size: 4;
26
26
  -o-tab-size: 4;
27
27
  tab-size: 4;
@@ -1479,6 +1479,12 @@ span.flatpickr-day.selected {
1479
1479
  outline-offset: 2px;
1480
1480
  }
1481
1481
 
1482
+ .super-input:disabled {
1483
+ opacity: 0.5;
1484
+ --tw-bg-opacity: 1;
1485
+ background-color: rgba(247, 250, 252, var(--tw-bg-opacity));
1486
+ }
1487
+
1482
1488
  .super-input-select {
1483
1489
  padding-right: 2rem;
1484
1490
  width: 100%;
@@ -237,7 +237,7 @@ var Super = (function (exports) {
237
237
 
238
238
  /*
239
239
  Unobtrusive JavaScript
240
- https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts
240
+ https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts
241
241
  Released under the MIT license
242
242
  */
243
243
  createCommonjsModule(function (module) {
@@ -489,9 +489,9 @@ var Super = (function (exports) {
489
489
 
490
490
  if (!options.crossDomain) {
491
491
  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
492
+ CSRFProtection(xhr);
492
493
  }
493
494
 
494
- CSRFProtection(xhr);
495
495
  xhr.withCredentials = !!options.withCredentials;
496
496
 
497
497
  xhr.onreadystatechange = function () {
@@ -1,10 +1,2 @@
1
1
  class <%= parent_controller_name.classify %>Controller < Super::ApplicationController
2
- class <%= parent_controller_name.classify.demodulize %>Controls < Super::Controls
3
- end
4
-
5
- private
6
-
7
- def new_controls
8
- self.class::Controls.new
9
- end
10
2
  end
@@ -1,9 +1,9 @@
1
1
  <% module_namespacing do -%>
2
2
  class <%= controller_class_name %>Controller < <%= parent_controller_name.classify %>Controller
3
- class Controls < <%= parent_controller_name.classify.demodulize %>Controls
4
- def model
5
- <%= class_name %>
6
- end
3
+ private
4
+
5
+ def model
6
+ <%= class_name %>
7
7
  end
8
8
  end
9
9
  <% end -%>
data/lib/super.rb CHANGED
@@ -14,7 +14,6 @@ require "super/badge"
14
14
  require "super/client_error"
15
15
  require "super/compatibility"
16
16
  require "super/configuration"
17
- require "super/controls"
18
17
  require "super/display"
19
18
  require "super/display/guesser"
20
19
  require "super/display/schema_types"
@@ -25,12 +25,19 @@ module Super
25
25
  }
26
26
  end
27
27
 
28
+ # @return [ActionInquirer]
28
29
  def self.index!; new(default_for_resources, "index"); end
30
+ # @return [ActionInquirer]
29
31
  def self.show!; new(default_for_resources, "show"); end
32
+ # @return [ActionInquirer]
30
33
  def self.new!; new(default_for_resources, "new"); end
34
+ # @return [ActionInquirer]
31
35
  def self.edit!; new(default_for_resources, "edit"); end
36
+ # @return [ActionInquirer]
32
37
  def self.create!; new(default_for_resources, "create"); end
38
+ # @return [ActionInquirer]
33
39
  def self.update!; new(default_for_resources, "update"); end
40
+ # @return [ActionInquirer]
34
41
  def self.destroy!; new(default_for_resources, "destroy"); end
35
42
 
36
43
  def initialize(categories_and_their_actions, action)
data/lib/super/badge.rb CHANGED
@@ -6,7 +6,6 @@ module Super
6
6
  light: "bg-gray-100 text-black",
7
7
  dark: "bg-gray-900 text-white",
8
8
  red: "bg-red-700 text-white",
9
- orange: "bg-orange-400 text-black",
10
9
  yellow: "bg-yellow-400 text-black",
11
10
  green: "bg-green-700 text-white",
12
11
  blue: "bg-blue-700 text-white",
data/lib/super/cheat.rb CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  module Super
4
4
  class Cheat
5
- def controls
6
- paths = %w[controls.rb controls/optional.rb controls/steps.rb controls/view.rb]
5
+ def controller
6
+ paths = %w[../../app/controllers/super/substructure_controller.rb]
7
7
  methods =
8
8
  paths
9
- .map { |f| File.read(File.join(__dir__, f)) }
10
- .flat_map { |content| content.scan(/^\s+def .*$/) }
11
- .map { |method| method.strip.sub(/^def /, "#") }
9
+ .map { |f| File.read(File.expand_path(f, __dir__)) }
10
+ .flat_map { |content| content.scan(/^\s+(?:helper_method )?def .*$/) }
11
+ .map { |method| method.strip.sub(/^(?:helper_method )?def /, "#") }
12
12
 
13
- puts "== Super::Controls"
13
+ puts "== Super::ApplicationController"
14
14
  puts methods.join("\n")
15
15
  end
16
16
  end
data/lib/super/link.rb CHANGED
@@ -82,7 +82,7 @@ module Super
82
82
 
83
83
  def self.polymorphic_parts(*parts_tail)
84
84
  parts_head = Super.configuration.path.strip.gsub(%r{\A/+}, "").gsub(%r{/+\z}, "").strip.split("/")
85
- parts_head + parts_tail
85
+ parts_head.map { |part| part.is_a?(String) ? part.to_sym : part } + parts_tail
86
86
  end
87
87
 
88
88
  def initialize(text, href, **options)
@@ -76,8 +76,8 @@ module Super
76
76
  module ControllerMethods
77
77
  def index
78
78
  super
79
- @pagination = controls.initialize_pagination(action: action_inquirer, records: @records, query_params: request.GET)
80
- @records = controls.paginate_records(action: action_inquirer, records: @records, pagination: @pagination)
79
+ @pagination = initialize_pagination
80
+ @records = paginate_records
81
81
  @view.mains.first.parts.push(:@pagination)
82
82
  end
83
83
  end
data/lib/super/reset.rb CHANGED
@@ -12,6 +12,11 @@ module Super
12
12
  undef_method :edit
13
13
  undef_method :update
14
14
  undef_method :destroy
15
+
16
+ Super::SubstructureController.private_instance_methods(false).each do |imethod|
17
+ next if imethod == :navigation
18
+ undef_method imethod
19
+ end
15
20
  end
16
21
  end
17
22
  end
data/lib/super/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Super
4
- VERSION = "0.0.15"
4
+ VERSION = "0.0.16"
5
5
  end
@@ -4,6 +4,6 @@ namespace :super do
4
4
  task :cheat do
5
5
  require "super/cheat"
6
6
  cheat = Super::Cheat.new
7
- cheat.controls
7
+ cheat.controller
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: super
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Ahn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-01 00:00:00.000000000 Z
11
+ date: 2021-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -226,6 +226,7 @@ files:
226
226
  - app/assets/javascripts/super/application.js
227
227
  - app/assets/stylesheets/super/application.css
228
228
  - app/controllers/super/application_controller.rb
229
+ - app/controllers/super/substructure_controller.rb
229
230
  - app/helpers/super/form_builder_helper.rb
230
231
  - app/views/layouts/super/application.html.erb
231
232
  - app/views/super/application/_collection_header.html.erb
@@ -250,6 +251,8 @@ files:
250
251
  - app/views/super/application/_pagination.html.erb
251
252
  - app/views/super/application/_panel.html.erb
252
253
  - app/views/super/application/_query.html.erb
254
+ - app/views/super/application/_site_footer.html.erb
255
+ - app/views/super/application/_site_header.html.erb
253
256
  - app/views/super/application/_sort.html.erb
254
257
  - app/views/super/application/_sort_expression.html.erb
255
258
  - app/views/super/application/edit.html.erb
@@ -285,10 +288,6 @@ files:
285
288
  - lib/super/client_error.rb
286
289
  - lib/super/compatibility.rb
287
290
  - lib/super/configuration.rb
288
- - lib/super/controls.rb
289
- - lib/super/controls/optional.rb
290
- - lib/super/controls/steps.rb
291
- - lib/super/controls/view.rb
292
291
  - lib/super/display.rb
293
292
  - lib/super/display/guesser.rb
294
293
  - lib/super/display/schema_types.rb
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "super/controls/optional"
4
- require "super/controls/steps"
5
- require "super/controls/view"
6
-
7
- module Super
8
- # The base Controls class. Most parts of Super can be configured by
9
- # customizing its methods.
10
- class Controls
11
- include Optional
12
- include Steps
13
- include View
14
-
15
- # Specifies the model. This is a required method
16
- #
17
- # @return [ActiveRecord::Base]
18
- def model
19
- raise NotImplementedError
20
- end
21
- end
22
- end
@@ -1,122 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Super
4
- class Controls
5
- # Methods for `Controls` that have a sane default implementation
6
- module Optional
7
- # This is an optional method
8
- #
9
- # @return [String]
10
- def title
11
- model.name.pluralize
12
- end
13
-
14
- # Configures what database records are visible on load. This is an optional
15
- # method, it defaults to "`all`" methods
16
- #
17
- # @param action [ActionInquirer]
18
- # @return [ActiveRecord::Relation]
19
- def scope(action:)
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
31
- end
32
- end
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
-
56
- # Configures the actions linked to on the index page. This is an optional
57
- # method
58
- #
59
- # @param action [ActionInquirer]
60
- # @return [Array<Link>]
61
- def collection_actions(action:)
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
- # @param action [ActionInquirer]
69
- # @return [Array<Link>]
70
- def member_actions(action:)
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
87
- end
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
111
-
112
- # Specifies how many records to show per page
113
- #
114
- # @param action [ActionInquirer]
115
- # @param query_params [Hash]
116
- # @return [ActiveRecord::Relation]
117
- def records_per_page(action:, query_params:)
118
- Super.configuration.index_records_per_page
119
- end
120
- end
121
- end
122
- end
@@ -1,133 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Super
4
- class Controls
5
- # Methods that are called by controller actions. All of these methods have
6
- # a default implementation, but feel free to override as needed.
7
- module Steps
8
- # Tells the controller how to load records in the index action using
9
- # `#scope`
10
- #
11
- # @param action [ActionInquirer]
12
- # @param params [ActionController::Parameters]
13
- # @return [ActiveRecord::Relation]
14
- def load_records(action:, params:)
15
- scope(action: action)
16
- end
17
-
18
- # Loads a record using `#scope`
19
- #
20
- # @param action [ActionInquirer]
21
- # @param params [ActionController::Parameters]
22
- # @return [ActiveRecord::Base]
23
- def load_record(action:, params:)
24
- scope(action: action).find(params[:id])
25
- end
26
-
27
- # Builds a record using `#scope`
28
- #
29
- # @param action [ActionInquirer]
30
- # @return [ActiveRecord::Base]
31
- def build_record(action:)
32
- scope(action: action).build
33
- end
34
-
35
- # Builds and populates a record using `#scope`
36
- #
37
- # @param action [ActionInquirer]
38
- # @param params [ActionController::Parameters]
39
- # @return [ActiveRecord::Base]
40
- def build_record_with_params(action:, params:)
41
- scope(action: action).build(permitted_params(params, action: action))
42
- end
43
-
44
- # Saves a record
45
- #
46
- # @param action [ActionInquirer]
47
- # @param params [ActionController::Parameters]
48
- # @return [true, false]
49
- def save_record(action:, record:, params:)
50
- record.save
51
- end
52
-
53
- # Saves a record
54
- #
55
- # @param action [ActionInquirer]
56
- # @param params [ActionController::Parameters]
57
- # @return [true, false]
58
- def update_record(action:, record:, params:)
59
- record.update(permitted_params(params, action: action))
60
- end
61
-
62
- # Destroys a record
63
- #
64
- # @param action [ActionInquirer]
65
- # @param params [ActionController::Parameters]
66
- # @return [ActiveRecord::Base, false]
67
- def destroy_record(action:, record:, params:)
68
- record.destroy
69
- end
70
-
71
- def initialize_query_form(params:, current_path:)
72
- Super::Query::FormObject.new(
73
- model: model,
74
- params: params,
75
- namespace: :q,
76
- current_path: current_path,
77
- )
78
- end
79
-
80
- def apply_queries(query_form:, records:)
81
- query_form.apply_changes(records)
82
- end
83
-
84
- def initialize_filter_form(query_form:)
85
- if filters_enabled?
86
- query_form.add(
87
- Super::Filter::FormObject,
88
- namespace: :f,
89
- schema: filter_schema
90
- )
91
- end
92
- end
93
-
94
- def initialize_sort_form(query_form:)
95
- if sort_enabled?
96
- query_form.add(
97
- Super::Sort::FormObject,
98
- namespace: :s,
99
- default: default_sort,
100
- sortable_columns: sortable_columns
101
- )
102
- end
103
- end
104
-
105
- # Sets up pagination
106
- #
107
- # @param action [ActionInquirer]
108
- # @param records [ActiveRecord::Relation]
109
- # @param query_params [Hash]
110
- # @return [Pagination]
111
- def initialize_pagination(action:, records:, query_params:)
112
- Pagination.new(
113
- total_count: records.size,
114
- limit: records_per_page(action: action, query_params: query_params),
115
- query_params: query_params,
116
- page_query_param: :page
117
- )
118
- end
119
-
120
- # Paginates
121
- #
122
- # @param action [ActionInquirer]
123
- # @param records [ActiveRecord::Relation]
124
- # @param pagination [Pagination]
125
- # @return [ActiveRecord::Relation]
126
- def paginate_records(action:, records:, pagination:)
127
- records
128
- .limit(pagination.limit)
129
- .offset(pagination.offset)
130
- end
131
- end
132
- end
133
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Super
4
- class Controls
5
- # Methods for `Controls` that have a sane default implementation
6
- module View
7
- def index_view
8
- Super::Layout.new(
9
- mains: [
10
- Super::Panel.new(
11
- Super::Partial.new("collection_header"),
12
- :@display
13
- ),
14
- ],
15
- asides: [
16
- :@query_form,
17
- ]
18
- )
19
- end
20
-
21
- def show_view
22
- Super::Layout.new(
23
- mains: [
24
- Super::Panel.new(
25
- Super::Partial.new("member_header"),
26
- :@display
27
- ),
28
- ]
29
- )
30
- end
31
-
32
- def new_view
33
- Super::Layout.new(
34
- mains: [
35
- Super::Panel.new(
36
- Super::Partial.new("collection_header"),
37
- :@form
38
- ),
39
- ]
40
- )
41
- end
42
-
43
- def edit_view
44
- Super::Layout.new(
45
- mains: [
46
- Super::Panel.new(
47
- Super::Partial.new("member_header"),
48
- :@form
49
- ),
50
- ]
51
- )
52
- end
53
- end
54
- end
55
- end