UNPKG

vanta-auditor-tui

Version:

Beautiful terminal UI for exporting Vanta audit evidence with ZIP support and progress tracking

99 lines 4.59 kB
import React, { useState } from 'react'; import { Box, Text } from 'ink'; import { SelectInput } from '../lib/inkModules.js'; import figures from 'figures'; import { theme } from '../theme.js'; export function AuditTable({ audits, onSelect }) { const [useTable] = useState(true); // Can toggle between table and list view if (audits.length === 0) { return (React.createElement(Box, { flexDirection: "column", paddingY: 1 }, React.createElement(Text, { color: theme.colors.warning }, figures.warning, " No audits found"), React.createElement(Text, { color: theme.colors.dim }, "Please check your credentials and try again."))); } if (useTable && audits.length > 1) { // Custom table view for multiple audits return (React.createElement(Box, { flexDirection: "column", paddingY: 1 }, React.createElement(Text, { color: theme.colors.primary, bold: true }, "\uD83E\uDD99 Select an audit to export:"), React.createElement(Box, { marginTop: 1, marginBottom: 1 }, React.createElement(Box, { width: 30 }, React.createElement(Text, { color: theme.colors.dim, bold: true }, "Client")), React.createElement(Box, { width: 20 }, React.createElement(Text, { color: theme.colors.dim, bold: true }, "Framework")), React.createElement(Box, { width: 15 }, React.createElement(Text, { color: theme.colors.dim, bold: true }, "Status"))), React.createElement(Text, { color: theme.colors.dim }, '─'.repeat(65)), audits.map((audit) => (React.createElement(Box, { key: audit.id, marginY: 0 }, React.createElement(Box, { width: 30 }, React.createElement(Text, { color: theme.colors.text }, audit.name?.split(' - ')[0] || 'Unknown')), React.createElement(Box, { width: 20 }, React.createElement(Text, { color: theme.colors.text }, audit.framework || '-')), React.createElement(Box, { width: 15 }, React.createElement(Text, { color: getStatusColor(audit.status) }, getStatusDisplay(audit.status)))))), React.createElement(Box, { flexDirection: "column", marginTop: 1 }, React.createElement(Text, { color: theme.colors.dim }, "Use arrow keys to navigate, Enter to select:"), React.createElement(SelectInput, { items: audits.map(a => ({ label: formatAuditLabel(a), value: a.id })), onSelect: item => onSelect(item.value) })))); } // List view (fallback or single audit) return (React.createElement(Box, { flexDirection: "column", paddingY: 1 }, React.createElement(Text, { color: theme.colors.purple, bold: true }, "\uD83E\uDD99 Select an audit to export:"), React.createElement(Box, { marginTop: 1 }, React.createElement(SelectInput, { items: audits.map(audit => ({ label: formatAuditLabel(audit), value: audit.id })), onSelect: item => onSelect(item.value) })))); } function getStatusDisplay(status) { if (!status) return '-'; switch (status.toLowerCase()) { case 'active': return `${figures.circle} Active`; case 'completed': return `${figures.tick} Completed`; case 'expired': return `${figures.cross} Expired`; default: return status; } } function getStatusColor(status) { if (!status) return theme.colors.dim; switch (status.toLowerCase()) { case 'active': return theme.colors.success; case 'completed': return theme.colors.primary; case 'expired': return theme.colors.error; default: return theme.colors.text; } } function formatAuditLabel(audit) { const parts = []; // Add status indicator if (audit.status) { switch (audit.status.toLowerCase()) { case 'active': parts.push(`[${figures.circle}]`); break; case 'completed': parts.push(`[${figures.tick}]`); break; case 'expired': parts.push(`[${figures.cross}]`); break; } } // Add name or ID parts.push(audit.name || audit.id); return parts.join(' '); } export default AuditTable; //# sourceMappingURL=AuditTable.js.map