Workflow column: FP# only, urgency-based colors
- Backend: only extract FP# workflows; SYS# auto-generated tickets are no longer stored or shown (not actionable for triage purposes). Findings with no FP# ticket show blank in the workflow column. - Frontend: recolor workflow badges by action urgency — Expired/Rejected = red (act now), Reworked/Actionable = amber (resubmit), Requested = blue (waiting on approval). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -130,33 +130,31 @@ function extractFinding(f) {
|
||||
// CVE list: vulnerabilities.vulnInfoList[].cve
|
||||
const cves = (f.vulnerabilities?.vulnInfoList || []).map(v => v.cve).filter(Boolean);
|
||||
|
||||
// Workflow: flatten all distribution buckets, prioritise FP# over SYS#
|
||||
// Workflow: only capture FP# (False Positive) tickets — SYS# are auto-generated
|
||||
// system workflows and not actionable for our purposes.
|
||||
const wfDist = f.workflowDistribution || {};
|
||||
const allWfEntries = [
|
||||
...(wfDist.actionableWorkflows || []),
|
||||
...(wfDist.requestedWorkflows || []),
|
||||
...(wfDist.approvedWorkflows || []),
|
||||
...(wfDist.reworkedWorkflows || []),
|
||||
...(wfDist.rejectedWorkflows || []),
|
||||
...(wfDist.expiredWorkflows || []),
|
||||
...(wfDist.latestSystemWorkflows || []),
|
||||
];
|
||||
// FP# (False Positive tickets) take priority over SYS# (system workflows)
|
||||
const fpEntry = allWfEntries.find(w => (w.generatedId || '').startsWith('FP#'));
|
||||
const sysEntry = allWfEntries.find(w => (w.generatedId || '').startsWith('SYS#'));
|
||||
const wfEntry = fpEntry || sysEntry || allWfEntries[0] || null;
|
||||
const fpBuckets = [
|
||||
...(wfDist.actionableWorkflows || []),
|
||||
...(wfDist.requestedWorkflows || []),
|
||||
...(wfDist.reworkedWorkflows || []),
|
||||
...(wfDist.rejectedWorkflows || []),
|
||||
...(wfDist.expiredWorkflows || []),
|
||||
...(wfDist.approvedWorkflows || []),
|
||||
].filter(w => (w.generatedId || '').startsWith('FP#'));
|
||||
|
||||
// If the distribution didn't surface an FP#, also check workflowGeneratedNames directly.
|
||||
// (Some FP# tickets only appear in the names list without full state info.)
|
||||
// Priority: actionable > requested > reworked > rejected > expired > approved
|
||||
const fpEntry = fpBuckets[0] || null;
|
||||
|
||||
// Fallback: if no FP# in distribution, check workflowGeneratedNames directly
|
||||
const generatedNames = f.workflowGeneratedNames || [];
|
||||
const fpFromNames = !fpEntry
|
||||
? generatedNames.find(n => n.startsWith('FP#')) || null
|
||||
: null;
|
||||
|
||||
const workflow = wfEntry ? {
|
||||
id: wfEntry.generatedId || '',
|
||||
state: wfEntry.state || '',
|
||||
type: wfEntry.type || wfEntry.acronym || '',
|
||||
const workflow = fpEntry ? {
|
||||
id: fpEntry.generatedId || '',
|
||||
state: fpEntry.state || '',
|
||||
type: 'FP',
|
||||
} : fpFromNames ? {
|
||||
id: fpFromNames,
|
||||
state: '',
|
||||
|
||||
@@ -126,14 +126,14 @@ function dueDateColor(dueDate) {
|
||||
}
|
||||
|
||||
function workflowStyle(state) {
|
||||
// Colors reflect action urgency — all findings here are Open, so Approved won't appear.
|
||||
switch ((state || '').toLowerCase()) {
|
||||
case 'approved': return { bg: 'rgba(16,185,129,0.12)', border: 'rgba(16,185,129,0.35)', text: '#10B981' };
|
||||
case 'requested': return { bg: 'rgba(14,165,233,0.12)', border: 'rgba(14,165,233,0.35)', text: '#0EA5E9' };
|
||||
case 'actionable': return { bg: 'rgba(245,158,11,0.12)', border: 'rgba(245,158,11,0.35)', text: '#F59E0B' };
|
||||
case 'reworked': return { bg: 'rgba(245,158,11,0.12)', border: 'rgba(245,158,11,0.35)', text: '#F59E0B' };
|
||||
case 'rejected': return { bg: 'rgba(239,68,68,0.12)', border: 'rgba(239,68,68,0.35)', text: '#EF4444' };
|
||||
case 'expired': return { bg: 'rgba(100,116,139,0.12)', border: 'rgba(100,116,139,0.3)', text: '#64748B' };
|
||||
default: return { bg: 'rgba(100,116,139,0.08)', border: 'rgba(100,116,139,0.2)', text: '#64748B' };
|
||||
case 'expired': return { bg: 'rgba(239,68,68,0.12)', border: 'rgba(239,68,68,0.4)', text: '#EF4444' }; // overdue — renew FP
|
||||
case 'rejected': return { bg: 'rgba(239,68,68,0.12)', border: 'rgba(239,68,68,0.4)', text: '#EF4444' }; // denied — must remediate
|
||||
case 'reworked': return { bg: 'rgba(245,158,11,0.12)', border: 'rgba(245,158,11,0.4)', text: '#F59E0B' }; // challenged — resubmit FP
|
||||
case 'actionable': return { bg: 'rgba(245,158,11,0.12)', border: 'rgba(245,158,11,0.4)', text: '#F59E0B' }; // needs action
|
||||
case 'requested': return { bg: 'rgba(14,165,233,0.12)', border: 'rgba(14,165,233,0.35)', text: '#0EA5E9' }; // in flight — awaiting approval
|
||||
default: return { bg: 'rgba(100,116,139,0.08)', border: 'rgba(100,116,139,0.2)', text: '#64748B' }; // unknown state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user