super 0.0.15 → 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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/app/assets/javascripts/super/application.js +2 -2
- data/app/assets/stylesheets/super/application.css +11 -5
- data/app/controllers/super/application_controller.rb +32 -42
- data/app/controllers/super/substructure_controller.rb +265 -0
- data/app/helpers/super/form_builder_helper.rb +7 -0
- data/app/views/layouts/super/application.html.erb +2 -20
- data/app/views/super/application/_collection_header.html.erb +2 -2
- data/app/views/super/application/_display_actions.html.erb +1 -1
- data/app/views/super/application/_display_index.html.erb +1 -1
- data/app/views/super/application/_display_show.html.erb +1 -1
- data/app/views/super/application/_member_header.html.erb +2 -2
- data/app/views/super/application/_pagination.html.erb +1 -1
- data/app/views/super/application/_site_footer.html.erb +3 -0
- data/app/views/super/application/_site_header.html.erb +17 -0
- data/frontend/super-frontend/dist/application.css +11 -5
- data/frontend/super-frontend/dist/application.js +2 -2
- data/lib/generators/super/install/templates/base_controller.rb.tt +0 -8
- data/lib/generators/super/resource/templates/resources_controller.rb.tt +4 -4
- data/lib/super.rb +0 -1
- data/lib/super/action_inquirer.rb +7 -0
- data/lib/super/badge.rb +0 -1
- data/lib/super/cheat.rb +6 -6
- data/lib/super/link.rb +1 -1
- data/lib/super/pagination.rb +2 -2
- data/lib/super/reset.rb +5 -0
- data/lib/super/version.rb +1 -1
- data/lib/tasks/super/cheat.rake +1 -1
- metadata +5 -6
- data/lib/super/controls.rb +0 -22
- data/lib/super/controls/optional.rb +0 -122
- data/lib/super/controls/steps.rb +0 -133
- data/lib/super/controls/view.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14981d8658b6c65e32ead25ed20481ab4f675928239f72454ed0fc8d2dcd8795
|
4
|
+
data.tar.gz: 124dc8f187b220e30d171bf4a2dda7f778b52a70088df3ffce5ea15bdfa93196
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
18
|
-
|
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/
|
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
|
+
/*! tailwindcss v2.1.2 | MIT License | https://tailwindcss.com */
|
2
2
|
|
3
|
-
/*! modern-normalize v1.
|
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
|
-
|
16
|
-
|
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
|
-
|
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 <
|
5
|
+
class ApplicationController < SubstructureController
|
6
6
|
include ClientError::Handling
|
7
7
|
|
8
|
-
helper_method :
|
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 =
|
15
|
-
@display =
|
16
|
-
@view =
|
17
|
-
@query_form =
|
18
|
-
|
19
|
-
|
20
|
-
@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 =
|
26
|
-
@display =
|
27
|
-
@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 =
|
33
|
-
@form =
|
34
|
-
@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 =
|
37
|
+
@record = build_record_with_params
|
40
38
|
|
41
|
-
if
|
39
|
+
if save_record
|
42
40
|
redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
|
43
41
|
else
|
44
|
-
@
|
45
|
-
@form =
|
46
|
-
@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 =
|
54
|
-
@form =
|
55
|
-
@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 =
|
58
|
+
@record = load_record
|
61
59
|
|
62
|
-
if
|
60
|
+
if update_record
|
63
61
|
redirect_to polymorphic_path(Super::Link.polymorphic_parts(@record))
|
64
62
|
else
|
65
|
-
@
|
66
|
-
@form =
|
67
|
-
@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 =
|
72
|
+
@record = load_record
|
75
73
|
|
76
|
-
if
|
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
|
90
|
-
@
|
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
|
-
|
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
|
-
|
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
|
-
<%=
|
3
|
+
<%= title %>
|
4
4
|
</h1>
|
5
5
|
<div>
|
6
|
-
<%
|
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"
|
@@ -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
|
-
<%=
|
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"><%=
|
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
|
-
<%=
|
3
|
+
<%= title %>
|
4
4
|
</h1>
|
5
5
|
<div>
|
6
|
-
<%
|
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"
|
@@ -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
|
+
/*! tailwindcss v2.1.2 | MIT License | https://tailwindcss.com */
|
2
2
|
|
3
|
-
/*! modern-normalize v1.
|
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
|
-
|
16
|
-
|
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
|
-
|
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/
|
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,9 +1,9 @@
|
|
1
1
|
<% module_namespacing do -%>
|
2
2
|
class <%= controller_class_name %>Controller < <%= parent_controller_name.classify %>Controller
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
private
|
4
|
+
|
5
|
+
def model
|
6
|
+
<%= class_name %>
|
7
7
|
end
|
8
8
|
end
|
9
9
|
<% end -%>
|
data/lib/super.rb
CHANGED
@@ -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
data/lib/super/cheat.rb
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
module Super
|
4
4
|
class Cheat
|
5
|
-
def
|
6
|
-
paths = %w[
|
5
|
+
def controller
|
6
|
+
paths = %w[../../app/controllers/super/substructure_controller.rb]
|
7
7
|
methods =
|
8
8
|
paths
|
9
|
-
.map { |f| File.read(File.
|
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::
|
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)
|
data/lib/super/pagination.rb
CHANGED
@@ -76,8 +76,8 @@ module Super
|
|
76
76
|
module ControllerMethods
|
77
77
|
def index
|
78
78
|
super
|
79
|
-
@pagination =
|
80
|
-
@records =
|
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
data/lib/tasks/super/cheat.rake
CHANGED
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.
|
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-
|
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
|
data/lib/super/controls.rb
DELETED
@@ -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
|
data/lib/super/controls/steps.rb
DELETED
@@ -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
|
data/lib/super/controls/view.rb
DELETED
@@ -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
|