import { beginActivity, showActivityFrame } from '../../platform/activity-store'; import { useState } from 'react'; import { useApp } from '../../app/AppProvider'; import { Dialog } from '../../components/Dialog/Dialog'; import { buildWorkViewExport, renderWorkViewCsv, renderWorkViewHtml, renderWorkViewMarkdown } from '../../exports/work-view-export'; import { downloadText } from '../../exports/text-download'; import { browserDownloadAdapter } from '../../platform/browser/browser-download-adapter'; import { useFilteredRecords } from '../search-filter/use-filtered-records'; import { selectWorkFacets } from '../search-filter/work-facets'; import { useContextClusterIndex } from '../context-layer/use-context-cluster-index'; import { useRelatedFindings } from '../related-findings/RelatedFindings'; import { useWorkPackages } from '../../remediation/use-work-packages'; import { WorkPackagesWindow } from '../../remediation/WorkPackagesWindow'; import { UNASSIGNED_WORK_PACKAGE, WORK_PACKAGE_FACET_ID } from '../../remediation/remediation-engine'; import { numberedClusterLabel, publishedClusterColour } from '../sidebar/context-cluster-display'; import { useComplianceWorkFacets } from '../../compliance/ui/compliance-work-facets'; export function ActionlistControls() { const app = useApp(); const records = useFilteredRecords(); const contextClusters = useContextClusterIndex(); const remediation = useWorkPackages(); const related = useRelatedFindings(); const workPackages = remediation.status === 'ready' ? remediation.index : undefined; const packageOverview = remediation.status === 'ready' ? remediation.overview : undefined; const complianceFacets = useComplianceWorkFacets(); const [failed, setFailed] = useState(false); const [packagesOpen, setPackagesOpen] = useState(false); const exportView = async (format: 'csv' | 'md' | 'html') => { if (!app.dataset || !app.activeSheet || !records.length) return; const activity = beginActivity('Core Engine', `Preparing Work ${format.toUpperCase()} export`); try { await showActivityFrame(); const facets = selectWorkFacets(app.activeSheet, { ...app, contextClusters, workPackages, complianceFacets }); const statusLabel = app.activeProfile.presentation.statusFilters.find(filter => filter.value === app.statusFilter)?.label ?? app.statusFilter; const filters = Object.entries(app.facetFilters).map(([id, filter]) => { const facet = facets.find(item => item.id === id); return `${facet?.label ?? id}: ${filter.values?.map(value => facet?.values.find(item => item.value === value)?.label ?? value).join(', ') ?? ''}${filter.minimum ? ` ≥ ${filter.minimum}` : ''}${filter.maximum ? ` ≤ ${filter.maximum}` : ''}`; }); const report = buildWorkViewExport({ dataset: app.dataset, sheet: app.activeSheet, records, generatedAt: new Date().toISOString(), reviews: app.reviews, titleColumn: app.titleColumn, context: [ { label: 'Scope', value: [`Project: ${app.projectId}`, `Assessments: ${app.activeAssessmentIds?.join(', ') ?? 'geladener Workspace'}`, `Scan runs: ${app.activeScanRunIds?.join(', ') ?? 'geladener Workspace'}`].join('\n') }, { label: 'Filter', value: [`Result Status: ${statusLabel}`, ...filters, `Suche: ${app.search || '—'}`, `My Workspace: ${app.actionOnly ? 'Ja' : 'Nein'}`, `Drilldown: ${app.pathFindingIds.length ? `${app.pathFindingIds.length} Record IDs` : 'Nein'}`].join('\n') }, { label: 'Sortierung', value: `${app.sortColumn} · ${app.sortDirection}` } ] }); const text = format === 'html' ? renderWorkViewHtml(report) : format === 'md' ? renderWorkViewMarkdown(report) : renderWorkViewCsv(report, app.delimiter === 'auto' ? ';' : app.delimiter); const stem = app.dataset.fileName.replace(/\.[^.]+$/, '').replace(/[<>:"/\\|?*\u0000-\u001f]/g, '_'); downloadText(browserDownloadAdapter, `${stem}-work-view.${format}`, text, format === 'html' ? 'text/html;charset=utf-8' : format === 'md' ? 'text/markdown;charset=utf-8' : 'text/csv;charset=utf-8'); setFailed(false); } catch { activity.fail(); setFailed(true); } finally { activity.complete(); } }; return
{/* Remediation Engine extension point: packages appear only while the engine is on and its result is ready. */} {workPackages && } {(['csv', 'md', 'html'] as const).map(format => )} {packageOverview && packagesOpen && cluster.id)} clusterLabels={Object.fromEntries(workPackages!.packages.map(p => [p.clusterId, numberedClusterLabel(p.clusterId, p.clusterLabel, contextClusters?.publication.clusters)]))} clusterSeverities={Object.fromEntries(workPackages!.packages.map(p => [p.clusterId, publishedClusterColour(contextClusters?.publication.clusters.find(cluster => cluster.id === p.clusterId))]))} onSelectRelated={() => related?.showAllInWork()} onClose={() => setPackagesOpen(false)} onSelectUnassigned={() => app.setFacetFilter(WORK_PACKAGE_FACET_ID, { values: [UNASSIGNED_WORK_PACKAGE] })} onSelect={workPackage => app.setFacetFilter(WORK_PACKAGE_FACET_ID, { values: [workPackage.id] })}/>} {failed && setFailed(false)}>

The current view could not be exported completely. No partial file was downloaded.

}
; }