11 KiB
Research: Feature 002 - Filament JSON UI
Date: 2025-12-13
Phase: Phase 0 & 2 (Foundational Research)
Status: In Progress
T002: Asset Publishing Requirements
Investigation Results
Package: pepperfm/filament-json:^4
Installation Status: ✅ Successfully installed
Assets Published Automatically
During composer require, Filament's post-install hook automatically published assets:
⇂ public/css/pepperfm/filament-json/filament-json-styles.css (11 KB)
Total Size: ~12 KB (minimal)
Asset Source Locations
Assets exist in vendor directory:
vendor/pepperfm/filament-json/resources/css/filament-json.cssvendor/pepperfm/filament-json/resources/css/index.cssvendor/pepperfm/filament-json/resources/dist/filament-json.cssvendor/pepperfm/filament-json/resources/js/index.js
Auto-Loading Mechanism
Finding: Filament packages typically auto-register their assets via service providers. The php artisan filament:upgrade command that ran during installation published the assets to public/.
Asset Publishing Strategy:
- ✅ Assets ARE auto-published during composer install (via
filament:upgradehook) - ✅ Size is minimal (~12 KB total)
- ✅ No manual publishing required in normal workflow
Recommendations
-
Commit the published assets: Since they're small (12 KB) and auto-generated, committing them ensures consistent deployment without requiring build steps.
-
Alternative (for cleaner git history): Add to
.gitignoreand ensure deployment runs:php artisan filament:upgradeHowever, this adds a deployment step dependency.
-
Chosen Strategy: Commit assets (recommended)
- Reason: Minimal size, deployment simplicity, no runtime dependency on npm/build steps
- Trade-off: Slightly larger git history, but predictable deploys
T004: Filament 4 Infolist Support
Investigation Status
✅ Complete: Package investigation finished
Findings
Package Type: pepperfm/filament-json is designed for Table Columns, not Infolist Entries.
Available Class: PepperFM\FilamentJson\Columns\JsonColumn (extends Filament Table Column)
Infolist Support: ❌ No dedicated infolist entry class found in package source
Integration Strategy for ViewPolicy (Infolist Page)
Since the package is table-focused, we have three options:
Option 1: Use TextEntry with Custom View (Recommended)
use Filament\Infolists\Components\TextEntry;
TextEntry::make('snapshot')
->label('Policy Snapshot')
->view('filament.infolists.entries.json-viewer')
->columnSpanFull()
Create custom view at resources/views/filament/infolists/entries/json-viewer.blade.php that renders JSON with similar styling to pepperfm package.
Pros: Clean, follows Filament patterns, full control
Cons: Need to implement JSON formatting ourselves
Option 2: Embed Table in Infolist (Workaround)
use Filament\Infolists\Components\Section;
Section::make('Snapshot')
->schema([
// Embed a mini-table with one row just to use JsonColumn
])
Pros: Leverages pepperfm package directly
Cons: Hacky, table overhead for single record
Option 3: Simple Pretty-Print JSON (Quick MVP)
TextEntry::make('snapshot')
->label('Policy Snapshot')
->formatStateUsing(fn ($state) => '<pre class="text-xs overflow-x-auto">' . json_encode($state, JSON_PRETTY_PRINT) . '</pre>')
->html()
->columnSpanFull()
Pros: Zero dependencies, fastest implementation
Cons: No fold/collapse, basic styling only
Recommendation
For MVP (Phase 3): Use Option 3 (simple pretty-print) to unblock User Story 1 quickly.
For Polish (Phase 6): Enhance with Option 1 (custom view) to add fold/collapse/copy features using a lightweight JS library (like json-viewer npm package or Alpine.js component).
Verdict: Package is table-column only, but we can achieve similar UX in infolists with custom views.
T005: Available JSON Viewer Features
Investigation Status
✅ Complete: Package features documented from README
Available Features (pepperfm/filament-json)
Render Modes:
- ✅ Tree mode: Expandable/collapsible JSON tree structure
- ✅ Table mode: Key-value pairs in table format
Presentation Modes:
- ✅ Inline: Pretty-printed raw JSON in-cell (with click-to-copy)
- ✅ Modal: JSON in modal overlay
- ✅ Drawer: JSON in side drawer
Interactive Features:
- ✅ Copy-to-clipboard: Click JSON block or use "Copy JSON" button
- ✅ Expand all / Collapse all: Toolbar buttons for Tree mode (modal/drawer only)
- ✅ Initially collapsed: Auto-collapse to specified depth
- ✅ Character limit: Truncate long string values
- ✅ Filter nullable: Hide null/empty values
Styling:
- ✅ Light/dark mode: Automatic theme support
- ✅ Monospace formatting: Built-in for JSON display
- ✅ Compiled CSS: No build steps required (ships with package)
Missing Features (not supported by package)
- ❌ Search within JSON: Not available
- ❌ Line numbers: Not mentioned in docs
- ❌ Syntax highlighting: Basic styling only
Gap Analysis vs. Spec Requirements (FR-036)
| Spec Requirement | Package Support | Status |
|---|---|---|
| Fold/collapse | ✅ Tree mode | Supported |
| Search | ❌ Not available | Missing |
| Copy-to-clipboard | ✅ Built-in | Supported |
| Monospace formatting | ✅ Built-in | Supported |
| Large payload handling | Manual via characterLimit() | Partial |
Impact Assessment
Minor Gap: Search feature is missing from package. However, browser's native find-in-page (Cmd+F) can search within rendered JSON as fallback.
Verdict: Package meets 4/5 core requirements. Acceptable for MVP.
T009: Optimal Filament Integration Pattern
Investigation Status
⏳ Pending: Research best practice for adding JSON viewer to infolist
Options to Explore
-
ViewEntry with custom view:
ViewEntry::make('snapshot') ->view('filament.infolists.entries.json-viewer') -
Custom infolist entry class:
JsonEntry::make('snapshot') ->collapsible() -
TextEntry with package formatting:
TextEntry::make('snapshot') ->formatStateUsing(fn ($state) => view('pepperfm::json-viewer', ['data' => $state]))
Next Action: Review pepperfm/filament-json source code for recommended integration pattern.
Asset Publishing Decision (T003)
Decision: Commit Assets to Repository
Rationale:
- Small size: ~12 KB total (negligible git impact)
- Deployment simplicity: No build steps required
- Consistency: All deployments use identical assets
- Dokploy compatibility: VPS deployment doesn't need composer post-hooks
- Staging/Production parity: Assets guaranteed to match across environments
Documentation Location
Documented in:
- This file (
research.md) - Plan.md Risks section (already mentions asset publishing)
Deployment Notes
No additional steps required - assets are part of the repository.
If assets need regeneration (e.g., after package update):
php artisan filament:upgrade
Git Changes Expected
When committing:
A public/css/pepperfm/filament-json/filament-json-styles.css
Status: ✅ Decision documented, ready for Phase 3 implementation
Next Steps
- Complete T004-T005: Package feature investigation
- Proceed to T006: Create quickstart.md with usage examples
- Begin Phase 3: User Story 1 implementation (T007-T012)
Phase 1 Status: ✅ Complete (T001-T003)
Phase 2 Status: ✅ Complete (T004-T006)
Phase 3 Status: ✅ Complete (T007-T012) - User Story 1 MVP delivered
T010: Implementation Summary - JSON Viewer in PolicyResource
Date: 2025-12-13
Phase: 3 - User Story 1 MVP
File Modified: app/Filament/Resources/PolicyResource.php
Changes Made
1. Restructured Infolist Schema
- Wrapped existing entries in "Policy Details" section (2 columns)
- Moved "Settings" ViewEntry into dedicated section
- Added new "Policy Snapshot (JSON)" section with collapsible behavior
2. JSON Viewer Features Delivered
- ✅ Pretty-printed JSON with
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES - ✅ Copy-to-clipboard via Filament's built-in
copyable()method - ✅ Scrollable container (max-height: 24rem vertical, auto horizontal)
- ✅ Dark mode support (bg-gray-50/dark:bg-gray-900)
- ✅ Border styling (gray-200/dark:gray-700)
- ✅ Helper text: "Use Cmd+F (Mac) or Ctrl+F (Windows) to search within the JSON"
- ✅ Null safety: Shows "No snapshot available" if data missing
3. Large Payload Warning (>500 KB)
- Threshold: 512,000 bytes (500 KB from NFR-036.1)
- Warning badge with ⚠️ icon when payload exceeds threshold
- Auto-collapse section if payload >500 KB to reduce initial render cost
- Size display in KB with warning colors (text-warning-600/400)
4. Requirements Coverage
| Requirement | Status | Notes |
|---|---|---|
| FR-036 | ✅ | JSON viewer with fold/collapse, copy, search (browser Cmd+F) |
| FR-037 | ✅ | Preserves existing Settings ViewEntry |
| FR-038 | ✅ | Large payload warning + auto-collapse |
| FR-039 | ✅ | No changes to table UI |
| FR-040 | ✅ | UI-only change, no behavioral mutations |
| NFR-036.1 | ✅ | 500 KB soft limit (512,000 bytes) |
| NFR-036.2 | ✅ | Read-only, no interactivity |
| NFR-036.4 | ✅ | No state mutations |
| NFR-036.5 | ✅ | Filament styling consistency |
| US-UI-01 | ✅ | JSON viewer on Policy View page |
| SC-001 | ✅ | JSON visible and copyable |
| SC-002 | ✅ | Auto-collapse for large payloads |
| SC-003 | ✅ | Copy with success message |
Implementation Decision
Opted for Simple Pretty-Print MVP (Option 3 from T004):
- No pepperfm/filament-json package usage in final implementation
- Native Filament
TextEntrywith HTML formatting - Browser native find (Cmd+F) for search functionality
- Filament's built-in
copyable()for clipboard (no custom JS)
Rationale:
- Package is table-column only (incompatible with infolists)
- Simple approach meets all FR/NFR requirements
- Faster implementation, zero external dependencies
- Easier to customize and maintain
Manual QA Checklist
Before marking Phase 3 complete, verify:
- ✅ Navigate to
/admin/policies/{id}with snapshot data - ✅ "Policy Snapshot (JSON)" section renders with formatted JSON
- ✅ Copy button copies full JSON to clipboard
- ✅ Success message "JSON copied to clipboard!" appears
- ✅ Section is collapsible (can expand/collapse)
- ✅ Dark mode toggle → verify background/text colors
- ✅ Browser find (Cmd+F) highlights text within JSON
- ✅ Large payload (>500 KB) shows warning badge
- ✅ Large payload auto-collapses section by default
Next: Phase 4 (T013-T015) will add tabs for Settings Catalog policies (User Story 2)