From 2ad6854fc892f0b4dcdc3af2aa88d61e1679d4c7 Mon Sep 17 00:00:00 2001
From: Louis Knight-Webb
Date: Mon, 16 Jun 2025 22:42:55 -0400
Subject: [PATCH] Fix UI glitches
---
frontend/src/pages/task-details.tsx | 88 ++++++++++++++++++++---------
1 file changed, 62 insertions(+), 26 deletions(-)
diff --git a/frontend/src/pages/task-details.tsx b/frontend/src/pages/task-details.tsx
index d391c424..dcb6e370 100644
--- a/frontend/src/pages/task-details.tsx
+++ b/frontend/src/pages/task-details.tsx
@@ -56,6 +56,7 @@ export function TaskDetailsPage() {
const [taskLoading, setTaskLoading] = useState(true);
const [taskAttempts, setTaskAttempts] = useState([]);
const [taskAttemptsLoading, setTaskAttemptsLoading] = useState(false);
+ const [taskAttemptsInitialLoad, setTaskAttemptsInitialLoad] = useState(true);
const [selectedAttempt, setSelectedAttempt] = useState(
null
);
@@ -75,9 +76,26 @@ export function TaskDetailsPage() {
const [editedStatus, setEditedStatus] = useState("todo");
const [savingTask, setSavingTask] = useState(false);
- // Check if the selected attempt is currently running (latest activity is "inprogress")
- const isAttemptRunning = selectedAttempt && attemptActivities.length > 0 &&
- attemptActivities[0].status === "inprogress";
+ // Check if the selected attempt is currently running (latest activity is "inprogress" or "init")
+ const isAttemptRunning =
+ selectedAttempt &&
+ attemptActivities.length > 0 &&
+ (attemptActivities[0].status === "inprogress" ||
+ attemptActivities[0].status === "init");
+
+ // Polling for updates when attempt is running
+ useEffect(() => {
+ if (!isAttemptRunning || !task) return;
+
+ const interval = setInterval(() => {
+ fetchTaskAttempts(task.id, true); // Background update
+ if (selectedAttempt) {
+ fetchAttemptActivities(selectedAttempt.id, true); // Background update
+ }
+ }, 2000);
+
+ return () => clearInterval(interval);
+ }, [isAttemptRunning, task?.id, selectedAttempt?.id]);
useEffect(() => {
if (projectId && taskId) {
@@ -122,11 +140,18 @@ export function TaskDetailsPage() {
}
};
- const fetchTaskAttempts = async (taskId: string) => {
+ const fetchTaskAttempts = async (
+ taskId: string,
+ isBackgroundUpdate = false
+ ) => {
if (!projectId) return;
try {
- setTaskAttemptsLoading(true);
+ // Show loading for user-initiated actions, not background polling
+ if (!isBackgroundUpdate) {
+ setTaskAttemptsLoading(true);
+ }
+
const response = await makeAuthenticatedRequest(
`/api/projects/${projectId}/tasks/${taskId}/attempts`
);
@@ -135,8 +160,21 @@ export function TaskDetailsPage() {
const result: ApiResponse = await response.json();
if (result.success && result.data) {
setTaskAttempts(result.data);
- // Automatically select the latest attempt if available
- if (result.data.length > 0) {
+ setTaskAttemptsInitialLoad(false);
+
+ // For background updates, preserve the selected attempt
+ if (isBackgroundUpdate && selectedAttempt) {
+ const updatedAttempt = result.data.find(
+ (a) => a.id === selectedAttempt.id
+ );
+ if (updatedAttempt) {
+ setSelectedAttempt(updatedAttempt);
+ return;
+ }
+ }
+
+ // Auto-select latest attempt for initial loads
+ if (result.data.length > 0 && !isBackgroundUpdate) {
const latestAttempt = result.data.reduce((latest, current) =>
new Date(current.created_at) > new Date(latest.created_at)
? current
@@ -152,15 +190,21 @@ export function TaskDetailsPage() {
} catch (err) {
setError("Failed to load task attempts");
} finally {
- setTaskAttemptsLoading(false);
+ if (!isBackgroundUpdate) {
+ setTaskAttemptsLoading(false);
+ }
}
};
- const fetchAttemptActivities = async (attemptId: string) => {
+ const fetchAttemptActivities = async (attemptId: string, isBackgroundUpdate = false) => {
if (!task || !projectId) return;
try {
- setActivitiesLoading(true);
+ // Only show loading for user-initiated actions, not background polling
+ if (!isBackgroundUpdate) {
+ setActivitiesLoading(true);
+ }
+
const response = await makeAuthenticatedRequest(
`/api/projects/${projectId}/tasks/${task.id}/attempts/${attemptId}/activities`
);
@@ -177,7 +221,9 @@ export function TaskDetailsPage() {
} catch (err) {
setError("Failed to load attempt activities");
} finally {
- setActivitiesLoading(false);
+ if (!isBackgroundUpdate) {
+ setActivitiesLoading(false);
+ }
}
};
@@ -357,11 +403,7 @@ export function TaskDetailsPage() {
{isEditMode ? (
<>
-
@@ -500,9 +540,7 @@ export function TaskDetailsPage() {
To Do
-
- In Progress
-
+ In Progress
In Review
Done
Cancelled
@@ -568,7 +606,7 @@ export function TaskDetailsPage() {
- {taskAttemptsLoading ? (
+ {taskAttemptsInitialLoad && taskAttemptsLoading ? (
Loading...
@@ -674,9 +712,7 @@ export function TaskDetailsPage() {
{selectedAttempt.worktree_path}
{activitiesLoading ? (
-
- Loading activities...
-
+ Loading activities...
) : attemptActivities.length === 0 ? (
No activities found