feat(phase-36): automatic Tempo time tracking via workflow buttons + fix campaign test management

- Add red_started_at/blue_started_at timing fields to Test model with Alembic migration

- Modify workflow transitions to auto-create integrity-hashed worklogs: Start Execution records red_started_at, Submit to Blue Team stops Red timer and creates worklog then starts Blue timer, Submit for Review stops Blue timer and creates worklog

- Auto-sync worklogs to Tempo when test has a Jira link

- Add LiveTimer component showing real-time elapsed counter during active phases

- Clear timing fields on test reopen

- Fix campaign test management: replace broken navigate-to-tests flow with AddTestToCampaignModal that lets users search and add existing tests directly from the campaign detail page
This commit is contained in:
2026-02-17 16:59:19 +01:00
parent 005a09b42f
commit febf460580
10 changed files with 461 additions and 5 deletions

View File

@@ -30,6 +30,7 @@ import { useAuth } from "../context/AuthContext";
import CampaignTimeline from "../components/CampaignTimeline";
import JiraLinkPanel from "../components/JiraLinkPanel";
import WorklogTimeline from "../components/WorklogTimeline";
import AddTestToCampaignModal from "../components/AddTestToCampaignModal";
const statusColors: Record<string, string> = {
draft: "bg-gray-800/50 text-gray-400 border-gray-600/30",
@@ -61,6 +62,7 @@ export default function CampaignDetailPage() {
const { user } = useAuth();
const [toast, setToast] = useState<{ message: string; type: "success" | "error" } | null>(null);
const [showAddTestModal, setShowAddTestModal] = useState(false);
const showToast = (message: string, type: "success" | "error") => {
setToast({ message, type });
@@ -500,7 +502,7 @@ export default function CampaignDetailPage() {
</h2>
{canManage && campaign.status === "draft" && (
<button
onClick={() => navigate(`/tests?campaign=${campaignId}`)}
onClick={() => setShowAddTestModal(true)}
className="flex items-center gap-1.5 rounded-lg border border-cyan-500/30 bg-cyan-500/10 px-3 py-1.5 text-sm font-medium text-cyan-400 hover:bg-cyan-500/20 transition-colors"
>
<Plus className="h-4 w-4" />
@@ -606,6 +608,15 @@ export default function CampaignDetailPage() {
<WorklogTimeline entityType="campaign" entityId={campaignId!} />
</div>
{/* Add Test to Campaign Modal */}
<AddTestToCampaignModal
campaignId={campaignId!}
existingTestIds={campaign.tests.map((ct) => ct.test_id)}
open={showAddTestModal}
onClose={() => setShowAddTestModal(false)}
onSuccess={() => showToast("Test added to campaign", "success")}
/>
{/* Toast notification */}
{toast && (
<div