admin_suite 0.2.8 → 0.2.9
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/CHANGELOG.md +6 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +10 -24
- data/app/controllers/admin_suite/resources_controller.rb +14 -4
- data/app/views/admin_suite/resources/index.html.erb +3 -1
- data/app/views/admin_suite/resources/show.html.erb +2 -2
- data/lib/admin/base/filter_builder.rb +2 -1
- data/lib/admin/base/resource.rb +14 -2
- data/lib/admin_suite/version.rb +1 -1
- data/test/controllers/resources_controller_test.rb +80 -0
- data/test/integration/read_only_resource_test.rb +143 -0
- data/test/lib/resource_observability_extensions_test.rb +53 -0
- metadata +5 -14
- data/docs/README.md +0 -26
- data/docs/actions.md +0 -98
- data/docs/configuration.md +0 -284
- data/docs/development.md +0 -64
- data/docs/docs_viewer.md +0 -79
- data/docs/fields.md +0 -188
- data/docs/installation.md +0 -80
- data/docs/portals.md +0 -140
- data/docs/releasing.md +0 -67
- data/docs/resources.md +0 -237
- data/docs/theming.md +0 -63
- data/docs/troubleshooting.md +0 -50
data/docs/actions.md
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# Actions
|
|
2
|
-
|
|
3
|
-
AdminSuite supports three action “shapes” in the resource DSL:
|
|
4
|
-
|
|
5
|
-
- `action` (member action on a single record)
|
|
6
|
-
- `bulk_action` (runs across selected records)
|
|
7
|
-
- `collection_action` (runs on a scope / collection)
|
|
8
|
-
|
|
9
|
-
## Defining actions
|
|
10
|
-
|
|
11
|
-
```ruby
|
|
12
|
-
actions do
|
|
13
|
-
action :reindex, label: "Reindex", method: :post, confirm: "Reindex this record?"
|
|
14
|
-
bulk_action :archive, label: "Archive", confirm: "Archive selected records?"
|
|
15
|
-
end
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Supported action options:
|
|
19
|
-
|
|
20
|
-
- `method:` HTTP method (default `:post`)
|
|
21
|
-
- `label:` button label (default is humanized action name)
|
|
22
|
-
- `icon:` lucide icon name (optional)
|
|
23
|
-
- `color:` (optional)
|
|
24
|
-
- `confirm:` string confirmation (optional)
|
|
25
|
-
- `type:` reserved (default `:button`)
|
|
26
|
-
- `if:` Proc condition (member actions only)
|
|
27
|
-
- `unless:` Proc condition (member actions only)
|
|
28
|
-
|
|
29
|
-
## How actions execute
|
|
30
|
-
|
|
31
|
-
When you trigger an action, AdminSuite resolves behavior in this order:
|
|
32
|
-
|
|
33
|
-
1. **Model method**: if the target responds to `action_name`, it calls that method.
|
|
34
|
-
2. **Bang model method**: else if it responds to `action_name!`, it calls that.
|
|
35
|
-
3. **Action handler class**: else it tries to find a handler class.
|
|
36
|
-
|
|
37
|
-
### Handler class naming convention
|
|
38
|
-
|
|
39
|
-
By default, AdminSuite looks for:
|
|
40
|
-
|
|
41
|
-
```ruby
|
|
42
|
-
Admin::Actions::<ResourceName><ActionName>Action
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Example for `UserResource` + `:reset_password`:
|
|
46
|
-
|
|
47
|
-
```ruby
|
|
48
|
-
Admin::Actions::UserResetPasswordAction
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Handlers should inherit from `Admin::Base::ActionHandler`:
|
|
52
|
-
|
|
53
|
-
```ruby
|
|
54
|
-
# app/admin/actions/user_reset_password_action.rb
|
|
55
|
-
module Admin
|
|
56
|
-
module Actions
|
|
57
|
-
class UserResetPasswordAction < Admin::Base::ActionHandler
|
|
58
|
-
def call
|
|
59
|
-
# record is available as `record`, actor as `actor`, request params as `params`
|
|
60
|
-
record.send_reset_password_instructions!
|
|
61
|
-
success "Reset email sent."
|
|
62
|
-
rescue StandardError => e
|
|
63
|
-
failure "Failed to send reset: #{e.message}"
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Overriding handler resolution (`config.resolve_action_handler`)
|
|
71
|
-
|
|
72
|
-
If your app doesn’t want to follow the default naming convention, you can provide a resolver:
|
|
73
|
-
|
|
74
|
-
```ruby
|
|
75
|
-
AdminSuite.configure do |config|
|
|
76
|
-
config.resolve_action_handler = ->(resource_class, action_name) do
|
|
77
|
-
# return a Class or nil
|
|
78
|
-
if resource_class.name == "Admin::Resources::UserResource" && action_name.to_sym == :reset_password
|
|
79
|
-
Admin::Actions::UserResetPasswordAction
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## Auditing hook (`config.on_action_executed`)
|
|
86
|
-
|
|
87
|
-
You can record or log all actions after they run:
|
|
88
|
-
|
|
89
|
-
```ruby
|
|
90
|
-
AdminSuite.configure do |config|
|
|
91
|
-
config.on_action_executed = ->(actor:, action_name:, resource_class:, subject:, params:, result:) do
|
|
92
|
-
Rails.logger.info(
|
|
93
|
-
"[admin_suite] actor=#{actor&.id} action=#{resource_class.name}##{action_name} success=#{result.success?}"
|
|
94
|
-
)
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
```
|
|
98
|
-
|
data/docs/configuration.md
DELETED
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
# Configuration
|
|
2
|
-
|
|
3
|
-
AdminSuite is configured via an initializer:
|
|
4
|
-
|
|
5
|
-
- `config/initializers/admin_suite.rb` (generated by `bin/rails g admin_suite:install`)
|
|
6
|
-
|
|
7
|
-
All configuration lives on `AdminSuite.config` (an `AdminSuite::Configuration` instance).
|
|
8
|
-
|
|
9
|
-
## Minimal secure configuration
|
|
10
|
-
|
|
11
|
-
```ruby
|
|
12
|
-
# config/initializers/admin_suite.rb
|
|
13
|
-
AdminSuite.configure do |config|
|
|
14
|
-
config.authenticate = ->(controller) do
|
|
15
|
-
# Example: require an admin user
|
|
16
|
-
controller.redirect_to(controller.main_app.root_path) unless controller.respond_to?(:current_user) && controller.current_user&.admin?
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
config.current_actor = ->(controller) do
|
|
20
|
-
controller.respond_to?(:current_user) ? controller.current_user : nil
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Defaults
|
|
26
|
-
|
|
27
|
-
These are the defaults in `AdminSuite::Configuration` / `AdminSuite::Engine`:
|
|
28
|
-
|
|
29
|
-
- `authenticate`: `nil`
|
|
30
|
-
- `current_actor`: `nil`
|
|
31
|
-
- `authorize`: `nil`
|
|
32
|
-
- `logout_path`: `nil`
|
|
33
|
-
- `logout_method`: `:delete`
|
|
34
|
-
- `logout_label`: `"Log out"`
|
|
35
|
-
- `resource_globs`: defaults to:
|
|
36
|
-
- `Rails.root/config/admin_suite/resources/*.rb`
|
|
37
|
-
- `Rails.root/app/admin/resources/*.rb`
|
|
38
|
-
- `action_globs`: defaults to:
|
|
39
|
-
- `Rails.root/config/admin_suite/actions/*.rb`
|
|
40
|
-
- `Rails.root/app/admin/actions/*.rb`
|
|
41
|
-
- `portal_globs`: defaults to:
|
|
42
|
-
- `Rails.root/config/admin_suite/portals/*.rb`
|
|
43
|
-
- `Rails.root/app/admin/portals/*.rb`
|
|
44
|
-
- `Rails.root/app/admin_suite/portals/*.rb`
|
|
45
|
-
- `dashboard_globs`: defaults to:
|
|
46
|
-
- `Rails.root/config/admin_suite/dashboard.rb`
|
|
47
|
-
- `Rails.root/config/admin_suite/dashboard/*.rb`
|
|
48
|
-
- `Rails.root/app/admin_suite/dashboard.rb`
|
|
49
|
-
- `Rails.root/app/admin_suite/dashboard/*.rb`
|
|
50
|
-
|
|
51
|
-
Note: AdminSuite definition files (resources, actions, portals) often don't follow
|
|
52
|
-
Zeitwerk's path-to-constant naming conventions. To prevent eager-load `Zeitwerk::NameError`s
|
|
53
|
-
in production, the engine only configures Zeitwerk to ignore these directories and load them via globs instead:
|
|
54
|
-
- `app/admin_suite`
|
|
55
|
-
- `app/admin/portals` (when portal DSL usage is detected)
|
|
56
|
-
|
|
57
|
-
Other `app/admin/*` directories (such as `app/admin/resources`, `app/admin/actions`, and `app/admin/base`) are
|
|
58
|
-
not ignored by default and may be treated as normal Zeitwerk autoload paths if they are added to the loader
|
|
59
|
-
(for example, via `loader.push_dir("app/admin")` in the host app). Do not rely on these directories being
|
|
60
|
-
ignored for autoloading; instead, keep files there Zeitwerk-compatible.
|
|
61
|
-
|
|
62
|
-
We recommend placing non-Zeitwerk-compatible definition files under `config/admin_suite/*` or `app/admin_suite/*`
|
|
63
|
-
for clearer separation from standard Rails autoloading.
|
|
64
|
-
- `portals`: default portal metadata for `:ops`, `:email`, `:ai`, `:assistant`
|
|
65
|
-
- `custom_renderers`: `{}`
|
|
66
|
-
- `icon_renderer`: `nil` (uses lucide-rails by default when available)
|
|
67
|
-
- `docs_url`: `nil`
|
|
68
|
-
- `docs_path`: `Rails.root.join("docs")`
|
|
69
|
-
- `partials`: `{}`
|
|
70
|
-
- `theme`: `{ primary: :indigo, secondary: :purple }`
|
|
71
|
-
- `host_stylesheet`: `nil`
|
|
72
|
-
- `tailwind_cdn`: `true`
|
|
73
|
-
- `on_action_executed`: `nil`
|
|
74
|
-
- `resolve_action_handler`: `nil`
|
|
75
|
-
|
|
76
|
-
## Options
|
|
77
|
-
|
|
78
|
-
### `authenticate`
|
|
79
|
-
|
|
80
|
-
Called as a `before_action` inside the engine.
|
|
81
|
-
|
|
82
|
-
- **Type**: `Proc` or `nil`
|
|
83
|
-
- **Signature**: `->(controller) { ... }`
|
|
84
|
-
|
|
85
|
-
If you don’t set it, AdminSuite will be accessible to any user that can reach the mounted route.
|
|
86
|
-
|
|
87
|
-
### `current_actor`
|
|
88
|
-
|
|
89
|
-
Used by actions/auditing hooks to identify “who initiated this”.
|
|
90
|
-
|
|
91
|
-
- **Type**: `Proc` or `nil`
|
|
92
|
-
- **Signature**: `->(controller) { current_user }`
|
|
93
|
-
|
|
94
|
-
### `authorize`
|
|
95
|
-
|
|
96
|
-
Optional authorization hook (you can wire Pundit/CanCan/ActionPolicy/etc).
|
|
97
|
-
|
|
98
|
-
- **Type**: `Proc` or `nil`
|
|
99
|
-
- **Signature**: `->(actor, action:, subject:, resource:, controller:) { true/false }`
|
|
100
|
-
|
|
101
|
-
Note: this hook is available, but your app must call it from resource definitions / custom actions as needed (AdminSuite will not guess your authorization policy).
|
|
102
|
-
|
|
103
|
-
### `logout_path`
|
|
104
|
-
|
|
105
|
-
Optional sign-out action shown in the top bar.
|
|
106
|
-
|
|
107
|
-
- **Type**: `Proc`, `String`, `Symbol`, or `nil`
|
|
108
|
-
- **Proc signature**: `->(view_context) { ... }`
|
|
109
|
-
|
|
110
|
-
Example:
|
|
111
|
-
|
|
112
|
-
```ruby
|
|
113
|
-
config.logout_path = ->(view) { view.main_app.internal_developer_logout_path }
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### `logout_method`
|
|
117
|
-
|
|
118
|
-
HTTP method for the topbar sign-out button.
|
|
119
|
-
|
|
120
|
-
- **Type**: `Symbol` or `String`
|
|
121
|
-
- **Default**: `:delete`
|
|
122
|
-
|
|
123
|
-
### `logout_label`
|
|
124
|
-
|
|
125
|
-
Button label for the topbar sign-out action.
|
|
126
|
-
|
|
127
|
-
- **Type**: `String` (or `Proc` for dynamic label)
|
|
128
|
-
- **Default**: `"Log out"`
|
|
129
|
-
|
|
130
|
-
### `resource_globs`
|
|
131
|
-
|
|
132
|
-
Where AdminSuite should load resource definition files from.
|
|
133
|
-
|
|
134
|
-
- **Type**: `Array<String>`
|
|
135
|
-
|
|
136
|
-
Example:
|
|
137
|
-
|
|
138
|
-
```ruby
|
|
139
|
-
config.resource_globs = [
|
|
140
|
-
Rails.root.join("app/admin/resources/**/*.rb").to_s
|
|
141
|
-
]
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### `action_globs`
|
|
145
|
-
|
|
146
|
-
Where AdminSuite should load action handler files from (files that define custom action handlers, typically subclasses of `Admin::Base::ActionHandler`).
|
|
147
|
-
|
|
148
|
-
- **Type**: `Array<String>`
|
|
149
|
-
|
|
150
|
-
Example:
|
|
151
|
-
|
|
152
|
-
```ruby
|
|
153
|
-
config.action_globs = [
|
|
154
|
-
Rails.root.join("app/admin/actions/**/*.rb").to_s
|
|
155
|
-
]
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### `portal_globs`
|
|
159
|
-
|
|
160
|
-
Where AdminSuite should load portal definition files from (files typically call `AdminSuite.portal(:key) { ... }`).
|
|
161
|
-
|
|
162
|
-
- **Type**: `Array<String>`
|
|
163
|
-
|
|
164
|
-
### `dashboard_globs`
|
|
165
|
-
|
|
166
|
-
Where AdminSuite should load the root dashboard definition file(s) from (files typically call `AdminSuite.root_dashboard { ... }`).
|
|
167
|
-
|
|
168
|
-
- **Type**: `Array<String>`
|
|
169
|
-
|
|
170
|
-
### `root_dashboard_title`
|
|
171
|
-
|
|
172
|
-
Optional title shown on the root dashboard.
|
|
173
|
-
|
|
174
|
-
- **Type**: `String`, `Proc`, or `nil`
|
|
175
|
-
- **Proc signature**: `->(controller) { "Admin Suite" }`
|
|
176
|
-
|
|
177
|
-
### `root_dashboard_description`
|
|
178
|
-
|
|
179
|
-
Optional description shown on the root dashboard.
|
|
180
|
-
|
|
181
|
-
- **Type**: `String`, `Proc`, or `nil`
|
|
182
|
-
- **Proc signature**: `->(controller) { "..." }`
|
|
183
|
-
|
|
184
|
-
### `portals`
|
|
185
|
-
|
|
186
|
-
Portal metadata used for navigation (label/icon/color/order). This is separate from the portal DSL and can be used alone.
|
|
187
|
-
|
|
188
|
-
- **Type**: `Hash{Symbol => Hash}`
|
|
189
|
-
|
|
190
|
-
Example:
|
|
191
|
-
|
|
192
|
-
```ruby
|
|
193
|
-
config.portals = {
|
|
194
|
-
ops: { label: "Ops", icon: "settings", color: :amber, order: 10 },
|
|
195
|
-
billing: { label: "Billing", icon: "credit-card", color: :emerald, order: 20 }
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### `theme`
|
|
200
|
-
|
|
201
|
-
Two-color theme used to set CSS variables scoped to AdminSuite.
|
|
202
|
-
|
|
203
|
-
- **Type**: `Hash` with `:primary` and `:secondary`
|
|
204
|
-
- **Values**: Tailwind-ish color names (`:indigo`, `:emerald`, …) or a hex string (`"#4f46e5"`)
|
|
205
|
-
|
|
206
|
-
See [Theming & assets](theming.md).
|
|
207
|
-
|
|
208
|
-
### `host_stylesheet`
|
|
209
|
-
|
|
210
|
-
If set, AdminSuite will include your host app stylesheet **after** its own styles in the engine layout.
|
|
211
|
-
|
|
212
|
-
- **Type**: `Symbol` or `String` (passed to `stylesheet_link_tag`)
|
|
213
|
-
- **Example**: `config.host_stylesheet = :app`
|
|
214
|
-
|
|
215
|
-
### `tailwind_cdn`
|
|
216
|
-
|
|
217
|
-
Reserved for host setups that want a CDN fallback. (AdminSuite already builds its own Tailwind CSS into your host app during `assets:precompile`.)
|
|
218
|
-
|
|
219
|
-
- **Type**: `true/false`
|
|
220
|
-
|
|
221
|
-
### `docs_url`
|
|
222
|
-
|
|
223
|
-
If set, shows a “Docs” link in the AdminSuite sidebar.
|
|
224
|
-
|
|
225
|
-
- **Type**: `String` or `nil`
|
|
226
|
-
|
|
227
|
-
### `docs_path`
|
|
228
|
-
|
|
229
|
-
Filesystem path where the docs viewer reads markdown from.
|
|
230
|
-
|
|
231
|
-
- **Type**: `Pathname`, `String`, or `Proc`
|
|
232
|
-
- **Proc signature**: `->(controller) { Rails.root.join("docs") }`
|
|
233
|
-
|
|
234
|
-
### `partials`
|
|
235
|
-
|
|
236
|
-
Override specific engine partials.
|
|
237
|
-
|
|
238
|
-
- **Type**: `Hash`
|
|
239
|
-
|
|
240
|
-
Example:
|
|
241
|
-
|
|
242
|
-
```ruby
|
|
243
|
-
config.partials[:flash] = "shared/flash"
|
|
244
|
-
config.partials[:panel_stat] = "admin/panels/stat"
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
### `custom_renderers`
|
|
248
|
-
|
|
249
|
-
Register custom show-section renderers (used when a show panel uses `render: :your_key`).
|
|
250
|
-
|
|
251
|
-
- **Type**: `Hash{Symbol => Proc}`
|
|
252
|
-
- **Proc signature**: `->(record, view_context) { ... }`
|
|
253
|
-
|
|
254
|
-
Example:
|
|
255
|
-
|
|
256
|
-
```ruby
|
|
257
|
-
config.custom_renderers[:billing_snapshot] = ->(record, view) do
|
|
258
|
-
view.render(partial: "admin/billing_snapshot", locals: { record: record })
|
|
259
|
-
end
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### `icon_renderer`
|
|
263
|
-
|
|
264
|
-
Replace the default icon provider (lucide-rails).
|
|
265
|
-
|
|
266
|
-
- **Type**: `Proc` or `nil`
|
|
267
|
-
- **Proc signature**: `->(name, view_context, **opts) { ... }`
|
|
268
|
-
|
|
269
|
-
### `resolve_action_handler`
|
|
270
|
-
|
|
271
|
-
Override how AdminSuite finds action handler classes.
|
|
272
|
-
|
|
273
|
-
- **Type**: `Proc` or `nil`
|
|
274
|
-
- **Proc signature**: `->(resource_class, action_name) { handler_class_or_nil }`
|
|
275
|
-
|
|
276
|
-
See [Actions](actions.md).
|
|
277
|
-
|
|
278
|
-
### `on_action_executed`
|
|
279
|
-
|
|
280
|
-
Hook called after action execution (success or failure).
|
|
281
|
-
|
|
282
|
-
- **Type**: `Proc` or `nil`
|
|
283
|
-
- **Proc signature**: `->(actor:, action_name:, resource_class:, subject:, params:, result:) { ... }`
|
|
284
|
-
|
data/docs/development.md
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# Development
|
|
2
|
-
|
|
3
|
-
This page is intended for contributors/maintainers working on the engine itself.
|
|
4
|
-
|
|
5
|
-
## Setup
|
|
6
|
-
|
|
7
|
-
From the gem root:
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
bundle install
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Run tests
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
bundle exec rake test
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Dummy app
|
|
20
|
-
|
|
21
|
-
AdminSuite uses a Rails “dummy” app under `test/dummy` for integration tests and to
|
|
22
|
-
exercise routing/assets in a host-like environment.
|
|
23
|
-
|
|
24
|
-
Useful commands (from the gem root):
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
cd test/dummy
|
|
28
|
-
bin/rails s
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Assets / Tailwind
|
|
32
|
-
|
|
33
|
-
AdminSuite ships:
|
|
34
|
-
|
|
35
|
-
- `app/assets/admin_suite.css` (baseline CSS)
|
|
36
|
-
- `app/assets/tailwind/admin_suite.css` (Tailwind input)
|
|
37
|
-
|
|
38
|
-
The engine Tailwind build task writes the compiled CSS into the **host app** builds folder:
|
|
39
|
-
|
|
40
|
-
- Output: `Rails.root/app/assets/builds/admin_suite_tailwind.css`
|
|
41
|
-
|
|
42
|
-
In a host app, this is run automatically during `assets:precompile`:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
bin/rails admin_suite:tailwind:build
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
When developing inside the engine repo itself, you can run it from the dummy app:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
cd test/dummy
|
|
52
|
-
bin/rails admin_suite:tailwind:build
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Docs
|
|
56
|
-
|
|
57
|
-
Engine docs live under:
|
|
58
|
-
|
|
59
|
-
- `docs/`
|
|
60
|
-
|
|
61
|
-
The docs viewer feature in the engine reads from the host app by default:
|
|
62
|
-
|
|
63
|
-
- `Rails.root/docs` (configurable via `AdminSuite.config.docs_path`)
|
|
64
|
-
|
data/docs/docs_viewer.md
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
# Docs viewer
|
|
2
|
-
|
|
3
|
-
AdminSuite includes a built-in docs viewer at:
|
|
4
|
-
|
|
5
|
-
- `/docs` (relative to the mount path)
|
|
6
|
-
|
|
7
|
-
It renders Markdown (`.md`) files from a folder on your host app filesystem.
|
|
8
|
-
|
|
9
|
-
## Quick start
|
|
10
|
-
|
|
11
|
-
1. Create `docs/` in your host app:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
mkdir -p docs
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
2. Add a markdown file:
|
|
18
|
-
|
|
19
|
-
```md
|
|
20
|
-
<!-- docs/getting_started.md -->
|
|
21
|
-
# Getting started
|
|
22
|
-
|
|
23
|
-
Hello from AdminSuite docs.
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
3. Visit:
|
|
27
|
-
|
|
28
|
-
- `/internal/admin/docs`
|
|
29
|
-
|
|
30
|
-
## Configuring the docs root (`config.docs_path`)
|
|
31
|
-
|
|
32
|
-
By default:
|
|
33
|
-
|
|
34
|
-
- `AdminSuite.config.docs_path = Rails.root.join("docs")`
|
|
35
|
-
|
|
36
|
-
You can point it somewhere else:
|
|
37
|
-
|
|
38
|
-
```ruby
|
|
39
|
-
AdminSuite.configure do |config|
|
|
40
|
-
config.docs_path = Rails.root.join("admin_docs")
|
|
41
|
-
end
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Or compute per-request:
|
|
45
|
-
|
|
46
|
-
```ruby
|
|
47
|
-
AdminSuite.configure do |config|
|
|
48
|
-
config.docs_path = ->(_controller) { Rails.root.join("docs") }
|
|
49
|
-
end
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Sidebar “Docs” link (`config.docs_url`)
|
|
53
|
-
|
|
54
|
-
If you want a persistent docs link in the AdminSuite sidebar, set:
|
|
55
|
-
|
|
56
|
-
```ruby
|
|
57
|
-
AdminSuite.configure do |config|
|
|
58
|
-
config.docs_url = "/internal/admin/docs"
|
|
59
|
-
end
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
This can also point to external docs.
|
|
63
|
-
|
|
64
|
-
## Organization
|
|
65
|
-
|
|
66
|
-
Docs are grouped by their first folder name. For example:
|
|
67
|
-
|
|
68
|
-
- `docs/ops/runbooks.md` → group “Ops”
|
|
69
|
-
- `docs/api/authentication.md` → group “API”
|
|
70
|
-
- `docs/getting_started.md` → group “Docs”
|
|
71
|
-
|
|
72
|
-
## Security notes
|
|
73
|
-
|
|
74
|
-
The docs viewer defends against path traversal:
|
|
75
|
-
|
|
76
|
-
- Rejects any path containing `..`
|
|
77
|
-
- Requires a `.md` extension
|
|
78
|
-
- Resolves realpaths and ensures the requested file stays under the docs root
|
|
79
|
-
|
data/docs/fields.md
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
# Fields
|
|
2
|
-
|
|
3
|
-
Fields are defined in the resource `form do ... end` block:
|
|
4
|
-
|
|
5
|
-
```ruby
|
|
6
|
-
form do
|
|
7
|
-
field :name
|
|
8
|
-
field :status, type: :select, collection: [["Active", "active"], ["Inactive", "inactive"]]
|
|
9
|
-
end
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## Common options
|
|
13
|
-
|
|
14
|
-
All fields support:
|
|
15
|
-
|
|
16
|
-
- `type:` (defaults to `:text`)
|
|
17
|
-
- `required:` (`true/false`)
|
|
18
|
-
- `label:` (String)
|
|
19
|
-
- `help:` (String)
|
|
20
|
-
- `placeholder:` (String)
|
|
21
|
-
- `readonly:` (`true/false`)
|
|
22
|
-
- `if:` Proc (render only if truthy)
|
|
23
|
-
- `unless:` Proc (render only if falsy)
|
|
24
|
-
|
|
25
|
-
Example conditional field:
|
|
26
|
-
|
|
27
|
-
```ruby
|
|
28
|
-
field :admin_notes, type: :textarea, if: ->(record) { record.admin? }
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Supported field types
|
|
32
|
-
|
|
33
|
-
### Text-like
|
|
34
|
-
|
|
35
|
-
- `:text` (default)
|
|
36
|
-
- `:textarea` (`rows:` supported)
|
|
37
|
-
- `:email`
|
|
38
|
-
- `:url`
|
|
39
|
-
- `:number`
|
|
40
|
-
- `:date`
|
|
41
|
-
- `:time`
|
|
42
|
-
- `:datetime`
|
|
43
|
-
|
|
44
|
-
### Toggle
|
|
45
|
-
|
|
46
|
-
- `:toggle` (renders a switch)
|
|
47
|
-
|
|
48
|
-
```ruby
|
|
49
|
-
field :enabled, type: :toggle
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Select
|
|
53
|
-
|
|
54
|
-
- `:select` (uses Rails `select`)
|
|
55
|
-
|
|
56
|
-
Options:
|
|
57
|
-
|
|
58
|
-
- `collection:` Array of `[label, value]` or simple values
|
|
59
|
-
|
|
60
|
-
```ruby
|
|
61
|
-
field :status, type: :select, collection: [["Active", "active"], ["Inactive", "inactive"]]
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Searchable select
|
|
65
|
-
|
|
66
|
-
- `:searchable_select` (Stimulus-powered searchable dropdown)
|
|
67
|
-
|
|
68
|
-
Options:
|
|
69
|
-
|
|
70
|
-
- `collection:` either:
|
|
71
|
-
- an Array (static options), or
|
|
72
|
-
- a String URL (advanced; used by the JS controller as a “search URL”)
|
|
73
|
-
- `create_url:` (String) enables “creatable” behavior in the UI
|
|
74
|
-
|
|
75
|
-
```ruby
|
|
76
|
-
field :company_id,
|
|
77
|
-
type: :searchable_select,
|
|
78
|
-
collection: Company.order(:name).pluck(:name, :id),
|
|
79
|
-
placeholder: "Search companies..."
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Multi-select & tags
|
|
83
|
-
|
|
84
|
-
- `:multi_select`
|
|
85
|
-
- `:tags`
|
|
86
|
-
|
|
87
|
-
Options:
|
|
88
|
-
|
|
89
|
-
- `collection:` Array of options (used for suggestions)
|
|
90
|
-
- `create_url:` enables “creatable” behavior
|
|
91
|
-
- `multiple:` boolean (reserved; arrays are permitted automatically)
|
|
92
|
-
|
|
93
|
-
Notes:
|
|
94
|
-
|
|
95
|
-
- These submit arrays and are permitted automatically by AdminSuite.
|
|
96
|
-
- For `:tags`, AdminSuite uses a `tag_list` parameter by default (or `#{field_name}_list` if your model exposes it).
|
|
97
|
-
|
|
98
|
-
```ruby
|
|
99
|
-
field :tag_list, type: :tags, placeholder: "Add tags..."
|
|
100
|
-
field :roles, type: :multi_select, collection: %w[admin editor viewer]
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### File uploads / attachments
|
|
104
|
-
|
|
105
|
-
- `:file`
|
|
106
|
-
- `:attachment`
|
|
107
|
-
- `:image`
|
|
108
|
-
|
|
109
|
-
Options:
|
|
110
|
-
|
|
111
|
-
- `accept:` MIME accept string (e.g. `"image/*"`, `"application/pdf"`)
|
|
112
|
-
|
|
113
|
-
These assume your host app uses **Active Storage**.
|
|
114
|
-
|
|
115
|
-
```ruby
|
|
116
|
-
field :avatar, type: :image, accept: "image/*"
|
|
117
|
-
field :resume, type: :file, accept: "application/pdf"
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### Rich text
|
|
121
|
-
|
|
122
|
-
- `:trix`
|
|
123
|
-
- `:rich_text`
|
|
124
|
-
|
|
125
|
-
These assume your host app uses **Action Text**.
|
|
126
|
-
|
|
127
|
-
```ruby
|
|
128
|
-
field :bio, type: :rich_text
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Markdown
|
|
132
|
-
|
|
133
|
-
- `:markdown` (textarea enhanced by EasyMDE via CDN in the engine layout)
|
|
134
|
-
|
|
135
|
-
```ruby
|
|
136
|
-
field :prompt_template, type: :markdown, rows: 16
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### JSON editor
|
|
140
|
-
|
|
141
|
-
- `:json` (renders the engine’s JSON editor partial)
|
|
142
|
-
|
|
143
|
-
```ruby
|
|
144
|
-
field :settings, type: :json
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### Code editor
|
|
148
|
-
|
|
149
|
-
- `:code` (monospace editor container; enhanced by engine JS)
|
|
150
|
-
|
|
151
|
-
```ruby
|
|
152
|
-
field :ruby_code, type: :code, rows: 20
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### Label (read-only)
|
|
156
|
-
|
|
157
|
-
- `:label` renders a badge-like value (useful for status fields)
|
|
158
|
-
|
|
159
|
-
Options:
|
|
160
|
-
|
|
161
|
-
- `label_color:` Symbol or Proc
|
|
162
|
-
- `label_size:` `:sm`/`:md` or Proc
|
|
163
|
-
|
|
164
|
-
```ruby
|
|
165
|
-
field :status, type: :label, label_color: ->(r) { r.active? ? :emerald : :slate }, label_size: :sm
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
## Layout helpers
|
|
169
|
-
|
|
170
|
-
Inside `form do ... end` you can group fields:
|
|
171
|
-
|
|
172
|
-
### `section`
|
|
173
|
-
|
|
174
|
-
```ruby
|
|
175
|
-
section "Billing", description: "Payment settings", collapsible: true do
|
|
176
|
-
field :stripe_customer_id, readonly: true
|
|
177
|
-
end
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### `row`
|
|
181
|
-
|
|
182
|
-
```ruby
|
|
183
|
-
row cols: 2 do
|
|
184
|
-
field :first_name
|
|
185
|
-
field :last_name
|
|
186
|
-
end
|
|
187
|
-
```
|
|
188
|
-
|