From a16ae05350749fb4800c8ffb2c702925a159b89c Mon Sep 17 00:00:00 2001 From: Louis Knight-Webb Date: Mon, 30 Jun 2025 23:46:08 +0100 Subject: [PATCH] Move stop button (#29) * Task attempt e2bfa5ea-1e87-4b4d-a7a0-7a523ce3f49d - Final changes * Task attempt e2bfa5ea-1e87-4b4d-a7a0-7a523ce3f49d - Final changes * Fix activity timestamp issue --- ...492c17c4f57b31908f6973ce4f4a53785f5f0.json | 68 ---------------- ...fcb1bce32a4be1269820bf2031dd6b7e13be8.json | 68 ++++++++++++++++ backend/src/models/task.rs | 81 ++++++++++++------- .../components/tasks/TaskDetailsToolbar.tsx | 48 +++++------ 4 files changed, 142 insertions(+), 123 deletions(-) delete mode 100644 backend/.sqlx/query-4333e38d5175a00d1206b929b8f492c17c4f57b31908f6973ce4f4a53785f5f0.json create mode 100644 backend/.sqlx/query-5303664388a91c378ade88cad68fcb1bce32a4be1269820bf2031dd6b7e13be8.json diff --git a/backend/.sqlx/query-4333e38d5175a00d1206b929b8f492c17c4f57b31908f6973ce4f4a53785f5f0.json b/backend/.sqlx/query-4333e38d5175a00d1206b929b8f492c17c4f57b31908f6973ce4f4a53785f5f0.json deleted file mode 100644 index 1225621e..00000000 --- a/backend/.sqlx/query-4333e38d5175a00d1206b929b8f492c17c4f57b31908f6973ce4f4a53785f5f0.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "db_name": "SQLite", - "query": "SELECT \n t.id as \"id!: Uuid\", \n t.project_id as \"project_id!: Uuid\", \n t.title, \n t.description, \n t.status as \"status!: TaskStatus\", \n t.created_at as \"created_at!: DateTime\", \n t.updated_at as \"updated_at!: DateTime\",\n CASE WHEN in_progress_attempts.task_id IS NOT NULL THEN true ELSE false END as \"has_in_progress_attempt!: i64\",\n CASE WHEN merged_attempts.task_id IS NOT NULL THEN true ELSE false END as \"has_merged_attempt!\"\n FROM tasks t\n LEFT JOIN (\n SELECT DISTINCT ta.task_id \n FROM task_attempts ta\n INNER JOIN execution_processes ep ON ta.id = ep.task_attempt_id\n INNER JOIN (\n SELECT execution_process_id, MAX(created_at) as latest_created_at\n FROM task_attempt_activities\n GROUP BY execution_process_id\n ) latest_activity ON ep.id = latest_activity.execution_process_id\n INNER JOIN task_attempt_activities taa ON ep.id = taa.execution_process_id \n AND taa.created_at = latest_activity.latest_created_at\n WHERE taa.status IN ('setuprunning', 'executorrunning')\n ) in_progress_attempts ON t.id = in_progress_attempts.task_id\n LEFT JOIN (\n SELECT DISTINCT ta.task_id \n FROM task_attempts ta\n WHERE ta.merge_commit IS NOT NULL\n ) merged_attempts ON t.id = merged_attempts.task_id\n WHERE t.project_id = $1 \n ORDER BY t.created_at DESC", - "describe": { - "columns": [ - { - "name": "id!: Uuid", - "ordinal": 0, - "type_info": "Blob" - }, - { - "name": "project_id!: Uuid", - "ordinal": 1, - "type_info": "Blob" - }, - { - "name": "title", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "description", - "ordinal": 3, - "type_info": "Text" - }, - { - "name": "status!: TaskStatus", - "ordinal": 4, - "type_info": "Text" - }, - { - "name": "created_at!: DateTime", - "ordinal": 5, - "type_info": "Text" - }, - { - "name": "updated_at!: DateTime", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "has_in_progress_attempt!: i64", - "ordinal": 7, - "type_info": "Integer" - }, - { - "name": "has_merged_attempt!", - "ordinal": 8, - "type_info": "Integer" - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - true, - false, - false, - true, - false, - false, - false, - false, - false - ] - }, - "hash": "4333e38d5175a00d1206b929b8f492c17c4f57b31908f6973ce4f4a53785f5f0" -} diff --git a/backend/.sqlx/query-5303664388a91c378ade88cad68fcb1bce32a4be1269820bf2031dd6b7e13be8.json b/backend/.sqlx/query-5303664388a91c378ade88cad68fcb1bce32a4be1269820bf2031dd6b7e13be8.json new file mode 100644 index 00000000..41dc7992 --- /dev/null +++ b/backend/.sqlx/query-5303664388a91c378ade88cad68fcb1bce32a4be1269820bf2031dd6b7e13be8.json @@ -0,0 +1,68 @@ +{ + "db_name": "SQLite", + "query": "SELECT \n t.id AS \"id!: Uuid\", \n t.project_id AS \"project_id!: Uuid\", \n t.title, \n t.description, \n t.status AS \"status!: TaskStatus\", \n t.created_at AS \"created_at!: DateTime\", \n t.updated_at AS \"updated_at!: DateTime\",\n CASE \n WHEN in_progress_attempts.task_id IS NOT NULL THEN true \n ELSE false \n END AS \"has_in_progress_attempt!: i64\",\n CASE \n WHEN merged_attempts.task_id IS NOT NULL THEN true \n ELSE false \n END AS \"has_merged_attempt!\"\n FROM tasks t\n LEFT JOIN (\n SELECT DISTINCT ta.task_id\n FROM task_attempts ta\n JOIN execution_processes ep \n ON ta.id = ep.task_attempt_id\n JOIN (\n -- pick exactly one “latest” activity per process,\n -- tiebreaking so that running‐states are lower priority\n SELECT execution_process_id, status\n FROM (\n SELECT\n execution_process_id,\n status,\n ROW_NUMBER() OVER (\n PARTITION BY execution_process_id\n ORDER BY\n created_at DESC,\n CASE \n WHEN status IN ('setuprunning','executorrunning') THEN 1 \n ELSE 0 \n END\n ) AS rn\n FROM task_attempt_activities\n ) sub\n WHERE rn = 1\n ) latest_act \n ON ep.id = latest_act.execution_process_id\n WHERE latest_act.status IN ('setuprunning','executorrunning')\n ) in_progress_attempts \n ON t.id = in_progress_attempts.task_id\n LEFT JOIN (\n SELECT DISTINCT ta.task_id\n FROM task_attempts ta\n WHERE ta.merge_commit IS NOT NULL\n ) merged_attempts \n ON t.id = merged_attempts.task_id\n WHERE t.project_id = $1\n ORDER BY t.created_at DESC;\n ", + "describe": { + "columns": [ + { + "name": "id!: Uuid", + "ordinal": 0, + "type_info": "Blob" + }, + { + "name": "project_id!: Uuid", + "ordinal": 1, + "type_info": "Blob" + }, + { + "name": "title", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "description", + "ordinal": 3, + "type_info": "Text" + }, + { + "name": "status!: TaskStatus", + "ordinal": 4, + "type_info": "Text" + }, + { + "name": "created_at!: DateTime", + "ordinal": 5, + "type_info": "Text" + }, + { + "name": "updated_at!: DateTime", + "ordinal": 6, + "type_info": "Text" + }, + { + "name": "has_in_progress_attempt!: i64", + "ordinal": 7, + "type_info": "Integer" + }, + { + "name": "has_merged_attempt!", + "ordinal": 8, + "type_info": "Integer" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + true, + false, + false, + true, + false, + false, + false, + false, + false + ] + }, + "hash": "5303664388a91c378ade88cad68fcb1bce32a4be1269820bf2031dd6b7e13be8" +} diff --git a/backend/src/models/task.rs b/backend/src/models/task.rs index fe9f4609..82925419 100644 --- a/backend/src/models/task.rs +++ b/backend/src/models/task.rs @@ -74,36 +74,61 @@ impl Task { ) -> Result, sqlx::Error> { let records = sqlx::query!( r#"SELECT - t.id as "id!: Uuid", - t.project_id as "project_id!: Uuid", + t.id AS "id!: Uuid", + t.project_id AS "project_id!: Uuid", t.title, t.description, - t.status as "status!: TaskStatus", - t.created_at as "created_at!: DateTime", - t.updated_at as "updated_at!: DateTime", - CASE WHEN in_progress_attempts.task_id IS NOT NULL THEN true ELSE false END as "has_in_progress_attempt!: i64", - CASE WHEN merged_attempts.task_id IS NOT NULL THEN true ELSE false END as "has_merged_attempt!" - FROM tasks t - LEFT JOIN ( - SELECT DISTINCT ta.task_id - FROM task_attempts ta - INNER JOIN execution_processes ep ON ta.id = ep.task_attempt_id - INNER JOIN ( - SELECT execution_process_id, MAX(created_at) as latest_created_at - FROM task_attempt_activities - GROUP BY execution_process_id - ) latest_activity ON ep.id = latest_activity.execution_process_id - INNER JOIN task_attempt_activities taa ON ep.id = taa.execution_process_id - AND taa.created_at = latest_activity.latest_created_at - WHERE taa.status IN ('setuprunning', 'executorrunning') - ) in_progress_attempts ON t.id = in_progress_attempts.task_id - LEFT JOIN ( - SELECT DISTINCT ta.task_id - FROM task_attempts ta - WHERE ta.merge_commit IS NOT NULL - ) merged_attempts ON t.id = merged_attempts.task_id - WHERE t.project_id = $1 - ORDER BY t.created_at DESC"#, + t.status AS "status!: TaskStatus", + t.created_at AS "created_at!: DateTime", + t.updated_at AS "updated_at!: DateTime", + CASE + WHEN in_progress_attempts.task_id IS NOT NULL THEN true + ELSE false + END AS "has_in_progress_attempt!: i64", + CASE + WHEN merged_attempts.task_id IS NOT NULL THEN true + ELSE false + END AS "has_merged_attempt!" + FROM tasks t + LEFT JOIN ( + SELECT DISTINCT ta.task_id + FROM task_attempts ta + JOIN execution_processes ep + ON ta.id = ep.task_attempt_id + JOIN ( + -- pick exactly one “latest” activity per process, + -- tiebreaking so that running‐states are lower priority + SELECT execution_process_id, status + FROM ( + SELECT + execution_process_id, + status, + ROW_NUMBER() OVER ( + PARTITION BY execution_process_id + ORDER BY + created_at DESC, + CASE + WHEN status IN ('setuprunning','executorrunning') THEN 1 + ELSE 0 + END + ) AS rn + FROM task_attempt_activities + ) sub + WHERE rn = 1 + ) latest_act + ON ep.id = latest_act.execution_process_id + WHERE latest_act.status IN ('setuprunning','executorrunning') + ) in_progress_attempts + ON t.id = in_progress_attempts.task_id + LEFT JOIN ( + SELECT DISTINCT ta.task_id + FROM task_attempts ta + WHERE ta.merge_commit IS NOT NULL + ) merged_attempts + ON t.id = merged_attempts.task_id + WHERE t.project_id = $1 + ORDER BY t.created_at DESC; + "#, project_id ) .fetch_all(pool) diff --git a/frontend/src/components/tasks/TaskDetailsToolbar.tsx b/frontend/src/components/tasks/TaskDetailsToolbar.tsx index b9c21484..6bfc6e48 100644 --- a/frontend/src/components/tasks/TaskDetailsToolbar.tsx +++ b/frontend/src/components/tasks/TaskDetailsToolbar.tsx @@ -565,7 +565,18 @@ export function TaskDetailsToolbar({ )} - {!isAttemptRunning && !isStopping && ( + {isStopping || isAttemptRunning ? ( + + ) : ( - )} - - {!selectedAttempt && !isAttemptRunning && !isStopping && ( - - )} + )}