TenantAtlas/specs/002-filament-json/research.md

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.css
  • vendor/pepperfm/filament-json/resources/css/index.css
  • vendor/pepperfm/filament-json/resources/dist/filament-json.css
  • vendor/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:upgrade hook)
  • Size is minimal (~12 KB total)
  • No manual publishing required in normal workflow

Recommendations

  1. Commit the published assets: Since they're small (12 KB) and auto-generated, committing them ensures consistent deployment without requiring build steps.

  2. Alternative (for cleaner git history): Add to .gitignore and ensure deployment runs:

    php artisan filament:upgrade
    

    However, this adds a deployment step dependency.

  3. 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:

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

  1. ViewEntry with custom view:

    ViewEntry::make('snapshot')
        ->view('filament.infolists.entries.json-viewer')
    
  2. Custom infolist entry class:

    JsonEntry::make('snapshot')
        ->collapsible()
    
  3. 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:

  1. Small size: ~12 KB total (negligible git impact)
  2. Deployment simplicity: No build steps required
  3. Consistency: All deployments use identical assets
  4. Dokploy compatibility: VPS deployment doesn't need composer post-hooks
  5. 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

  1. Complete T004-T005: Package feature investigation
  2. Proceed to T006: Create quickstart.md with usage examples
  3. 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 TextEntry with HTML formatting
  • Browser native find (Cmd+F) for search functionality
  • Filament's built-in copyable() for clipboard (no custom JS)

Rationale:

  1. Package is table-column only (incompatible with infolists)
  2. Simple approach meets all FR/NFR requirements
  3. Faster implementation, zero external dependencies
  4. Easier to customize and maintain

Manual QA Checklist

Before marking Phase 3 complete, verify:

  1. Navigate to /admin/policies/{id} with snapshot data
  2. "Policy Snapshot (JSON)" section renders with formatted JSON
  3. Copy button copies full JSON to clipboard
  4. Success message "JSON copied to clipboard!" appears
  5. Section is collapsible (can expand/collapse)
  6. Dark mode toggle → verify background/text colors
  7. Browser find (Cmd+F) highlights text within JSON
  8. Large payload (>500 KB) shows warning badge
  9. Large payload auto-collapses section by default

Next: Phase 4 (T013-T015) will add tabs for Settings Catalog policies (User Story 2)