vanta-auditor-tui
Version:
Beautiful terminal UI for exporting Vanta audit evidence with ZIP support and progress tracking
99 lines • 4.59 kB
JavaScript
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