/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ /** * IDS BCF Export Dialog * * Provides a configuration dialog for exporting IDS validation results to BCF. * Options include: * - Topic grouping strategy (per-entity, per-specification, per-requirement) * - Include passing entities * - Include per-entity camera positions (from entity bounds) * - Capture per-entity snapshots (batch render) * - Load into BCF panel after export */ import { useState, useCallback } from 'react'; import { FileBox, Loader2, Camera, Focus, Upload, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Progress } from '@/components/ui/progress'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog'; // ============================================================================ // Types // ============================================================================ export type TopicGrouping = 'per-entity' | 'per-specification' | 'per-requirement'; export interface IDSBCFExportSettings { topicGrouping: TopicGrouping; includePassingEntities: boolean; includeCamera: boolean; includeSnapshots: boolean; loadIntoBcfPanel: boolean; } export interface IDSExportProgress { phase: 'building' | 'snapshots' | 'writing' | 'done'; current: number; total: number; message: string; } interface IDSExportDialogProps { /** Trigger element (e.g., a button) — only used for uncontrolled mode */ trigger?: React.ReactNode; /** Whether a report is available */ hasReport: boolean; /** Total failing entity count for display */ failedCount: number; /** Called when export is confirmed */ onExport: (settings: IDSBCFExportSettings) => Promise; /** Export progress (controlled externally) */ progress: IDSExportProgress | null; /** Controlled open state (if provided, dialog is controlled externally) */ open?: boolean; /** Controlled open state callback */ onOpenChange?: (open: boolean) => void; } // ============================================================================ // Component // ============================================================================ export function IDSExportDialog({ trigger, hasReport, failedCount, onExport, progress, open: controlledOpen, onOpenChange: controlledOnOpenChange, }: IDSExportDialogProps) { const [internalOpen, setInternalOpen] = useState(false); const open = controlledOpen ?? internalOpen; const setOpen = controlledOnOpenChange ?? setInternalOpen; const [settings, setSettings] = useState({ topicGrouping: 'per-entity', includePassingEntities: false, includeCamera: true, includeSnapshots: false, loadIntoBcfPanel: false, }); const isExporting = progress !== null && progress.phase !== 'done'; const handleExport = useCallback(async () => { await onExport(settings); // Don't close — let the progress indicator finish, then user closes }, [onExport, settings]); const handleOpenChange = useCallback((value: boolean) => { // Don't allow closing during export if (isExporting) return; setOpen(value); }, [isExporting, setOpen]); const progressPercent = progress && progress.total > 0 ? Math.round((progress.current / progress.total) * 100) : 0; return ( {trigger && ( {trigger} )} Export IDS Report as BCF Create BCF topics from IDS validation failures. {failedCount > 0 && ` ${failedCount} failing entities found.`}
{/* Topic Grouping */}

{settings.topicGrouping === 'per-entity' && 'One topic per failing entity. Failed requirements listed as comments.'} {settings.topicGrouping === 'per-specification' && 'One topic per failing specification. Entities listed as comments.'} {settings.topicGrouping === 'per-requirement' && 'One topic per failed requirement per entity (most granular).'}

{/* Include Passing */}

Add topics for entities that passed validation

setSettings(s => ({ ...s, includePassingEntities: v }))} disabled={isExporting || settings.topicGrouping !== 'per-entity'} />
{/* Include Camera */}

Compute camera framing each entity from its bounding box

setSettings(s => ({ ...s, includeCamera: v }))} disabled={isExporting} />
{/* Include Snapshots */}

Render a screenshot for each entity (slow for large reports)

setSettings(s => ({ ...s, includeSnapshots: v }))} disabled={isExporting} />
{/* Load into BCF Panel */}

Open the BCF panel with exported topics after export

setSettings(s => ({ ...s, loadIntoBcfPanel: v }))} disabled={isExporting} />
{/* Progress */} {progress && (
{progress.message} {progress.current}/{progress.total}
)}
); }