summaryrefslogtreecommitdiff
path: root/makima/frontend/src/routes
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-18 18:02:08 +0000
committerGitHub <noreply@github.com>2026-01-18 18:02:08 +0000
commite0da93a20a965125ba4cbb46e3e0e179f06c2a08 (patch)
tree5d127394e1dfa921c5d09fe8f10d716f6548d168 /makima/frontend/src/routes
parent869f21ee2efaefed6a5aa4fbd417c25df8dec02a (diff)
downloadsoryu-e0da93a20a965125ba4cbb46e3e0e179f06c2a08.tar.gz
soryu-e0da93a20a965125ba4cbb46e3e0e179f06c2a08.zip
Improve Mesh Tab: Organize by contract with status filter (#5)
* Add status filter toggle to Mesh Tab TaskList component Add a filter toggle at the top of the TaskList that allows filtering by contract status (All, Active, Completed, Archive) with Active as the default. Changes: - Backend: Add contract_status field to TaskSummary struct in models.rs - Backend: Update all SQL queries returning TaskSummary to include c.status as contract_status from the contracts table join - Frontend: Add contractStatus to TaskSummary TypeScript type - Frontend: Add useState for statusFilter with 'active' as default - Frontend: Add filter button group in header area next to '+ New Task' - Frontend: Update groupedTasks useMemo to filter based on contract status - Frontend: Update empty state message to reflect current filter Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Task completion checkpoint * feat(mesh): show all contract tasks for supervisor tasks When viewing a supervisor task (task.isSupervisor === true), the TaskDetail component now shows all tasks in the contract instead of showing the subtasks tree. Changes: - Add contractTasks prop to TaskDetailProps for passing contract tasks - Add displayTasks computed value that uses contractTasks for supervisors - Change section header from "Subtasks" to "Contract Tasks" for supervisors - Hide the "+ Add Subtask" button for supervisor tasks - Update empty state message for supervisors - Fetch contract tasks in mesh.tsx when viewing a supervisor task - Filter out the supervisor itself from the contract tasks list Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Task completion checkpoint * Task completion checkpoint --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'makima/frontend/src/routes')
-rw-r--r--makima/frontend/src/routes/mesh.tsx25
1 files changed, 24 insertions, 1 deletions
diff --git a/makima/frontend/src/routes/mesh.tsx b/makima/frontend/src/routes/mesh.tsx
index cc09bca..a8d3574 100644
--- a/makima/frontend/src/routes/mesh.tsx
+++ b/makima/frontend/src/routes/mesh.tsx
@@ -7,7 +7,7 @@ import { TaskOutput } from "../components/mesh/TaskOutput";
import { UnifiedMeshChatInput } from "../components/mesh/UnifiedMeshChatInput";
import { useTasks } from "../hooks/useTasks";
import { useTaskSubscription, type TaskUpdateEvent, type TaskOutputEvent } from "../hooks/useTaskSubscription";
-import type { TaskWithSubtasks, MeshChatContext, ContractSummary, ContractWithRelations, DaemonDirectory } from "../lib/api";
+import type { TaskWithSubtasks, MeshChatContext, ContractSummary, ContractWithRelations, DaemonDirectory, TaskSummary } from "../lib/api";
import { startTask as startTaskApi, stopTask as stopTaskApi, getTaskOutput, listContracts, getContract, getDaemonDirectories, continueTask as continueTaskApi, resumeSupervisor } from "../lib/api";
import { DirectoryInput } from "../components/mesh/DirectoryInput";
import { useAuth } from "../contexts/AuthContext";
@@ -119,6 +119,8 @@ export default function MeshPage() {
// Track which subtask's output we're viewing (null = parent task)
const [viewingSubtaskId, setViewingSubtaskId] = useState<string | null>(null);
const [viewingSubtaskName, setViewingSubtaskName] = useState<string | null>(null);
+ // For supervisor tasks: all tasks in the contract (excluding the supervisor itself)
+ const [contractTasks, setContractTasks] = useState<TaskSummary[]>([]);
// View mode for the split panel layout
const [viewMode, setViewMode] = useState<ViewMode>("split");
// Width of the task panel as a percentage (0-100)
@@ -309,6 +311,26 @@ export default function MeshPage() {
}
}, [id, fetchTask]);
+ // For supervisor tasks: fetch all tasks in the contract (excluding the supervisor itself)
+ useEffect(() => {
+ if (taskDetail?.isSupervisor && taskDetail.contractId) {
+ getContract(taskDetail.contractId)
+ .then((contract) => {
+ // Filter out the supervisor task itself
+ const tasksExcludingSupervisor = contract.tasks.filter(
+ (t) => t.id !== taskDetail.id
+ );
+ setContractTasks(tasksExcludingSupervisor);
+ })
+ .catch((err) => {
+ console.error("Failed to fetch contract tasks for supervisor:", err);
+ setContractTasks([]);
+ });
+ } else {
+ setContractTasks([]);
+ }
+ }, [taskDetail?.isSupervisor, taskDetail?.contractId, taskDetail?.id]);
+
const handleSelectTask = useCallback(
(taskId: string) => {
navigate(`/mesh/${taskId}`);
@@ -711,6 +733,7 @@ export default function MeshPage() {
onToggleSubtaskOutput={handleToggleSubtaskOutput}
viewingSubtaskId={viewingSubtaskId}
onViewContract={(contractId) => navigate(`/contracts/${contractId}`)}
+ contractTasks={taskDetail.isSupervisor ? contractTasks : undefined}
/>
</div>
)}