From bfe97fd749a6524fa29cc9e99fc0b8094a2f462b Mon Sep 17 00:00:00 2001 From: Kyle Pope Date: Sun, 22 Feb 2026 11:53:09 +0800 Subject: [PATCH] Fix 5 testing bugs: priority badge width, recurring event errors, nested subtask UI, comment timestamps, close button - Widen priority badge from w-10 to w-14 to fit "medium" text, add "none" case - Guard against null end_datetime in event update validation - Exclude current event from this_and_future DELETE to prevent 404 - Use Python-side datetime.now for comment timestamps (avoids UTC offset) - Hide "Add subtask" button when viewing a subtask (prevents nested nesting) - Add X close button to TaskDetailPanel header on desktop Co-Authored-By: Claude Opus 4.6 --- backend/app/models/task_comment.py | 4 +-- backend/app/routers/events.py | 3 +- .../components/dashboard/UpcomingWidget.tsx | 3 +- .../src/components/projects/ProjectDetail.tsx | 2 ++ .../components/projects/TaskDetailPanel.tsx | 35 +++++++++++++------ 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/backend/app/models/task_comment.py b/backend/app/models/task_comment.py index 3a11516..0a1423a 100644 --- a/backend/app/models/task_comment.py +++ b/backend/app/models/task_comment.py @@ -1,4 +1,4 @@ -from sqlalchemy import Text, Integer, ForeignKey, func +from sqlalchemy import Text, Integer, ForeignKey from sqlalchemy.orm import Mapped, mapped_column, relationship as sa_relationship from datetime import datetime from app.database import Base @@ -12,7 +12,7 @@ class TaskComment(Base): Integer, ForeignKey("project_tasks.id", ondelete="CASCADE"), nullable=False, index=True ) content: Mapped[str] = mapped_column(Text, nullable=False) - created_at: Mapped[datetime] = mapped_column(server_default=func.now()) + created_at: Mapped[datetime] = mapped_column(default=datetime.now) # Relationships task: Mapped["ProjectTask"] = sa_relationship(back_populates="comments") diff --git a/backend/app/routers/events.py b/backend/app/routers/events.py index a3a655c..21c2e92 100644 --- a/backend/app/routers/events.py +++ b/backend/app/routers/events.py @@ -287,7 +287,7 @@ async def update_event( start = update_data.get("start_datetime", event.start_datetime) end_dt = update_data.get("end_datetime", event.end_datetime) - if end_dt < start: + if end_dt is not None and end_dt < start: raise HTTPException(status_code=400, detail="End datetime must be after start datetime") if scope == "this": @@ -316,6 +316,7 @@ async def update_event( delete(CalendarEvent).where( CalendarEvent.parent_event_id == parent_id, CalendarEvent.original_start >= this_original_start, + CalendarEvent.id != event_id, ) ) diff --git a/frontend/src/components/dashboard/UpcomingWidget.tsx b/frontend/src/components/dashboard/UpcomingWidget.tsx index 41c3d95..e09ff81 100644 --- a/frontend/src/components/dashboard/UpcomingWidget.tsx +++ b/frontend/src/components/dashboard/UpcomingWidget.tsx @@ -57,10 +57,11 @@ export default function UpcomingWidget({ items, days = 7 }: UpcomingWidgetProps) {config.label} {item.priority || ''} diff --git a/frontend/src/components/projects/ProjectDetail.tsx b/frontend/src/components/projects/ProjectDetail.tsx index f7f5989..f89de7f 100644 --- a/frontend/src/components/projects/ProjectDetail.tsx +++ b/frontend/src/components/projects/ProjectDetail.tsx @@ -575,6 +575,7 @@ export default function ProjectDetail() { onEdit={(task) => openTaskForm(task, null)} onDelete={handleDeleteTask} onAddSubtask={(parentId) => openTaskForm(null, parentId)} + onClose={() => setSelectedTaskId(null)} /> @@ -603,6 +604,7 @@ export default function ProjectDetail() { onEdit={(task) => openTaskForm(task, null)} onDelete={handleDeleteTask} onAddSubtask={(parentId) => openTaskForm(null, parentId)} + onClose={() => setSelectedTaskId(null)} /> diff --git a/frontend/src/components/projects/TaskDetailPanel.tsx b/frontend/src/components/projects/TaskDetailPanel.tsx index b7c09cd..17f8190 100644 --- a/frontend/src/components/projects/TaskDetailPanel.tsx +++ b/frontend/src/components/projects/TaskDetailPanel.tsx @@ -4,7 +4,7 @@ import { toast } from 'sonner'; import { format, formatDistanceToNow, parseISO } from 'date-fns'; import { Pencil, Trash2, Plus, MessageSquare, ClipboardList, - Calendar, User, Flag, Activity, Send, + Calendar, User, Flag, Activity, Send, X, } from 'lucide-react'; import api, { getErrorMessage } from '@/lib/api'; import type { ProjectTask, TaskComment, Person } from '@/types'; @@ -37,6 +37,7 @@ interface TaskDetailPanelProps { onEdit: (task: ProjectTask) => void; onDelete: (taskId: number) => void; onAddSubtask: (parentId: number) => void; + onClose?: () => void; } export default function TaskDetailPanel({ @@ -45,6 +46,7 @@ export default function TaskDetailPanel({ onEdit, onDelete, onAddSubtask, + onClose, }: TaskDetailPanelProps) { const queryClient = useQueryClient(); const [commentText, setCommentText] = useState(''); @@ -145,6 +147,17 @@ export default function TaskDetailPanel({ > + {onClose && ( + + )} @@ -222,15 +235,17 @@ export default function TaskDetailPanel({ )} - + {!task.parent_task_id && ( + + )} {task.subtasks.length > 0 ? (