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
This commit is contained in:
committed by
GitHub
parent
9bb3411390
commit
a16ae05350
@@ -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<Utc>\", \n t.updated_at as \"updated_at!: DateTime<Utc>\",\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<Utc>",
|
|
||||||
"ordinal": 5,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "updated_at!: DateTime<Utc>",
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
68
backend/.sqlx/query-5303664388a91c378ade88cad68fcb1bce32a4be1269820bf2031dd6b7e13be8.json
generated
Normal file
68
backend/.sqlx/query-5303664388a91c378ade88cad68fcb1bce32a4be1269820bf2031dd6b7e13be8.json
generated
Normal file
@@ -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<Utc>\", \n t.updated_at AS \"updated_at!: DateTime<Utc>\",\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<Utc>",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at!: DateTime<Utc>",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
@@ -74,36 +74,61 @@ impl Task {
|
|||||||
) -> Result<Vec<TaskWithAttemptStatus>, sqlx::Error> {
|
) -> Result<Vec<TaskWithAttemptStatus>, sqlx::Error> {
|
||||||
let records = sqlx::query!(
|
let records = sqlx::query!(
|
||||||
r#"SELECT
|
r#"SELECT
|
||||||
t.id as "id!: Uuid",
|
t.id AS "id!: Uuid",
|
||||||
t.project_id as "project_id!: Uuid",
|
t.project_id AS "project_id!: Uuid",
|
||||||
t.title,
|
t.title,
|
||||||
t.description,
|
t.description,
|
||||||
t.status as "status!: TaskStatus",
|
t.status AS "status!: TaskStatus",
|
||||||
t.created_at as "created_at!: DateTime<Utc>",
|
t.created_at AS "created_at!: DateTime<Utc>",
|
||||||
t.updated_at as "updated_at!: DateTime<Utc>",
|
t.updated_at AS "updated_at!: DateTime<Utc>",
|
||||||
CASE WHEN in_progress_attempts.task_id IS NOT NULL THEN true ELSE false END as "has_in_progress_attempt!: i64",
|
CASE
|
||||||
CASE WHEN merged_attempts.task_id IS NOT NULL THEN true ELSE false END as "has_merged_attempt!"
|
WHEN in_progress_attempts.task_id IS NOT NULL THEN true
|
||||||
FROM tasks t
|
ELSE false
|
||||||
LEFT JOIN (
|
END AS "has_in_progress_attempt!: i64",
|
||||||
SELECT DISTINCT ta.task_id
|
CASE
|
||||||
FROM task_attempts ta
|
WHEN merged_attempts.task_id IS NOT NULL THEN true
|
||||||
INNER JOIN execution_processes ep ON ta.id = ep.task_attempt_id
|
ELSE false
|
||||||
INNER JOIN (
|
END AS "has_merged_attempt!"
|
||||||
SELECT execution_process_id, MAX(created_at) as latest_created_at
|
FROM tasks t
|
||||||
FROM task_attempt_activities
|
LEFT JOIN (
|
||||||
GROUP BY execution_process_id
|
SELECT DISTINCT ta.task_id
|
||||||
) latest_activity ON ep.id = latest_activity.execution_process_id
|
FROM task_attempts ta
|
||||||
INNER JOIN task_attempt_activities taa ON ep.id = taa.execution_process_id
|
JOIN execution_processes ep
|
||||||
AND taa.created_at = latest_activity.latest_created_at
|
ON ta.id = ep.task_attempt_id
|
||||||
WHERE taa.status IN ('setuprunning', 'executorrunning')
|
JOIN (
|
||||||
) in_progress_attempts ON t.id = in_progress_attempts.task_id
|
-- pick exactly one “latest” activity per process,
|
||||||
LEFT JOIN (
|
-- tiebreaking so that running‐states are lower priority
|
||||||
SELECT DISTINCT ta.task_id
|
SELECT execution_process_id, status
|
||||||
FROM task_attempts ta
|
FROM (
|
||||||
WHERE ta.merge_commit IS NOT NULL
|
SELECT
|
||||||
) merged_attempts ON t.id = merged_attempts.task_id
|
execution_process_id,
|
||||||
WHERE t.project_id = $1
|
status,
|
||||||
ORDER BY t.created_at DESC"#,
|
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
|
project_id
|
||||||
)
|
)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
|
|||||||
@@ -565,7 +565,18 @@ export function TaskDetailsToolbar({
|
|||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isAttemptRunning && !isStopping && (
|
{isStopping || isAttemptRunning ? (
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
size="sm"
|
||||||
|
onClick={onStopAllExecutions}
|
||||||
|
disabled={isStopping}
|
||||||
|
className="gap-2"
|
||||||
|
>
|
||||||
|
<StopCircle className="h-4 w-4" />
|
||||||
|
{isStopping ? 'Stopping...' : 'Stop Attempt'}
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -593,33 +604,16 @@ export function TaskDetailsToolbar({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Special Actions */}
|
{/* Special Actions */}
|
||||||
{(isAttemptRunning ||
|
{!selectedAttempt && !isAttemptRunning && !isStopping && (
|
||||||
isStopping ||
|
|
||||||
(!selectedAttempt && !isAttemptRunning && !isStopping)) && (
|
|
||||||
<div className="space-y-2 pt-3 border-t">
|
<div className="space-y-2 pt-3 border-t">
|
||||||
{(isAttemptRunning || isStopping) && (
|
<Button
|
||||||
<Button
|
onClick={handleEnterCreateAttemptMode}
|
||||||
variant="destructive"
|
size="sm"
|
||||||
size="sm"
|
className="w-full gap-2"
|
||||||
onClick={onStopAllExecutions}
|
>
|
||||||
disabled={isStopping}
|
<Play className="h-4 w-4" />
|
||||||
className="w-full gap-2"
|
Start Attempt
|
||||||
>
|
</Button>
|
||||||
<StopCircle className="h-4 w-4" />
|
|
||||||
{isStopping ? 'Stopping...' : 'Stop Attempt'}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!selectedAttempt && !isAttemptRunning && !isStopping && (
|
|
||||||
<Button
|
|
||||||
onClick={handleEnterCreateAttemptMode}
|
|
||||||
size="sm"
|
|
||||||
className="w-full gap-2"
|
|
||||||
>
|
|
||||||
<Play className="h-4 w-4" />
|
|
||||||
Start Attempt
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user