From bca83c682daf63fca5d928753667d000d36239a4 Mon Sep 17 00:00:00 2001 From: OpenClaw Bot Date: Thu, 26 Feb 2026 13:22:42 -0600 Subject: [PATCH] Signed-off-by: OpenClaw Bot --- components/gantt/BacklogView.tsx | 27 +++++++++++++++++++++------ stores/useTaskStore.ts | 10 ++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/components/gantt/BacklogView.tsx b/components/gantt/BacklogView.tsx index 3a33c54..ff91059 100644 --- a/components/gantt/BacklogView.tsx +++ b/components/gantt/BacklogView.tsx @@ -42,6 +42,15 @@ const typeLabels: Record = { plan: "📐", } +const UNSPRINTED_SENTINELS = new Set(["null", "none", "backlog", "unassigned", "no-sprint", "no_sprint"]) + +const normalizeSprintId = (value: string | undefined): string | undefined => { + if (typeof value !== "string") return undefined + const sprintId = value.trim() + if (!sprintId) return undefined + return UNSPRINTED_SENTINELS.has(sprintId.toLowerCase()) ? undefined : sprintId +} + interface AssignableUser { id: string name: string @@ -296,11 +305,16 @@ export function BacklogView() { const otherSprints = sprints.filter((s) => s.id !== currentSprint?.id) // Get tasks by section + const sprintIds = new Set(sprints.map((s) => s.id)) + const currentSprintTasks = currentSprint - ? tasks.filter((t) => t.sprintId === currentSprint.id) + ? tasks.filter((t) => normalizeSprintId(t.sprintId) === currentSprint.id) : [] - const backlogTasks = tasks.filter((t) => !t.sprintId) + const backlogTasks = tasks.filter((t) => { + const sprintId = normalizeSprintId(t.sprintId) + return !sprintId || !sprintIds.has(sprintId) + }) // Get active task for drag overlay const activeTask = activeId ? tasks.find((t) => t.id === activeId) : null @@ -319,11 +333,12 @@ export function BacklogView() { const overId = over.id as string const overTask = tasks.find((t) => t.id === overId) + const overTaskSprintId = overTask ? normalizeSprintId(overTask.sprintId) : undefined const destinationId = overTask - ? overTask.sprintId - ? currentSprint && overTask.sprintId === currentSprint.id + ? overTaskSprintId + ? currentSprint && overTaskSprintId === currentSprint.id ? "current" - : `sprint-${overTask.sprintId}` + : `sprint-${overTaskSprintId}` : "backlog" : overId @@ -395,7 +410,7 @@ export function BacklogView() { {otherSprints .sort((a, b) => new Date(a.startDate).getTime() - new Date(b.startDate).getTime()) .map((sprint) => { - const sprintTasks = tasks.filter((t) => t.sprintId === sprint.id) + const sprintTasks = tasks.filter((t) => normalizeSprintId(t.sprintId) === sprint.id) console.log(`Sprint ${sprint.name}: ${sprintTasks.length} tasks`, sprintTasks.map(t => t.title)) return ( diff --git a/stores/useTaskStore.ts b/stores/useTaskStore.ts index b8c7cba..1ef7b59 100644 --- a/stores/useTaskStore.ts +++ b/stores/useTaskStore.ts @@ -477,8 +477,18 @@ const normalizeAttachments = (value: unknown): TaskAttachment[] => { .filter((attachment): attachment is TaskAttachment => attachment !== null) } +const UNSPRINTED_SENTINELS = new Set(['null', 'none', 'backlog', 'unassigned', 'no-sprint', 'no_sprint']) + +const normalizeSprintId = (value: unknown): string | undefined => { + if (typeof value !== 'string') return undefined + const sprintId = value.trim() + if (sprintId.length === 0) return undefined + return UNSPRINTED_SENTINELS.has(sprintId.toLowerCase()) ? undefined : sprintId +} + const normalizeTask = (task: Task): Task => ({ ...task, + sprintId: normalizeSprintId(task.sprintId), comments: normalizeComments(task.comments), tags: Array.isArray(task.tags) ? task.tags.filter((tag): tag is string => typeof tag === 'string' && tag.trim().length > 0) : [], attachments: normalizeAttachments(task.attachments),