mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
## Context Another take on [this PR](https://github.com/supabase/supabase/pull/50733), decided that it's better UX + DX to use a PDF library (`@react-pdf/renderer`) instead for handling exporting Notebooks to PDF. The previous method using `print` involved a lot of sparse patching in various places + had a lot of limitations, not to mention its awkward UX to "Print". There's a lot of code changes in this PR but it's because we're constructing the PDF document based on the notebook's contents using primitives from `@react-pdf/renderer` which gives us a lot more control over the PDF's output. PDF output will differ slightly from the Notebook UI in the browser - Added a custom header in the report which covers the notebook name + project name, and when its exported - Empty markdown cells are skipped - Query cells will show both SQL content + results (either table or chart) - Opting to skip syntax highlighting for SQL content (Can consider separately) - Results will only be included in the PDF if the notebook's been run (Aligns with Copy as Markdown CTA) - For table results, _all_ rows will be rendered (Aligns with Copy as Markdown CTA) Feel free to give it a spin! 🙂 🙏 <img width="248" height="207" alt="image" src="https://github.com/user-attachments/assets/e38c14ba-7ee8-40ce-99b1-fa126453bf0f" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added an “Export as PDF” option for notebooks. - PDFs include notebook details, Markdown content, SQL queries, query results, tables, and charts. - Query exports show errors, empty results, row counts, and applicable row limits. - Export progress is displayed while the PDF is generated, and failures are reported via notifications. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
51 lines
1.4 KiB
TypeScript
51 lines
1.4 KiB
TypeScript
import { Text, View } from '@react-pdf/renderer'
|
|
import type { ReactElement } from 'react'
|
|
|
|
import { pdfStyles } from './theme'
|
|
import { formatCellValue } from '@/components/ui/DataGridResults/DataGridResults.utils'
|
|
|
|
interface NotebookPdfTableProps {
|
|
rows: readonly Record<string, unknown>[]
|
|
}
|
|
|
|
export function NotebookPdfTable({ rows }: NotebookPdfTableProps): ReactElement | null {
|
|
const columns = Object.keys(rows[0] ?? {})
|
|
if (columns.length === 0) return null
|
|
|
|
return (
|
|
<View style={pdfStyles.table}>
|
|
<View style={pdfStyles.tableHeaderRow}>
|
|
{columns.map((column) => (
|
|
<Text key={column} style={pdfStyles.tableHeaderCell}>
|
|
{column}
|
|
</Text>
|
|
))}
|
|
</View>
|
|
{rows.map((row, rowIndex) => (
|
|
<View
|
|
key={rowIndex}
|
|
style={
|
|
rowIndex === rows.length - 1
|
|
? [pdfStyles.tableRow, pdfStyles.tableRowLast]
|
|
: pdfStyles.tableRow
|
|
}
|
|
wrap={false}
|
|
>
|
|
{columns.map((column) => {
|
|
const value = row[column]
|
|
return value === null ? (
|
|
<Text key={column} style={pdfStyles.tableCellNull}>
|
|
NULL
|
|
</Text>
|
|
) : (
|
|
<Text key={column} style={pdfStyles.tableCell}>
|
|
{formatCellValue(value)}
|
|
</Text>
|
|
)
|
|
})}
|
|
</View>
|
|
))}
|
|
</View>
|
|
)
|
|
}
|