Changed color and contrast gradients

This commit is contained in:
2026-02-10 09:54:42 -07:00
parent ba4d16396c
commit 626d0cac3a
2 changed files with 313 additions and 118 deletions

View File

@@ -680,7 +680,7 @@ export default function App() {
</div>
<div className="mb-4 p-3 bg-intel-medium border border-intel-accent/30 rounded">
<p className="text-sm text-gray-300">
<p className="text-sm text-white">
<strong className="text-intel-accent">Tip:</strong> You can add the same CVE-ID multiple times with different vendors.
Each vendor will have its own documents folder.
</p>
@@ -688,7 +688,7 @@ export default function App() {
<form onSubmit={handleAddCVE} className="space-y-4">
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
CVE ID *
</label>
<div className="relative">
@@ -721,7 +721,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
Vendor *
</label>
<input
@@ -736,7 +736,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
Severity *
</label>
<select
@@ -752,7 +752,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
Description *
</label>
<textarea
@@ -766,7 +766,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
Published Date *
</label>
<input
@@ -815,14 +815,14 @@ export default function App() {
</div>
<div className="mb-4 p-3 bg-intel-medium border border-intel-warning/30 rounded">
<p className="text-sm text-gray-300">
<p className="text-sm text-white">
<strong className="text-intel-warning">Note:</strong> Changing CVE ID or Vendor will move associated documents to the new path.
</p>
</div>
<form onSubmit={handleEditCVESubmit} className="space-y-4">
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">CVE ID *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">CVE ID *</label>
<div className="relative">
<input
type="text"
@@ -850,7 +850,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Vendor *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Vendor *</label>
<input
type="text"
required
@@ -861,7 +861,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Severity *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Severity *</label>
<select
value={editForm.severity}
onChange={(e) => setEditForm({...editForm, severity: e.target.value})}
@@ -875,7 +875,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Description *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Description *</label>
<textarea
required
value={editForm.description}
@@ -886,7 +886,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Published Date *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Published Date *</label>
<input
type="date"
required
@@ -897,7 +897,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Status *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Status *</label>
<select
value={editForm.status}
onChange={(e) => setEditForm({...editForm, status: e.target.value})}
@@ -955,7 +955,7 @@ export default function App() {
{!addTicketContext && (
<>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">CVE ID *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">CVE ID *</label>
<input
type="text"
required
@@ -966,7 +966,7 @@ export default function App() {
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Vendor *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Vendor *</label>
<input
type="text"
required
@@ -979,12 +979,12 @@ export default function App() {
</>
)}
{addTicketContext && (
<div className="p-3 bg-intel-medium border border-intel-warning/30 rounded text-sm text-gray-300">
<div className="p-3 bg-intel-medium border border-intel-warning/30 rounded text-sm text-white">
Adding ticket for <strong className="text-intel-warning">{addTicketContext.cve_id}</strong> / <strong className="text-intel-warning">{addTicketContext.vendor}</strong>
</div>
)}
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Ticket Key *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Ticket Key *</label>
<input
type="text"
required
@@ -995,7 +995,7 @@ export default function App() {
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">JIRA URL</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">JIRA URL</label>
<input
type="url"
placeholder="https://jira.company.com/browse/VULN-1234"
@@ -1005,7 +1005,7 @@ export default function App() {
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Summary</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Summary</label>
<input
type="text"
placeholder="Brief description"
@@ -1015,7 +1015,7 @@ export default function App() {
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Status</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Status</label>
<select
value={ticketForm.status}
onChange={(e) => setTicketForm({...ticketForm, status: e.target.value})}
@@ -1051,12 +1051,12 @@ export default function App() {
<XCircle className="w-6 h-6" />
</button>
</div>
<div className="p-3 bg-intel-medium rounded text-sm text-gray-300 mb-4 font-mono">
<div className="p-3 bg-intel-medium rounded text-sm text-white mb-4 font-mono">
{editingTicket.cve_id} / {editingTicket.vendor}
</div>
<form onSubmit={handleUpdateTicket} className="space-y-4">
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Ticket Key *</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Ticket Key *</label>
<input
type="text"
required
@@ -1066,7 +1066,7 @@ export default function App() {
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">JIRA URL</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">JIRA URL</label>
<input
type="url"
value={ticketForm.url}
@@ -1075,7 +1075,7 @@ export default function App() {
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Summary</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Summary</label>
<input
type="text"
value={ticketForm.summary}
@@ -1084,7 +1084,7 @@ export default function App() {
/>
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">Status</label>
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">Status</label>
<select
value={ticketForm.status}
onChange={(e) => setTicketForm({...ticketForm, status: e.target.value})}
@@ -1137,7 +1137,7 @@ export default function App() {
<XCircle className="w-5 h-5 text-intel-danger mt-0.5" />
<div>
<p className="font-medium text-intel-danger font-mono">Error</p>
<p className="text-sm text-gray-400">{quickCheckResult.error}</p>
<p className="text-sm text-gray-300">{quickCheckResult.error}</p>
</div>
</div>
) : quickCheckResult.exists ? (
@@ -1147,12 +1147,12 @@ export default function App() {
<p className="font-medium text-intel-success font-mono"> CVE Addressed ({quickCheckResult.vendors.length} vendor{quickCheckResult.vendors.length > 1 ? 's' : ''})</p>
<div className="mt-3 space-y-3">
{quickCheckResult.vendors.map((vendorInfo, idx) => (
<div key={idx} className="p-3 bg-intel-dark/50 rounded border border-intel-accent/20">
<p className="font-semibold text-gray-200 mb-2 font-sans">{vendorInfo.vendor}</p>
<div className="grid grid-cols-2 gap-2 text-sm text-gray-400 mb-2 font-mono">
<p><strong className="text-gray-300">Severity:</strong> {vendorInfo.severity}</p>
<p><strong className="text-gray-300">Status:</strong> {vendorInfo.status}</p>
<p><strong className="text-gray-300">Documents:</strong> {vendorInfo.total_documents} attached</p>
<div key={idx} className="p-3 bg-intel-dark/70 rounded border border-intel-accent/30 shadow-lg">
<p className="font-semibold text-white mb-2 font-sans">{vendorInfo.vendor}</p>
<div className="grid grid-cols-2 gap-2 text-sm text-gray-300 mb-2 font-mono">
<p><strong className="text-white">Severity:</strong> {vendorInfo.severity}</p>
<p><strong className="text-white">Status:</strong> {vendorInfo.status}</p>
<p><strong className="text-white">Documents:</strong> {vendorInfo.total_documents} attached</p>
</div>
</div>
))}
@@ -1164,7 +1164,7 @@ export default function App() {
<AlertCircle className="w-5 h-5 text-intel-warning mt-0.5" />
<div>
<p className="font-medium text-intel-warning font-mono">Not Found</p>
<p className="text-sm text-gray-400">This CVE has not been addressed yet. No entry exists in the database.</p>
<p className="text-sm text-gray-300">This CVE has not been addressed yet. No entry exists in the database.</p>
</div>
</div>
)}
@@ -1192,7 +1192,7 @@ export default function App() {
</div>
<div className="space-y-2">
{jiraTickets.filter(t => t.status !== 'Closed').map(ticket => (
<div key={ticket.id} className="data-row flex items-center justify-between p-3 bg-intel-dark/50 rounded border border-intel-grid hover:border-intel-warning/30">
<div key={ticket.id} className="jira-ticket-item flex items-center justify-between">
<div className="flex items-center gap-4 flex-1">
<a
href={ticket.url || '#'}
@@ -1202,9 +1202,9 @@ export default function App() {
>
{ticket.ticket_key}
</a>
<span className="text-sm text-gray-300 font-mono">{ticket.cve_id}</span>
<span className="text-sm text-gray-500 font-mono">({ticket.vendor})</span>
{ticket.summary && <span className="text-sm text-gray-400 truncate max-w-xs">{ticket.summary}</span>}
<span className="text-sm text-white font-mono">{ticket.cve_id}</span>
<span className="text-sm text-gray-300 font-mono">({ticket.vendor})</span>
{ticket.summary && <span className="text-sm text-gray-300 truncate max-w-xs">{ticket.summary}</span>}
<span className={`status-badge ${
ticket.status === 'Open' ? 'status-critical' : 'status-high'
}`}>
@@ -1213,10 +1213,10 @@ export default function App() {
</div>
{canWrite() && (
<div className="flex gap-2">
<button onClick={() => handleEditTicket(ticket)} className="text-gray-500 hover:text-intel-warning transition-colors">
<button onClick={() => handleEditTicket(ticket)} className="text-gray-400 hover:text-intel-warning transition-colors">
<Edit2 className="w-4 h-4" />
</button>
<button onClick={() => handleDeleteTicket(ticket)} className="text-gray-500 hover:text-intel-danger transition-colors">
<button onClick={() => handleDeleteTicket(ticket)} className="text-gray-400 hover:text-intel-danger transition-colors">
<Trash2 className="w-4 h-4" />
</button>
</div>
@@ -1231,7 +1231,7 @@ export default function App() {
<div className="intel-card rounded-lg p-6 mb-6">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="md:col-span-1">
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
<Search className="inline w-4 h-4 mr-1" />
Search CVEs
</label>
@@ -1245,7 +1245,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
<Filter className="inline w-4 h-4 mr-1" />
Vendor
</label>
@@ -1261,7 +1261,7 @@ export default function App() {
</div>
<div>
<label className="block text-xs font-medium text-gray-400 mb-2 uppercase tracking-wider">
<label className="block text-xs font-medium text-gray-300 mb-2 uppercase tracking-wider">
<AlertCircle className="inline w-4 h-4 mr-1" />
Severity
</label>
@@ -1331,7 +1331,7 @@ export default function App() {
<div key={cveId} className="intel-card rounded-lg relative overflow-hidden">
{/* Clickable CVE Header */}
<div
className="p-6 cursor-pointer hover:bg-intel-medium/30 transition-all duration-200 select-none"
className="cve-header p-6 cursor-pointer transition-all duration-200 select-none"
onClick={() => toggleCVEExpand(cveId)}
>
<div className="flex items-start justify-between">
@@ -1346,17 +1346,17 @@ export default function App() {
{/* Collapsed: truncated description + summary row */}
{!isCVEExpanded && (
<div className="ml-8">
<p className="text-gray-400 text-sm truncate mb-2">{vendorEntries[0].description}</p>
<p className="text-gray-300 text-sm truncate mb-2">{vendorEntries[0].description}</p>
<div className="flex items-center gap-3 flex-wrap">
<span className={`status-badge status-${highestSeverity.toLowerCase()}`}>
{highestSeverity}
</span>
<span className="text-xs text-gray-500 font-mono">{vendorEntries.length} vendor{vendorEntries.length > 1 ? 's' : ''}</span>
<span className="text-xs text-gray-500 flex items-center gap-1 font-mono">
<span className="text-xs text-gray-300 font-mono">{vendorEntries.length} vendor{vendorEntries.length > 1 ? 's' : ''}</span>
<span className="text-xs text-gray-300 flex items-center gap-1 font-mono">
<FileText className="w-3 h-3" />
{totalDocCount} doc{totalDocCount !== 1 ? 's' : ''}
</span>
<span className="text-xs text-gray-500 font-mono">
<span className="text-xs text-gray-300 font-mono">
{overallStatuses.join(', ')}
</span>
</div>
@@ -1366,8 +1366,8 @@ export default function App() {
{/* Expanded: full description + metadata */}
{isCVEExpanded && (
<div className="ml-8">
<p className="text-gray-300 mb-3">{vendorEntries[0].description}</p>
<div className="flex items-center gap-2 text-sm text-gray-400 font-mono">
<p className="text-white mb-3">{vendorEntries[0].description}</p>
<div className="flex items-center gap-2 text-sm text-gray-300 font-mono">
<span>Published: {vendorEntries[0].published_date}</span>
<span className="text-intel-accent"></span>
<span>{vendorEntries.length} affected vendor{vendorEntries.length > 1 ? 's' : ''}</span>
@@ -1397,17 +1397,17 @@ export default function App() {
const isDocExpanded = selectedCVE === cve.cve_id && selectedVendorView === cve.vendor;
return (
<div key={cve.id} className="border border-intel-accent/20 rounded-lg p-4 bg-intel-dark/50 hover:bg-intel-dark transition-all">
<div key={cve.id} className="vendor-card">
<div className="flex justify-between items-start">
<div className="flex-1">
<div className="flex items-center gap-3 mb-2">
<h4 className="text-lg font-semibold text-gray-200 font-sans">{cve.vendor}</h4>
<h4 className="text-lg font-semibold text-white font-sans">{cve.vendor}</h4>
<span className={`status-badge status-${cve.severity.toLowerCase()}`}>
{cve.severity}
</span>
</div>
<div className="flex items-center gap-4 text-sm text-gray-400 font-mono">
<span>Status: <span className="font-medium text-gray-300">{cve.status}</span></span>
<div className="flex items-center gap-4 text-sm text-gray-300 font-mono">
<span>Status: <span className="font-medium text-white">{cve.status}</span></span>
<span className="flex items-center gap-1">
<FileText className="w-4 h-4" />
{cve.document_count} doc{cve.document_count !== 1 ? 's' : ''}
@@ -1445,9 +1445,9 @@ export default function App() {
{/* Documents Section */}
{isDocExpanded && (
<div className="mt-4 pt-4 border-t border-intel-accent/20">
<h5 className="text-sm font-semibold text-gray-300 mb-3 flex items-center gap-2 font-mono uppercase tracking-wider">
<FileText className="w-4 h-4" />
<div className="mt-4 pt-4 border-t border-intel-accent/30">
<h5 className="text-sm font-semibold text-white mb-3 flex items-center gap-2 font-mono uppercase tracking-wider">
<FileText className="w-4 h-4 text-intel-accent" />
Documents ({documents.length})
</h5>
{documents.length > 0 ? (
@@ -1455,7 +1455,7 @@ export default function App() {
{documents.map(doc => (
<div
key={doc.id}
className="data-row flex items-center justify-between p-3 bg-intel-darkest/50 rounded hover:bg-intel-medium/30 transition-all border border-intel-grid"
className="document-item flex items-center justify-between"
>
<div className="flex items-center gap-3 flex-1">
<input
@@ -1464,10 +1464,10 @@ export default function App() {
onChange={() => toggleDocumentSelection(doc.id)}
className="w-4 h-4 text-intel-accent rounded focus:ring-2 focus:ring-intel-accent bg-intel-dark border-intel-accent/50"
/>
<FileText className="w-5 h-5 text-intel-accent/70" />
<FileText className="w-5 h-5 text-intel-accent" />
<div className="flex-1">
<p className="text-sm font-medium text-gray-200 font-mono">{doc.name}</p>
<p className="text-xs text-gray-500 capitalize font-mono">
<p className="text-sm font-medium text-white font-mono">{doc.name}</p>
<p className="text-xs text-gray-300 capitalize font-mono">
{doc.type} <span className="text-intel-accent"></span> {doc.file_size}
{doc.notes && <span> <span className="text-intel-accent"></span> {doc.notes}</span>}
</p>
@@ -1496,7 +1496,7 @@ export default function App() {
))}
</div>
) : (
<p className="text-sm text-gray-500 italic font-mono">No documents attached</p>
<p className="text-sm text-gray-400 italic font-mono">No documents attached</p>
)}
{canWrite() && (
<button
@@ -1515,16 +1515,16 @@ export default function App() {
{(() => {
const vendorTickets = jiraTickets.filter(t => t.cve_id === cve.cve_id && t.vendor === cve.vendor);
return vendorTickets.length > 0 || canWrite() ? (
<div className="mt-4 pt-4 border-t border-gray-300">
<div className="mt-4 pt-4 border-t border-intel-warning/30">
<div className="flex justify-between items-center mb-3">
<h5 className="text-sm font-semibold text-gray-700 flex items-center gap-2">
<AlertCircle className="w-4 h-4 text-orange-500" />
<h5 className="text-sm font-semibold text-white flex items-center gap-2 font-mono uppercase tracking-wider">
<AlertCircle className="w-4 h-4 text-intel-warning" />
JIRA Tickets ({vendorTickets.length})
</h5>
{canWrite() && (
<button
onClick={() => openAddTicketForCVE(cve.cve_id, cve.vendor)}
className="text-xs px-2 py-1 text-orange-600 hover:bg-orange-50 rounded border border-orange-300 flex items-center gap-1"
className="text-xs px-3 py-1 intel-button intel-button-primary flex items-center gap-1"
>
<Plus className="w-3 h-3" />
Add Ticket
@@ -1534,32 +1534,32 @@ export default function App() {
{vendorTickets.length > 0 ? (
<div className="space-y-2">
{vendorTickets.map(ticket => (
<div key={ticket.id} className="flex items-center justify-between p-2 bg-white rounded border border-gray-200">
<div className="flex items-center gap-3">
<div key={ticket.id} className="jira-ticket-item flex items-center justify-between">
<div className="flex items-center gap-3 flex-1">
<a
href={ticket.url || '#'}
target="_blank"
rel="noopener noreferrer"
className="font-mono text-sm font-semibold text-[#0476D9] hover:underline"
className="font-mono text-sm font-semibold text-intel-accent hover:text-intel-warning transition-colors"
>
{ticket.ticket_key}
</a>
{ticket.summary && <span className="text-sm text-gray-600 truncate max-w-xs">{ticket.summary}</span>}
<span className={`px-2 py-0.5 rounded text-xs font-medium ${
ticket.status === 'Open' ? 'bg-red-100 text-red-800' :
ticket.status === 'In Progress' ? 'bg-yellow-100 text-yellow-800' :
'bg-green-100 text-green-800'
{ticket.summary && <span className="text-sm text-gray-300 truncate max-w-xs">{ticket.summary}</span>}
<span className={`status-badge ${
ticket.status === 'Open' ? 'status-critical' :
ticket.status === 'In Progress' ? 'status-high' :
'status-low'
}`}>
{ticket.status}
</span>
</div>
{canWrite() && (
<div className="flex gap-1">
<button onClick={() => handleEditTicket(ticket)} className="p-1 text-gray-400 hover:text-orange-600">
<Edit2 className="w-3 h-3" />
<div className="flex gap-2">
<button onClick={() => handleEditTicket(ticket)} className="p-1 text-gray-400 hover:text-intel-warning transition-colors">
<Edit2 className="w-4 h-4" />
</button>
<button onClick={() => handleDeleteTicket(ticket)} className="p-1 text-gray-400 hover:text-red-600">
<Trash2 className="w-3 h-3" />
<button onClick={() => handleDeleteTicket(ticket)} className="p-1 text-gray-400 hover:text-intel-danger transition-colors">
<Trash2 className="w-4 h-4" />
</button>
</div>
)}
@@ -1567,7 +1567,7 @@ export default function App() {
))}
</div>
) : (
<p className="text-sm text-gray-500 italic">No JIRA tickets linked</p>
<p className="text-sm text-gray-400 italic font-mono">No JIRA tickets linked</p>
)}
</div>
) : null;
@@ -1585,10 +1585,10 @@ export default function App() {
)}
{Object.keys(filteredGroupedCVEs).length === 0 && !loading && (
<div className="bg-white rounded-lg shadow-md p-12 text-center">
<div className="intel-card rounded-lg p-12 text-center">
<AlertCircle className="w-12 h-12 text-gray-400 mx-auto mb-4" />
<h3 className="text-lg font-medium text-gray-900 mb-2">No CVEs Found</h3>
<p className="text-gray-600">Try adjusting your search criteria or filters</p>
<h3 className="text-lg font-medium text-white mb-2 font-mono">No CVEs Found</h3>
<p className="text-gray-300">Try adjusting your search criteria or filters</p>
</div>
)}
</div>