refactor(campaigns): move CampaignTimingPanel next to Progress panel
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Progress and Timing now share a 2-column grid at the top of the detail page. Removed CampaignTimingPanel from the bottom Jira section. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -309,44 +309,50 @@ export default function CampaignDetailPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Progress Panel */}
|
||||
<div className="rounded-xl border border-gray-800 bg-gray-900 p-6">
|
||||
<h2 className="mb-4 text-lg font-semibold text-white">Progress</h2>
|
||||
<div className="flex items-center gap-6 mb-4">
|
||||
<div>
|
||||
<span className="text-3xl font-bold text-white">{progress.completion_pct}%</span>
|
||||
<span className="ml-1 text-sm text-gray-400">complete</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="h-3 w-full rounded-full bg-gray-800 overflow-hidden">
|
||||
<div
|
||||
className={`h-full rounded-full transition-all ${
|
||||
progress.completion_pct === 100 ? "bg-green-500" : "bg-cyan-500"
|
||||
}`}
|
||||
style={{ width: `${progress.completion_pct}%` }}
|
||||
/>
|
||||
{/* Progress + Timing side by side */}
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
{/* Progress Panel */}
|
||||
<div className="rounded-xl border border-gray-800 bg-gray-900 p-6">
|
||||
<h2 className="mb-4 text-lg font-semibold text-white">Progress</h2>
|
||||
<div className="flex items-center gap-6 mb-4">
|
||||
<div>
|
||||
<span className="text-3xl font-bold text-white">{progress.completion_pct}%</span>
|
||||
<span className="ml-1 text-sm text-gray-400">complete</span>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="h-3 w-full rounded-full bg-gray-800 overflow-hidden">
|
||||
<div
|
||||
className={`h-full rounded-full transition-all ${
|
||||
progress.completion_pct === 100 ? "bg-green-500" : "bg-cyan-500"
|
||||
}`}
|
||||
style={{ width: `${progress.completion_pct}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-sm text-gray-400">
|
||||
{progress.by_state?.validated || 0} / {progress.total} tests
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-sm text-gray-400">
|
||||
{progress.by_state?.validated || 0} / {progress.total} tests
|
||||
</span>
|
||||
|
||||
{/* State breakdown */}
|
||||
{progress.total > 0 && (
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{Object.entries(progress.by_state || {}).map(([state, count]) => (
|
||||
<div
|
||||
key={state}
|
||||
className={`rounded-lg border px-3 py-1.5 text-xs font-medium ${
|
||||
testStateColors[state] || testStateColors.draft
|
||||
}`}
|
||||
>
|
||||
{state.replace(/_/g, " ")}: {count}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* State breakdown */}
|
||||
{progress.total > 0 && (
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{Object.entries(progress.by_state || {}).map(([state, count]) => (
|
||||
<div
|
||||
key={state}
|
||||
className={`rounded-lg border px-3 py-1.5 text-xs font-medium ${
|
||||
testStateColors[state] || testStateColors.draft
|
||||
}`}
|
||||
>
|
||||
{state.replace(/_/g, " ")}: {count}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{/* Campaign Timing */}
|
||||
<CampaignTimingPanel campaignId={campaignId!} />
|
||||
</div>
|
||||
|
||||
{/* Kill Chain Timeline */}
|
||||
@@ -630,11 +636,8 @@ export default function CampaignDetailPage() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Jira + Campaign Timing */}
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
<JiraLinkPanel entityType="campaign" entityId={campaignId!} readOnly label={campaign.name} />
|
||||
<CampaignTimingPanel campaignId={campaignId!} />
|
||||
</div>
|
||||
{/* Jira */}
|
||||
<JiraLinkPanel entityType="campaign" entityId={campaignId!} readOnly label={campaign.name} />
|
||||
|
||||
{/* Add Test to Campaign Modal */}
|
||||
<AddTestToCampaignModal
|
||||
|
||||
Reference in New Issue
Block a user