ExportTab.tsx raw

   1  import { useState } from 'react'
   2  import { useNostr } from '@/providers/NostrProvider'
   3  import { useRelayAdmin } from '@/providers/RelayAdminProvider'
   4  import relayAdmin from '@/services/relay-admin.service'
   5  import { Button } from '@/components/ui/button'
   6  import { toast } from 'sonner'
   7  
   8  export default function ExportTab() {
   9    const { pubkey } = useNostr()
  10    const { isAdmin, isOwner } = useRelayAdmin()
  11    const [isExporting, setIsExporting] = useState(false)
  12  
  13    const downloadBlob = (blob: Blob, filename: string) => {
  14      const url = URL.createObjectURL(blob)
  15      const a = document.createElement('a')
  16      a.href = url
  17      a.download = filename
  18      a.click()
  19      URL.revokeObjectURL(url)
  20    }
  21  
  22    const exportMyEvents = async () => {
  23      if (!pubkey) return
  24      setIsExporting(true)
  25      try {
  26        const blob = await relayAdmin.exportEvents([pubkey])
  27        downloadBlob(blob, `my-events-${Date.now()}.jsonl`)
  28        toast.success('Export complete')
  29      } catch (e) {
  30        toast.error(`Export failed: ${e instanceof Error ? e.message : String(e)}`)
  31      } finally {
  32        setIsExporting(false)
  33      }
  34    }
  35  
  36    const exportAllEvents = async () => {
  37      setIsExporting(true)
  38      try {
  39        const blob = await relayAdmin.exportEvents()
  40        downloadBlob(blob, `all-events-${Date.now()}.jsonl`)
  41        toast.success('Export complete')
  42      } catch (e) {
  43        toast.error(`Export failed: ${e instanceof Error ? e.message : String(e)}`)
  44      } finally {
  45        setIsExporting(false)
  46      }
  47    }
  48  
  49    return (
  50      <div className="space-y-4 p-4 max-w-lg">
  51        {pubkey && (
  52          <div className="rounded-lg bg-card p-4 space-y-3">
  53            <h3 className="text-lg font-semibold">Export My Events</h3>
  54            <p className="text-sm text-muted-foreground">
  55              Download your personal events as a JSONL file.
  56            </p>
  57            <Button onClick={exportMyEvents} disabled={isExporting}>
  58              {isExporting ? 'Exporting...' : 'Export My Events'}
  59            </Button>
  60          </div>
  61        )}
  62        {(isAdmin || isOwner) && (
  63          <div className="rounded-lg bg-card p-4 space-y-3">
  64            <h3 className="text-lg font-semibold">Export All Events</h3>
  65            <p className="text-sm text-muted-foreground">
  66              Download the complete database as a JSONL file. This includes all events from all
  67              users.
  68            </p>
  69            <Button onClick={exportAllEvents} disabled={isExporting}>
  70              {isExporting ? 'Exporting...' : 'Export All Events'}
  71            </Button>
  72          </div>
  73        )}
  74      </div>
  75    )
  76  }
  77