mission canvas: add / edit / delete toolbar controls
Top-right toolbar grows three CRUD controls per your request:
- Plus (always visible) — opens MissionWizard, selects the new
mission on create
- Pencil (draft-only) — opens EditMissionModal for title +
description; PATCHes /api/missions/{id}
- Trash (always visible) — window.confirm then DELETEs; sidebar
selection clears via new onDeleted callback
Backend:
- cm-db::repo::missions::update_meta(id, ws, title?, description?)
— COALESCE-based partial patch
- cm-db::repo::missions::delete(id, ws) — hard delete, cascades
via FKs on phases/tasks/artifacts/benchmark_snapshots
- PATCH /api/missions/{id} (draft-only) + DELETE /api/missions/{id}
Frontend:
- lib/api/missions — updateMission + deleteMission clients
- MissionCanvas — three toolbar buttons, EditMissionModal
(title + textarea for description), local wizard state
- Dashboard — passes onSelect + onDeleted so sidebar reacts to
create + delete without stale selection
Edit is draft-only (backend enforces + button hidden past draft) so
in-flight missions can't have their brief mutated out from under
running agents. Delete is unconditional — operator responsibility to
Cancel first if a run is live.
This commit is contained in:
@@ -252,6 +252,47 @@ pub async fn set_description(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Patch title + description in one shot. Either field `None` = leave
|
||||
/// as-is (uses COALESCE so partial edits don't clobber the other).
|
||||
pub async fn update_meta(
|
||||
pool: &PgPool,
|
||||
id: Uuid,
|
||||
workspace_id: Uuid,
|
||||
title: Option<&str>,
|
||||
description: Option<&str>,
|
||||
) -> Result<(), DbError> {
|
||||
sqlx::query(
|
||||
"UPDATE missions
|
||||
SET title = COALESCE($3, title),
|
||||
description = COALESCE($4, description),
|
||||
updated_at = now()
|
||||
WHERE id = $1 AND workspace_id = $2",
|
||||
)
|
||||
.bind(id)
|
||||
.bind(workspace_id)
|
||||
.bind(title)
|
||||
.bind(description)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Hard-delete a mission. Cascades via FKs on mission_phases /
|
||||
/// mission_tasks / mission_artifacts / benchmark_snapshots (all
|
||||
/// declared ON DELETE CASCADE in 0047).
|
||||
pub async fn delete(
|
||||
pool: &PgPool,
|
||||
id: Uuid,
|
||||
workspace_id: Uuid,
|
||||
) -> Result<u64, DbError> {
|
||||
let r = sqlx::query("DELETE FROM missions WHERE id = $1 AND workspace_id = $2")
|
||||
.bind(id)
|
||||
.bind(workspace_id)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(r.rows_affected())
|
||||
}
|
||||
|
||||
pub async fn set_status(
|
||||
pool: &PgPool,
|
||||
id: Uuid,
|
||||
|
||||
Reference in New Issue
Block a user