Skip to content

POC: Add PDF Export for Run Reports#2145

Draft
calebroseland wants to merge 6 commits intomasterfrom
poc/run-report-pdf-export
Draft

POC: Add PDF Export for Run Reports#2145
calebroseland wants to merge 6 commits intomasterfrom
poc/run-report-pdf-export

Conversation

@calebroseland
Copy link
Member

@calebroseland calebroseland commented Nov 5, 2025

Summary

Status: POC with very rough edges

CleanShot 2025-11-05 at 14 33 15 CleanShot 2025-11-05 at 14 33 28

Incident_ Test Incident-report-2025-11-05 (1).pdf

Comprehensive PDF export functionality for playbook run reports, allowing users to generate professional documentation of completed runs for post-mortems, compliance, or stakeholder communication.

Key Features

📄 Flexible Export Options

  • Customizable Sections: Users can select which sections to include
    • Cover page with run metadata
    • Executive summary
    • Timeline of key events
    • Status updates
    • Checklists & tasks with enhanced visual status
    • Retrospective with metrics
    • Complete chat log with thread grouping and time filtering

📊 Professional Formatting

  • Clean, branded PDF layout using @react-pdf/renderer v4.2.0
  • Table of contents with dynamic section listing
  • Consistent Mattermost brand styling (#1c58d9)
  • Page numbering throughout

✅ Enhanced Task Presentation

  • Clear visual status indicators (☑ DONE / ☐ TODO)
  • Color-coded borders (green=completed, gray=pending)
  • Status badges with background colors
  • Assignee names resolved (not just IDs)
  • Task descriptions displayed
  • Due dates and metadata with emoji icons (👤 📅)
  • Completion percentage per checklist

💬 Chat Log with Threading

  • Thread-aware display: Posts grouped by conversation threads
  • Time-filtered: Only includes messages during the run's lifetime (prevents mixing runs in shared channels)
  • Visual hierarchy with indented replies and left border
  • Reply indicators (↳) for clarity
  • Statistics showing thread count vs reply count
  • Chronologically sorted within threads

Backend Implementation

API Endpoints

  • New endpoint: GET /runs/{id}/export-data with permission checks
  • Returns comprehensive data: run metadata, status updates, participants, owner, channel, team, and time-filtered chat posts

Data Fetching

  • GetPlaybookRunExportData service method aggregates data from multiple sources
  • Channel membership verification before fetching chat posts (security)
  • Efficient time-based filtering using GetPostsSince API
  • Posts filtered by: startTime <= post.CreateAt <= endTime
  • Handles ongoing runs (EndAt = 0) by using current time

Security & Permissions

  • RunView permission check at API level
  • Channel membership verification per user
  • Graceful degradation if user lacks channel access
  • Comprehensive error logging

Frontend Implementation

Components Structure

run_report/
├── index.ts
├── types.ts
├── styles.ts
├── export_options_modal.tsx
├── report_document.tsx
├── table_of_contents.tsx
├── cover_page.tsx
├── executive_summary.tsx
├── timeline_section.tsx
├── status_updates_section.tsx
├── checklists_section.tsx
├── retrospective_section.tsx
└── chat_log_section.tsx

Key Improvements

  • Retrospective section: Fixed to use correct data structure (run.retrospective string, run.metrics_data array)
  • Table of contents: Dynamic generation based on enabled sections
  • Thread support: Added root_id to type definitions for proper threading
  • User resolution: Display names shown instead of user IDs throughout

Technical Details

PDF Generation

  • All generation happens client-side
  • Async data fetching with error handling
  • Null-safe throughout (graceful handling of missing data)

Performance

  • Efficient API usage with GetPostsSince for time-range queries
  • Pagination removed in favor of targeted time-based fetching
  • Reduced data transfer for channels with long histories

Bug Fixes

  • Fixed ChunkLoadError by removing lazy loading (static imports)
  • Added eslint override for error logging
  • Removed unused isLoading state
  • Fixed retrospective data structure mismatch

Testing Checklist

  • Verify export button appears in run context menu
  • Test modal opens and loads data correctly
  • Verify all sections render properly in PDF
  • Test table of contents reflects selected sections
  • Verify chat log shows only posts from run timeframe
  • Test thread grouping displays correctly
  • Verify task status indicators are clear
  • Test with runs missing optional data (no retrospective, etc.)
  • Check permissions enforcement on API endpoint
  • Verify chat log respects channel membership
  • Test with ongoing runs (EndAt = 0)
  • Test with channels reused across multiple runs
  • Verify PDF downloads with correct filename

Future Enhancements

  • AI-generated executive summary based on run data
  • Custom branding/logo options
  • Additional export formats (CSV, Markdown)
  • Batch export for multiple runs
  • Export scheduling/automation

Migration Notes

  • Breaking change: GetPlaybookRunExportData signature now includes userID parameter
  • New dependency: @react-pdf/renderer v4.2.0
  • New field: ChatPosts in PlaybookRunExportData struct
  • New field: root_id in StatusPostComplete interface

🤖 Generated with Claude Code

Adds comprehensive PDF export functionality for playbook run reports,
allowing users to generate professional documentation of completed runs.

**Backend Changes:**
- Add /runs/{id}/export-data API endpoint with permissions check
- Implement GetPlaybookRunExportData service method
- Create PlaybookRunExportData struct with run metadata, status updates,
  participants, owner, channel, and team information

**Frontend Changes:**
- Add @react-pdf/renderer dependency for PDF generation
- Create modular report components (cover page, executive summary,
  timeline, status updates, checklists, retrospective)
- Add export options modal for section selection
- Integrate export menu item in run context menu
- Add client API method for fetching export data

**UI Components:**
- ExportOptionsModal: Section selection interface
- ReportDocument: Main PDF layout orchestrator
- Multiple section components with consistent styling
- Support for customizable section inclusion

**Technical Details:**
- Fix ChunkLoadError by removing lazy loading
- Add eslint override for error logging
- Handle null data gracefully during async fetch
- Comprehensive error handling and logging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@calebroseland calebroseland changed the title [POC] Add PDF Export for Run Reports POC: Add PDF Export for Run Reports Nov 5, 2025
calebroseland and others added 5 commits November 5, 2025 12:55
**Bug Fix:**
- Fix retrospective section accessing wrong data structure
  - Changed from `retrospective.text` to `run.retrospective` (string)
  - Changed from `retrospective.metrics` to `run.metrics_data` (array)
- Add null handling for metric values with String() conversion

**Enhancement:**
- Add professional table of contents page after cover page
- TOC dynamically lists enabled sections only
- Clean design with Mattermost branding
- Includes sub-items for retrospective (Summary, Metrics)
- Consistent styling with divider lines and indentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Implements full channel chat log export for run reports with proper
permission checks and pagination.

**Backend Changes:**
- Add ChatPosts field to PlaybookRunExportData struct
- Update GetPlaybookRunExportData signature to include userID parameter
- Implement channel member permission check before fetching posts
- Add paginated fetching of all channel posts (200 per page)
- Gracefully handle permission errors (returns empty array)

**Frontend Changes:**
- Create ChatLogSection component with chronological post display
- Show user display names (first/last name fallback to username)
- Format timestamps in readable format
- Display post type indicators for system messages
- Include total post count at end
- Enable chat log option in export modal (previously disabled)

**Security:**
- Verify user is channel member via GetMember before fetching posts
- Log permission failures without breaking entire export
- Respect existing RunView permission check at API level

**Performance:**
- Efficient pagination with 200 posts per page
- Early break on API errors
- Sorted chronologically (oldest first) for natural reading

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
**Chat Log Improvements:**
- Group posts by threads using Post.RootId field
- Show replies indented with left border (Mattermost blue)
- Add reply indicator (↳) before usernames
- Sort threads chronologically with replies in order
- Display thread count vs reply count in footer
- Update description to mention thread grouping

**Checklist/Task Improvements:**
- Add clear visual status indicators (☑ DONE / ☐ TODO)
- Color-coded left borders (green=done, gray=todo)
- Status badges with background colors
- Resolve assignee IDs to display names (first/last name or username)
- Show task descriptions in italic style
- Add emoji icons for assignee (👤) and due date (📅)
- Display completion percentage per checklist
- Better spacing and visual hierarchy

**Type Updates:**
- Add root_id field to StatusPostComplete interface
- Enables proper thread detection in frontend

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Prevents exporting posts from other runs when a channel is reused
for multiple playbook runs.

**Changes:**
- Use GetPostsSince API with run's CreateAt timestamp for efficiency
- Filter posts to only include those between run start and end
- Handle ongoing runs (EndAt = 0) by using current time as end
- Add logging for post count and time range

**Before:** Exported ALL posts from channel history
**After:** Only posts created during the specific run's lifetime

**Time Range:**
- Start: playbookRun.CreateAt
- End: playbookRun.EndAt (or current time if run still active)

**Benefits:**
- Accurate conversation history per run
- Prevents mixing conversations from different runs
- More efficient API usage with GetPostsSince
- Better performance on long-lived channels

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…atText utility

Adds proper markdown rendering to PDF exports using Mattermost's
existing formatText utility, then converting HTML to PDF components.

**Markdown Support:**
- Uses `formatText` from webapp_globals (Mattermost's markdown parser)
- Converts HTML output to @react-pdf/renderer components
- Supports: **bold**, *italic*, `code`, links, code blocks, line breaks

**Applied To:**
- Chat log messages
- Status update messages
- Retrospective summaries
- Task descriptions

**Implementation:**
- Created MarkdownText component that wraps formatText
- HTML-to-PDF converter handles common tags (strong, em, code, a, pre)
- HTML entity decoding (&lt;, &gt;, &amp;, &quot;)
- Code blocks with monospace font and styled background
- Inline code with Mattermost red color (#e01e5a)
- Links with Mattermost blue (#1c58d9) and underline

**Benefits:**
- Consistent markdown parsing with main Mattermost app
- Properly formatted messages in PDF exports
- Rich text content preserved from markdown source

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant