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.
data/docs/installation.md DELETED
@@ -1,80 +0,0 @@
1
- # Installation
2
-
3
- ## Requirements
4
-
5
- - Ruby **3.2+**
6
- - Rails **8.0+**
7
-
8
- AdminSuite is a mountable engine. You mount it under a path in your host app’s `config/routes.rb`.
9
-
10
- ## Add the gem
11
-
12
- In your host app `Gemfile`:
13
-
14
- ```ruby
15
- gem "admin_suite"
16
- ```
17
-
18
- Then:
19
-
20
- ```bash
21
- bundle install
22
- ```
23
-
24
- ## Install into your app
25
-
26
- Run the install generator (creates an initializer and mounts the engine):
27
-
28
- ```bash
29
- bin/rails g admin_suite:install
30
- ```
31
-
32
- To mount at a custom path:
33
-
34
- ```bash
35
- bin/rails g admin_suite:install --mount-path=/internal/admin
36
- ```
37
-
38
- This will:
39
-
40
- - Create `config/initializers/admin_suite.rb`
41
- - Add a route like `mount AdminSuite::Engine => "/internal/admin"`
42
-
43
- ## First run checklist
44
-
45
- - **Auth**: set `config.authenticate` so only permitted users can access AdminSuite.
46
- - **Actor**: set `config.current_actor` if you want actions/auditing to know “who did it”.
47
- - **Resources**: add at least one resource definition file (see [Resources](resources.md)).
48
- - **Portals**: set up portal metadata and dashboards (see [Portals](portals.md)).
49
-
50
- ## Assets (CSS/JS)
51
-
52
- AdminSuite ships with:
53
-
54
- - A small baseline stylesheet (`admin_suite.css`)
55
- - A compiled Tailwind stylesheet (`admin_suite_tailwind.css`) that is built into the host app at asset precompile time
56
- - Engine-provided Stimulus controllers via importmap
57
-
58
- ### CSS build behavior
59
-
60
- When your app runs `assets:precompile`, AdminSuite automatically runs:
61
-
62
- - `admin_suite:tailwind:build` → writes `app/assets/builds/admin_suite_tailwind.css` in your **host app**
63
-
64
- So in production you typically just need to ensure your deployment runs `assets:precompile` as usual.
65
-
66
- ### Host stylesheet overrides (optional)
67
-
68
- If your app already uses Tailwind (or you want custom branding), you can include your app stylesheet after AdminSuite:
69
-
70
- - Set `config.host_stylesheet` (see [Theming & assets](theming.md))
71
-
72
- ## Routes and URLs
73
-
74
- Assuming you mounted at `/internal/admin`:
75
-
76
- - `/internal/admin` → AdminSuite dashboard
77
- - `/internal/admin/docs` → docs viewer (optional)
78
- - `/internal/admin/:portal` → portal dashboard (optional)
79
- - `/internal/admin/:portal/:resource_name` → resource index
80
-
data/docs/portals.md DELETED
@@ -1,140 +0,0 @@
1
- # Portals & dashboards
2
-
3
- AdminSuite navigation is organized by **portal** and **section**:
4
-
5
- - A **portal** is the top-level grouping (e.g. `:ops`, `:ai`)
6
- - A **section** is a grouping within a portal (e.g. `:billing`, `:users`)
7
- - A **resource** belongs to exactly one portal + section via the resource DSL
8
-
9
- You can configure portals in two complementary ways:
10
-
11
- 1. **Portal metadata** via `AdminSuite.config.portals` (label/icon/color/order)
12
- 2. **Portal DSL** via `AdminSuite.portal(:key) { ... }` (metadata + dashboard layout)
13
-
14
- ## Portal metadata (`config.portals`)
15
-
16
- ```ruby
17
- AdminSuite.configure do |config|
18
- config.portals = {
19
- ops: { label: "Ops", icon: "settings", color: :amber, order: 10 },
20
- ai: { label: "AI", icon: "cpu", color: :cyan, order: 20 }
21
- }
22
- end
23
- ```
24
-
25
- ### Portal fields
26
-
27
- - `label` (String): display label
28
- - `icon` (String/Symbol): lucide icon name (e.g. `"settings"`)
29
- - `color` (Symbol/String): used for accents (`:amber`, `:emerald`, `:cyan`, `:violet`, `:slate`)
30
- - `order` (Integer): sort order in the root dashboard and sidebar
31
- - `description` (String, optional): shown on the root dashboard cards when present
32
-
33
- ## Portal DSL (`AdminSuite.portal`)
34
-
35
- Portal DSL files are loaded from `AdminSuite.config.portal_globs` (defaults include
36
- `config/admin_suite/portals/*.rb`, `app/admin/portals/*.rb`, `app/admin_suite/portals/*.rb`).
37
-
38
- Example file:
39
-
40
- ```ruby
41
- # config/admin_suite/portals/ops.rb
42
- AdminSuite.portal :ops do
43
- label "Ops Portal"
44
- icon "settings"
45
- color :amber
46
- order 10
47
- description "Operational tools and internal resources."
48
-
49
- dashboard do
50
- row do
51
- stat_panel "New users (24h)", -> { User.where("created_at > ?", 24.hours.ago).count }, color: :emerald, span: 3
52
- stat_panel "Failed jobs", -> { SolidQueue::FailedExecution.count }, color: :red, span: 3
53
- end
54
-
55
- row do
56
- recent_panel "Recent signups", scope: -> { User.order(created_at: :desc).limit(5) }, span: 6
57
- table_panel "Queue summary",
58
- rows: -> { SolidQueue::Job.order(created_at: :desc).limit(10) },
59
- columns: %i[id class_name created_at],
60
- span: 6
61
- end
62
- end
63
- end
64
- ```
65
-
66
- ## Dashboard DSL
67
-
68
- The dashboard DSL is available inside `portal.dashboard do ... end`.
69
-
70
- - `dashboard` contains `row { ... }`
71
- - each `row` contains one or more `panel(...)` calls
72
-
73
- ### Panel helpers
74
-
75
- These are convenience helpers that all create a `panel` under the hood:
76
-
77
- - `stat_panel(title, value=nil, span: nil, **options, &block)`
78
- - `health_panel(title, status: nil, metrics: nil, span: nil, **options, &block)`
79
- - `chart_panel(title, data: nil, span: nil, **options, &block)`
80
- - `cards_panel(title, resources: nil, span: nil, **options, &block)`
81
- - `recent_panel(title, scope: nil, link: nil, span: nil, **options, &block)`
82
- - `table_panel(title, rows: nil, columns: nil, span: nil, **options, &block)`
83
-
84
- ### `span`
85
-
86
- `span` controls width in a 12-column grid. Typical values: `3`, `4`, `6`, `12`.
87
-
88
- ## Portal pages
89
-
90
- Once mounted, portal pages are served at:
91
-
92
- - `/:portal` (relative to the mount path)
93
-
94
- Example:
95
-
96
- - `/internal/admin/ops`
97
- - `/internal/admin/ai`
98
-
99
- ## Root dashboard (`AdminSuite.root_dashboard`)
100
-
101
- The engine root (`/`, relative to the mount path) renders a default dashboard (portal cards + basic stats).
102
-
103
- To customize it, create a dashboard definition file (loaded from `AdminSuite.config.dashboard_globs`, which defaults to paths like `config/admin_suite/dashboard.rb` and `app/admin_suite/dashboard.rb`):
104
-
105
- ```ruby
106
- # config/admin_suite/dashboard.rb
107
- AdminSuite.configure do |config|
108
- config.root_dashboard_title = "Developer Portal"
109
- config.root_dashboard_description = "Internal tools for managing application resources."
110
- end
111
-
112
- AdminSuite.root_dashboard do
113
- row do
114
- cards_panel "Portals",
115
- span: 12,
116
- variant: :portals,
117
- resources: ->(view) do
118
- view.navigation_items
119
- .sort_by { |(_k, meta)| (meta[:order] || 100).to_i }
120
- .map do |portal_key, portal|
121
- {
122
- key: portal_key,
123
- label: portal[:label] || portal_key.to_s.humanize,
124
- description: portal[:description],
125
- color: view.portal_color(portal_key),
126
- icon: portal[:icon],
127
- path: view.portal_path(portal: portal_key),
128
- count: (portal[:sections] || {}).values.sum { |s| Array(s[:items]).size }
129
- }
130
- end
131
- end
132
- end
133
-
134
- row do
135
- stat_panel "Portals", ->(view) { view.navigation_items.keys.count }, span: 6, variant: :mini, color: :slate
136
- stat_panel "Resources", -> { Admin::Base::Resource.registered_resources.count }, span: 6, variant: :mini, color: :slate
137
- end
138
- end
139
- ```
140
-
data/docs/releasing.md DELETED
@@ -1,67 +0,0 @@
1
- # Releasing
2
-
3
- This page is intended for maintainers publishing `admin_suite` to RubyGems.
4
-
5
- ## Automated Release Process (Recommended)
6
-
7
- The gem is automatically published to RubyGems when changes are merged to `main`, provided the version has been bumped.
8
-
9
- ### Steps
10
-
11
- 1. **Bump the version**
12
- - Update `lib/admin_suite/version.rb`
13
-
14
- 2. **Update changelog**
15
- - Add an entry to `CHANGELOG.md`
16
-
17
- 3. **Create a PR and get it merged**
18
- - The CI workflow will run tests automatically on the PR
19
- - Once merged to `main`, after CI passes, the publish workflow will:
20
- - Check if the version already exists on RubyGems
21
- - Build and publish the gem (if it's a new version)
22
- - Create a Git tag for the release (if it doesn't already exist)
23
- - Create a GitHub Release with notes extracted from `CHANGELOG.md`, or auto-generated from commits since the previous tag if no CHANGELOG entry exists
24
-
25
- ### Requirements
26
-
27
- - The `RUBYGEMS_API_KEY` secret must be configured in the repository settings
28
- - The version in `lib/admin_suite/version.rb` must be unique (not already published)
29
-
30
- ## Manual Release Process
31
-
32
- If you need to publish manually:
33
-
34
- 1. Bump the version
35
- - Update `lib/admin_suite/version.rb`
36
-
37
- 2. Update changelog
38
- - Add an entry to `CHANGELOG.md`
39
-
40
- 3. Run tests and build the gem
41
-
42
- ```bash
43
- bundle exec rake test
44
- gem build admin_suite.gemspec
45
- ```
46
-
47
- 4. Tag the release
48
-
49
- ```bash
50
- git tag -a "vX.Y.Z" -m "AdminSuite vX.Y.Z"
51
- git push --tags
52
- ```
53
-
54
- 5. Publish to RubyGems
55
-
56
- ```bash
57
- gem push "admin_suite-X.Y.Z.gem"
58
- ```
59
-
60
- ## Notes
61
-
62
- - RubyGems commonly requires MFA/OTP for pushes (this gem is configured with `rubygems_mfa_required`)
63
- - The automated workflow uses a GitHub Actions bot to push tags and create GitHub Releases
64
- - The publish workflow only runs after the CI workflow completes successfully
65
- - GitHub Release notes are sourced from the matching version section in `CHANGELOG.md`; if no entry exists, they are auto-generated from commits since the previous tag; a plain "Release vX.Y.Z" string is used only as a final fallback when no previous tag or commit-generated notes are available
66
- - You can manually trigger the publish workflow from the GitHub Actions tab if needed
67
-
data/docs/resources.md DELETED
@@ -1,237 +0,0 @@
1
- # Resources
2
-
3
- Resources are defined using `Admin::Base::Resource`.
4
-
5
- AdminSuite loads resource definition files from `AdminSuite.config.resource_globs`
6
- (defaults include `config/admin_suite/resources/*.rb` and `app/admin/resources/*.rb`).
7
-
8
- ## Create a resource
9
-
10
- A resource is a Ruby class under `Admin::Resources` ending in `Resource`.
11
-
12
- Example:
13
-
14
- ```ruby
15
- # config/admin_suite/resources/user.rb
16
- module Admin
17
- module Resources
18
- class UserResource < Admin::Base::Resource
19
- model ::User
20
- portal :ops
21
- section :accounts
22
-
23
- nav label: "Users", icon: "users", order: 10
24
-
25
- index do
26
- searchable :email, :name
27
- sortable :created_at, :email, default: :created_at, direction: :desc
28
- paginate 50
29
-
30
- columns do
31
- column :id
32
- column :email
33
- column :created_at
34
- column :admin, type: :toggle, toggle_field: :admin, header: "Admin?"
35
- column :status, type: :label, label_color: ->(u) { u.active? ? :emerald : :slate }, label_size: :sm
36
- end
37
-
38
- filters do
39
- filter :search, type: :text, placeholder: "Search users..."
40
- filter :status, type: :select, options: [["Active", "active"], ["Inactive", "inactive"]]
41
- end
42
-
43
- stats do
44
- stat :total, -> { User.count }, color: :slate
45
- stat :new_24h, -> { User.where("created_at > ?", 24.hours.ago).count }, color: :emerald
46
- end
47
- end
48
-
49
- form do
50
- section "Basics", description: "Core account fields" do
51
- field :email, type: :email, required: true
52
- field :name, required: true
53
- end
54
-
55
- row cols: 2 do
56
- field :admin, type: :toggle, help: "Grants access to internal tools."
57
- field :status, type: :select, collection: [["Active", "active"], ["Inactive", "inactive"]]
58
- end
59
- end
60
-
61
- show do
62
- main do
63
- panel :details, title: "User details", fields: %i[email name status created_at]
64
- panel :activity, title: "Activity", render: :custom_activity_timeline
65
- end
66
-
67
- sidebar do
68
- panel :summary, title: "Summary", fields: %i[id admin]
69
- end
70
- end
71
-
72
- actions do
73
- action :reset_password, label: "Reset password", icon: "key", confirm: "Send reset email?"
74
- end
75
- end
76
- end
77
- end
78
- ```
79
-
80
- ## Core DSL
81
-
82
- ### Model
83
-
84
- ```ruby
85
- model ::User
86
- ```
87
-
88
- ### Navigation placement
89
-
90
- ```ruby
91
- portal :ops
92
- section :accounts
93
- ```
94
-
95
- These determine:
96
-
97
- - URL: `/:portal/:resource_name`
98
- - Sidebar placement: portal group → section group → resource link
99
-
100
- ### Navigation metadata
101
-
102
- ```ruby
103
- nav label: "Users", icon: "users", order: 10
104
- ```
105
-
106
- Also available as convenience setters:
107
-
108
- ```ruby
109
- label "Users"
110
- icon "users"
111
- order 10
112
- ```
113
-
114
- ## Index DSL (`index do ... end`)
115
-
116
- ### Search
117
-
118
- ```ruby
119
- searchable :name, :email
120
- ```
121
-
122
- Search uses `ILIKE` across the configured fields.
123
-
124
- ### Sort
125
-
126
- ```ruby
127
- sortable :created_at, :email, default: :created_at, direction: :desc
128
- ```
129
-
130
- ### Pagination
131
-
132
- ```ruby
133
- paginate 25
134
- ```
135
-
136
- ### Columns
137
-
138
- ```ruby
139
- columns do
140
- column :email
141
- column :job_listings, ->(u) { u.job_listings.count }
142
- end
143
- ```
144
-
145
- `column` options:
146
-
147
- - `header:` string (defaults to a humanized name)
148
- - `class:` css class for the cell
149
- - `render:` custom render key (advanced)
150
- - `type:` `:toggle` or `:label` (special rendering)
151
- - `toggle_field:` field to flip when `type: :toggle`
152
- - `label_color:` color for `type: :label` (Symbol or Proc)
153
- - `label_size:` `:sm`/`:md` (or Proc)
154
- - `sortable:` boolean (reserved for future per-column sorting UI)
155
-
156
- ### Filters
157
-
158
- ```ruby
159
- filters do
160
- filter :status, type: :select, options: [["Active", "active"], ["Inactive", "inactive"]]
161
- end
162
- ```
163
-
164
- Filter options:
165
-
166
- - `type:` (default `:text`)
167
- - `label:`
168
- - `placeholder:`
169
- - `options:` / `collection:` (for select-like UI)
170
- - `field:` which model field to filter on (defaults to the filter name)
171
- - `apply:` Proc that receives the scope (advanced)
172
-
173
- ### Stats
174
-
175
- ```ruby
176
- stats do
177
- stat :total, -> { User.count }, color: :slate
178
- end
179
- ```
180
-
181
- ## Form DSL (`form do ... end`)
182
-
183
- ```ruby
184
- form do
185
- field :name, required: true
186
- field :website, type: :url
187
- end
188
- ```
189
-
190
- See [Fields](fields.md) for supported types and options.
191
-
192
- AdminSuite also supports basic layout helpers in forms:
193
-
194
- - `section "Title" do ... end`
195
- - `row cols: 2 do ... end`
196
-
197
- ## Show DSL (`show do ... end`)
198
-
199
- Show is section-based. Sections can live in the main column or sidebar.
200
-
201
- ```ruby
202
- show do
203
- main do
204
- panel :details, title: "Details", fields: %i[name email]
205
- panel :related, title: "Projects", association: :projects, display: :table, columns: %i[id name status], paginate: true
206
- end
207
-
208
- sidebar do
209
- panel :meta, title: "Meta", fields: %i[id created_at updated_at]
210
- end
211
- end
212
- ```
213
-
214
- Panel options:
215
-
216
- - `title:` (defaults to a humanized name)
217
- - `fields:` array of field names to display
218
- - `render:` custom renderer key (see `custom_renderers` in [Configuration](configuration.md))
219
- - `association:` association name to render (`has_many`, `belongs_to`, etc.)
220
- - `display:` `:list` (default), `:table`, or `:cards` for associations
221
- - `columns:` columns for association `:table` display
222
- - `link_to:` helper method name to build links for association items (optional)
223
- - `paginate:` boolean, enables pagination within the association section
224
- - `per_page:` items per page for association pagination
225
- - `limit:` max items (if not paginating)
226
- - `collapsible:` / `collapsed:` (reserved for future UI toggles)
227
-
228
- ## Actions DSL (`actions do ... end`)
229
-
230
- ```ruby
231
- actions do
232
- action :reindex, label: "Reindex", method: :post, confirm: "Reindex this record?"
233
- end
234
- ```
235
-
236
- See [Actions](actions.md) for how actions execute and how to define handlers.
237
-
data/docs/theming.md DELETED
@@ -1,63 +0,0 @@
1
- # Theming & assets
2
-
3
- AdminSuite is designed to work in two modes:
4
-
5
- 1. **Engine-build mode (default)**: AdminSuite builds and ships its own Tailwind CSS into your host app at `assets:precompile` time.
6
- 2. **Host-themed mode (optional)**: your host app includes a stylesheet after AdminSuite for branding/overrides.
7
-
8
- ## Theme colors (`config.theme`)
9
-
10
- AdminSuite uses CSS variables scoped to `body.admin-suite`.
11
-
12
- ```ruby
13
- AdminSuite.configure do |config|
14
- config.theme = { primary: :emerald, secondary: :cyan }
15
- end
16
- ```
17
-
18
- ### Allowed values
19
-
20
- - **Named colors**: symbols/strings like `:indigo`, `:emerald`, `:cyan`, `:amber`, `:violet`, `:slate`, etc.
21
- - **Hex**: `"#4f46e5"` (uses that exact color as primary/secondary in key places)
22
-
23
- The theme primarily drives:
24
-
25
- - Primary links/buttons (`--admin-suite-primary`, `--admin-suite-primary-hover`)
26
- - Sidebar gradient (`--admin-suite-sidebar-from/via/to`)
27
-
28
- ## Host stylesheet (`config.host_stylesheet`)
29
-
30
- If your host app already has Tailwind (or you want to override the engine UI), you can include an additional stylesheet after AdminSuite in the engine layout:
31
-
32
- ```ruby
33
- AdminSuite.configure do |config|
34
- config.host_stylesheet = :app
35
- end
36
- ```
37
-
38
- This calls `stylesheet_link_tag :app` after `admin_suite.css` and `admin_suite_tailwind.css`.
39
-
40
- ## Tailwind build
41
-
42
- AdminSuite writes an engine stylesheet into your host app during `assets:precompile`:
43
-
44
- - Input: `AdminSuite::Engine.root/app/assets/tailwind/admin_suite.css`
45
- - Output: `Rails.root/app/assets/builds/admin_suite_tailwind.css`
46
-
47
- In development, the engine also makes a best-effort to create the output file if it’s missing, so the UI stays usable.
48
-
49
- ## Icons
50
-
51
- AdminSuite uses lucide icons by default via `lucide-rails`.
52
-
53
- If you need a different icon provider:
54
-
55
- ```ruby
56
- AdminSuite.configure do |config|
57
- config.icon_renderer = ->(name, view, **opts) do
58
- # return HTML-safe SVG (string or ActiveSupport::SafeBuffer)
59
- view.content_tag(:span, name, class: opts[:class])
60
- end
61
- end
62
- ```
63
-
@@ -1,50 +0,0 @@
1
- # Troubleshooting
2
-
3
- ## “My resources don’t show up in the sidebar”
4
-
5
- Checklist:
6
-
7
- - Your resource class:
8
- - is under `Admin::Resources`
9
- - ends with `Resource` (e.g. `UserResource`)
10
- - sets both `portal :...` and `section :...`
11
- - The file is located under one of the configured `resource_globs` paths (see [Configuration](configuration.md)).
12
-
13
- In development, AdminSuite loads resources on-demand when building navigation. In non-development environments, you should ensure your resource files are loaded at boot (using the globs) and are not excluded by your deployment setup.
14
-
15
- ## “Constant not found” / Zeitwerk errors for host DSL files
16
-
17
- If you store AdminSuite DSL files under `app/admin_suite/**` in the host app, those files are not constant definitions.
18
-
19
- AdminSuite ignores `Rails.root/app/admin_suite` in Zeitwerk to prevent eager-load errors. If you still see issues:
20
-
21
- - Ensure the DSL folder really is `app/admin_suite` (not a different path)
22
- - Prefer `config/admin_suite/resources/*.rb` and `config/admin_suite/portals/*.rb` for DSL files
23
-
24
- ## “Docs viewer shows no files”
25
-
26
- - Confirm `AdminSuite.config.docs_path` exists
27
- - Ensure files are `*.md`
28
- - Visit `/docs` relative to your mount path (e.g. `/internal/admin/docs`)
29
-
30
- ## “Tailwind styles are missing in production”
31
-
32
- AdminSuite expects `assets:precompile` to run and generate:
33
-
34
- - `app/assets/builds/admin_suite_tailwind.css` in your host app
35
-
36
- If you don’t run precompile in your deployment pipeline, you can:
37
-
38
- - Start running `assets:precompile`, or
39
- - Build the file manually by running:
40
-
41
- ```bash
42
- bin/rails admin_suite:tailwind:build
43
- ```
44
-
45
- ## “Icons don’t render”
46
-
47
- AdminSuite defaults to `lucide-rails`.
48
-
49
- If your host app excludes it, set `AdminSuite.config.icon_renderer` to provide icons (see [Theming & assets](theming.md)).
50
-