fix(reporting): smart-flip queue popover + add CARD workflow type
Popover now flips above the row when it would overflow the bottom of the viewport, and clamps horizontally to stay within the window. Adds CARD as a third workflow type (for out-of-team asset disposition in CARD) alongside FP and Archer. CARD is styled in green (#10B981) across the popover toggle and queue panel badge. DB: new migration (add_card_workflow_type.js) recreates ivanti_todo_queue with an updated CHECK constraint to allow 'CARD'; run manually on dev. App-level validation in the route is updated to match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1084,7 +1084,14 @@ function AddToQueuePopover({ finding, anchorRect, queueForm, setQueueForm, onAdd
|
||||
|
||||
useEffect(() => {
|
||||
if (!anchorRect) return;
|
||||
setPos({ top: anchorRect.bottom + 6, left: anchorRect.left });
|
||||
const PANEL_W = 260;
|
||||
const PANEL_H = 360; // conservative estimate (3 workflow buttons)
|
||||
const spaceBelow = window.innerHeight - anchorRect.bottom - 6;
|
||||
const top = spaceBelow >= PANEL_H
|
||||
? anchorRect.bottom + 6
|
||||
: Math.max(8, anchorRect.top - PANEL_H - 6);
|
||||
const left = Math.min(anchorRect.left, window.innerWidth - PANEL_W - 8);
|
||||
setPos({ top, left });
|
||||
setTimeout(() => inputRef.current?.focus(), 0);
|
||||
}, [anchorRect]);
|
||||
|
||||
@@ -1156,16 +1163,19 @@ function AddToQueuePopover({ finding, anchorRect, queueForm, setQueueForm, onAdd
|
||||
Workflow Type
|
||||
</span>
|
||||
<div style={{ display: 'flex', gap: '0.375rem' }}>
|
||||
{['FP', 'Archer'].map((wt) => {
|
||||
const active = queueForm.workflowType === wt;
|
||||
const col = wt === 'FP' ? '#F59E0B' : '#0EA5E9';
|
||||
{[
|
||||
{ key: 'FP', col: '#F59E0B', rgb: '245,158,11' },
|
||||
{ key: 'Archer', col: '#0EA5E9', rgb: '14,165,233' },
|
||||
{ key: 'CARD', col: '#10B981', rgb: '16,185,129' },
|
||||
].map(({ key, col, rgb }) => {
|
||||
const active = queueForm.workflowType === key;
|
||||
return (
|
||||
<button
|
||||
key={wt}
|
||||
onClick={() => setQueueForm((f) => ({ ...f, workflowType: wt }))}
|
||||
key={key}
|
||||
onClick={() => setQueueForm((f) => ({ ...f, workflowType: key }))}
|
||||
style={{
|
||||
flex: 1, padding: '0.3rem',
|
||||
background: active ? `rgba(${wt === 'FP' ? '245,158,11' : '14,165,233'},0.15)` : 'transparent',
|
||||
background: active ? `rgba(${rgb},0.15)` : 'transparent',
|
||||
border: `1px solid ${active ? col : 'rgba(255,255,255,0.1)'}`,
|
||||
borderRadius: '0.25rem',
|
||||
color: active ? col : '#475569',
|
||||
@@ -1173,7 +1183,7 @@ function AddToQueuePopover({ finding, anchorRect, queueForm, setQueueForm, onAdd
|
||||
cursor: 'pointer', transition: 'all 0.12s',
|
||||
}}
|
||||
>
|
||||
{wt}
|
||||
{key}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
@@ -1322,7 +1332,9 @@ function QueuePanel({ open, items, onClose, onUpdate, onDelete, onClearCompleted
|
||||
{/* Items */}
|
||||
{vendorItems.map((item) => {
|
||||
const done = item.status === 'complete';
|
||||
const isFP = item.workflow_type === 'FP';
|
||||
const wfColor = item.workflow_type === 'FP' ? { col: '#F59E0B', rgb: '245,158,11' }
|
||||
: item.workflow_type === 'Archer' ? { col: '#0EA5E9', rgb: '14,165,233' }
|
||||
: { col: '#10B981', rgb: '16,185,129' };
|
||||
const cves = item.cves || [];
|
||||
const cveDisplay = cves.length > 0
|
||||
? cves.slice(0, 3).join(', ') + (cves.length > 3 ? ` +${cves.length - 3}` : '')
|
||||
@@ -1377,9 +1389,9 @@ function QueuePanel({ open, items, onClose, onUpdate, onDelete, onClearCompleted
|
||||
flexShrink: 0,
|
||||
padding: '0.1rem 0.35rem',
|
||||
borderRadius: '0.2rem',
|
||||
background: isFP ? 'rgba(245,158,11,0.12)' : 'rgba(14,165,233,0.12)',
|
||||
border: `1px solid ${isFP ? 'rgba(245,158,11,0.3)' : 'rgba(14,165,233,0.3)'}`,
|
||||
color: isFP ? '#F59E0B' : '#0EA5E9',
|
||||
background: `rgba(${wfColor.rgb},0.12)`,
|
||||
border: `1px solid rgba(${wfColor.rgb},0.3)`,
|
||||
color: wfColor.col,
|
||||
fontFamily: 'monospace', fontSize: '0.6rem', fontWeight: '700',
|
||||
}}>
|
||||
{item.workflow_type}
|
||||
|
||||
Reference in New Issue
Block a user