feat(dashboard): support fully offline use#408
Conversation
The dashboard loaded Inter (Google Fonts) and chart.js, Alpine.js, and Lucide (jsDelivr CDN) over the network, making it unusable offline. Vendor all of them into the embedded static tree and reference them via the existing assetURL pipeline: - static/vendor/: chart.js, Alpine.js, Lucide (verified against the SRI hashes previously declared in layout.html; sourceMappingURL comments stripped so no .map files are requested). - static/fonts/: Inter as a single variable woff2 per subset (latin, latin-ext) with a local @font-face stylesheet. Extend the //go:embed directive and drop the preconnect/CDN/integrity attributes. No build system or asset-serving changes required. Refs #407
When audit logging (LOGGING_ENABLED, off by default) or usage tracking is disabled, the /admin/audit/log and /admin/usage/log fast paths returned an empty response with limit:0. The dashboard reuses the returned limit as the next request's limit param, so the following request sent limit=0, which validation rejects with 400 "invalid limit, expected positive integer". Echo the requested limit/offset in both disabled-reader responses so they match the enabled-reader contract (which clamps limit to a positive value). The dashboard's audit/usage pages now load cleanly with their readers off, showing an empty list instead of erroring. Refs #407
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThe PR vendors Inter font files and JS libraries (Chart.js, Alpine, Lucide) into the admin dashboard's embedded filesystem, replacing CDN references in ChangesDashboard Offline Asset Vendoring
Pagination Echo in Nil-Reader Fast Paths
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Confidence Score: 5/5This looks safe to merge.
Reviews (2): Last reviewed commit: "fix(admin): default page size in disable..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/admin/dashboard/dashboard_test.go`:
- Around line 341-343: The regular expression pattern in the `loaded` variable
does not detect protocol-relative URLs (those starting with `//`), allowing
external dependencies to bypass the offline guard. Update the regex pattern used
in `regexp.MustCompile` to match not only `https?://` but also `//` for
protocol-relative URLs. This should catch all forms of external resource
references including `src="//..."`, `href="//..."`, and `url(//...)` patterns in
addition to the currently matched absolute URLs.
In `@internal/admin/dashboard/static/fonts/inter.css`:
- Line 4: The font-family name 'Inter' is quoted in violation of the Stylelint
font-family-name-quotes rule, which fails CI checks. Remove the single quotes
surrounding Inter in all font-family declarations in the inter.css file (at
lines 4 and 12 as indicated) so that the font-family property reads font-family:
Inter; without any quotes around the family name.
In `@internal/admin/handler_audit.go`:
- Around line 115-119: The auditLogListResponse return statement is currently
setting Limit directly to params.Limit, which is 0 when the query parameter is
omitted. This contradicts the documented default page size of 25 and can cause
client-loop behavior. Modify the Limit field in the auditLogListResponse struct
initialization to apply a default value: if params.Limit is 0 (meaning not
explicitly set), use the documented default page size of 25 instead, otherwise
use the provided params.Limit value.
In `@internal/admin/handler_test.go`:
- Around line 615-617: The pagination tests in both locations (around the
result.Limit assertion at 615-617 and the second similar test at 772-774) are
incomplete. They verify the limit value but do not assert the offset value even
though offset=0 is being sent. Add an assertion for result.Offset to verify it
equals 0 in both test blocks to fully validate the pagination contract being
tested.
In `@internal/admin/handler_usage.go`:
- Around line 206-210: The nil-reader path returns usage.UsageLogResult with
params.Limit directly, which is 0 when the query omits the limit parameter, but
the documented default should be 50. Modify the return statement to use a
default limit value of 50 when params.Limit is 0, ensuring the Limit field in
the UsageLogResult reflects the actual default that will be used for processing,
not the unset zero value.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b5ad87a8-fbcb-41dd-97be-cdb7319bacaf
⛔ Files ignored due to path filters (5)
internal/admin/dashboard/static/fonts/inter-latin-ext.woff2is excluded by!**/*.woff2internal/admin/dashboard/static/fonts/inter-latin.woff2is excluded by!**/*.woff2internal/admin/dashboard/static/vendor/alpine.min.jsis excluded by!**/*.min.jsinternal/admin/dashboard/static/vendor/chart.umd.min.jsis excluded by!**/*.min.jsinternal/admin/dashboard/static/vendor/lucide.min.jsis excluded by!**/*.min.js
📒 Files selected for processing (8)
internal/admin/dashboard/dashboard.gointernal/admin/dashboard/dashboard_test.gointernal/admin/dashboard/static/fonts/inter.cssinternal/admin/dashboard/static/js/modules/dashboard-layout.test.cjsinternal/admin/dashboard/templates/layout.htmlinternal/admin/handler_audit.gointernal/admin/handler_test.gointernal/admin/handler_usage.go
| /* Inter (variable, latin + latin-ext subsets) — vendored from Google Fonts for offline use. | ||
| v20 ships one variable woff2 per subset, so a single @font-face covers weights 400-700. */ | ||
| @font-face { | ||
| font-family: 'Inter'; |
There was a problem hiding this comment.
Fix Stylelint font-family-name-quotes violations.
The quoted Inter family name fails the configured lint rule and can break CI.
Suggested fix
- font-family: 'Inter';
+ font-family: Inter;- font-family: 'Inter';
+ font-family: Inter;Also applies to: 12-12
🧰 Tools
🪛 Stylelint (17.13.0)
[error] 4-4: Expected no quotes around "Inter" (font-family-name-quotes)
(font-family-name-quotes)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/admin/dashboard/static/fonts/inter.css` at line 4, The font-family
name 'Inter' is quoted in violation of the Stylelint font-family-name-quotes
rule, which fails CI checks. Remove the single quotes surrounding Inter in all
font-family declarations in the inter.css file (at lines 4 and 12 as indicated)
so that the font-family property reads font-family: Inter; without any quotes
around the family name.
Source: Linters/SAST tools
Address PR review: when the caller omits limit, params.Limit is 0, so the disabled-reader fast paths still echoed limit:0 and could drive the same client limit=0 loop. Echo the documented default (25 audit / 50 usage) via named constants alongside the existing max constants, matching the enabled-reader clamp. Tests now omit limit and assert the default limit and offset. Also harden the offline-resource guard to catch protocol-relative (//cdn...) URLs. Refs #407
|
Thanks for the reviews. Addressed in bcccedc:
Intentionally not changed:
Full pre-commit suite ( |
Closes #407
Problem
The admin dashboard loaded several assets over the network — the Inter typeface from Google Fonts and chart.js, Alpine.js, and Lucide icons from the jsDelivr CDN. In an offline environment the dashboard was effectively unusable: no styling, no charts, no interactivity, no icons.
Changes
Vendor all front-end assets (offline support — the issue)
static/vendor/—chart.umd.min.js,alpine.min.js,lucide.min.js, served from the embedded static tree via the existingassetURLpipeline. Each file was verified byte-for-byte against the SRI hashes previously declared inlayout.html, and the trailing//# sourceMappingURL=…comments were stripped so browsers don't 404 on.mapfiles that aren't shipped.static/fonts/— Inter vendored as one variablewoff2per subset (latin,latin-ext) with a local@font-facestylesheet. Inter v20 ships a single variable file per subset, so one@font-facewithfont-weight: 400 700covers every weight the UI uses. System-font fallbacks already cover non-Latin text.layout.htmlnow references these local assets and drops thepreconnect/CDN/integrityattributes; the//go:embeddirective is extended to includestatic/vendor/*.js,static/fonts/*.css, andstatic/fonts/*.woff2.Fix a 400 surfaced by exercising the dashboard offline
With audit logging disabled (
LOGGING_ENABLEDis off by default), the Audit Logs page failed with400 "invalid limit, expected positive integer". The disabled-reader fast paths for/admin/audit/logand/admin/usage/logreturnedlimit:0; the dashboard reuses the returnedlimitas the next request'slimitparam, so the follow-up request sentlimit=0, which validation rejects. Both fast paths now echo the requestedlimit/offset, matching the enabled-reader contract (which clampslimitto a positive value). The pages now load cleanly with their readers off, showing an empty list instead of erroring.Tests
dashboard_test.go:TestIndex_HasNoExternalResources(page fetches nohttp(s)resources) andTestStatic_ServesVendoredAssets(vendored libs + fonts are embedded and served).dashboard-layout.test.cjs: updated to assert local font/vendor references and the absence of any CDN/preconnect.handler_test.go:TestAuditLog_NilReader/TestUsageLog_NilReadernow assert the echoedlimit.make test-race,make lint, dashboard JS tests, gofmt/imports).🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Documentation