feat(FN-1010): add mission start endpoint and UI button
- Add POST /api/missions/:missionId/start backend endpoint to start planning missions - Add startMission() frontend API function in dashboard api.ts - Add Start button in MissionManager component for planning missions - Add integration tests for the startMission endpoint covering success, error, and edge cases
This commit is contained in:
@@ -2654,6 +2654,13 @@ export function stopMission(missionId: string, projectId?: string): Promise<Miss
|
||||
});
|
||||
}
|
||||
|
||||
/** Start a planning mission: sets status to "active" and activates the first pending slice */
|
||||
export function startMission(missionId: string, projectId?: string): Promise<MissionWithHierarchy> {
|
||||
return api<MissionWithHierarchy>(withProjectId(`/missions/${encodeURIComponent(missionId)}/start`, projectId), {
|
||||
method: "POST",
|
||||
});
|
||||
}
|
||||
|
||||
// ── Mission Autopilot API ────────────────────────────────────────────────
|
||||
|
||||
/** Fetch autopilot status for a mission */
|
||||
|
||||
@@ -61,6 +61,7 @@ import {
|
||||
pauseMission,
|
||||
resumeMission,
|
||||
stopMission,
|
||||
startMission,
|
||||
fetchMissionAutopilotStatus,
|
||||
updateMissionAutopilot,
|
||||
startMissionAutopilot,
|
||||
@@ -686,6 +687,18 @@ export function MissionManager({ isOpen, onClose, addToast, projectId, onSelectT
|
||||
}
|
||||
}, [addToast, loadMissionDetail, loadMissions, projectId]);
|
||||
|
||||
// Start a planning mission — set status to "active" and activate first slice
|
||||
const handleStartMission = useCallback(async (missionId: string) => {
|
||||
try {
|
||||
await startMission(missionId, projectId);
|
||||
addToast("Mission started — first slice activated", "success");
|
||||
await loadMissionDetail(missionId);
|
||||
loadMissions();
|
||||
} catch (err: any) {
|
||||
addToast(err.message || "Failed to start mission", "error");
|
||||
}
|
||||
}, [addToast, loadMissionDetail, loadMissions, projectId]);
|
||||
|
||||
// ── Autopilot handlers ──
|
||||
|
||||
const loadAutopilotStatus = useCallback(async (missionId: string) => {
|
||||
@@ -980,6 +993,16 @@ export function MissionManager({ isOpen, onClose, addToast, projectId, onSelectT
|
||||
<RefreshCw size={14} />
|
||||
</button>
|
||||
)}
|
||||
{selectedMission.status === "planning" && (
|
||||
<button
|
||||
className="mission-icon-btn mission-icon-btn--success"
|
||||
onClick={() => handleStartMission(selectedMission.id)}
|
||||
title="Start mission"
|
||||
aria-label="Start mission"
|
||||
>
|
||||
<Play size={14} />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className="mission-icon-btn"
|
||||
onClick={() => handleEditMission(selectedMission)}
|
||||
@@ -1597,6 +1620,15 @@ export function MissionManager({ isOpen, onClose, addToast, projectId, onSelectT
|
||||
<RefreshCw size={14} />
|
||||
</button>
|
||||
)}
|
||||
{m.status === "planning" && (
|
||||
<button
|
||||
className="mission-icon-btn mission-icon-btn--success"
|
||||
onClick={() => handleStartMission(m.id)}
|
||||
title="Start mission"
|
||||
>
|
||||
<Play size={14} />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className="mission-icon-btn"
|
||||
onClick={() => handleEditMission(mission)}
|
||||
|
||||
Reference in New Issue
Block a user