feat(kanban): add refresh button to manually reload tasks (#548)
* feat(kanban): add refresh button to manually reload tasks - Add Refresh button in Kanban Board header - Show spinning animation while refreshing - Add handleRefreshTasks handler in App component - Pass onRefresh and isRefreshing props to KanbanBoard This helps when the UI doesn't update or when tasks are stuck, giving users a way to manually refresh task state. * fix: use ml-auto instead of justify-between for flexible layout Apply code review suggestion to improve layout flexibility by using ml-auto on the right-side controls instead of justify-between on parent.
This commit is contained in:
@@ -85,6 +85,7 @@ export function App() {
|
||||
const [settingsInitialProjectSection, setSettingsInitialProjectSection] = useState<ProjectSettingsSection | undefined>(undefined);
|
||||
const [activeView, setActiveView] = useState<SidebarView>('kanban');
|
||||
const [isOnboardingWizardOpen, setIsOnboardingWizardOpen] = useState(false);
|
||||
const [isRefreshingTasks, setIsRefreshingTasks] = useState(false);
|
||||
|
||||
// Initialize dialog state
|
||||
const [showInitDialog, setShowInitDialog] = useState(false);
|
||||
@@ -373,6 +374,17 @@ export function App() {
|
||||
setSelectedTask(task);
|
||||
};
|
||||
|
||||
const handleRefreshTasks = async () => {
|
||||
const currentProjectId = activeProjectId || selectedProjectId;
|
||||
if (!currentProjectId) return;
|
||||
setIsRefreshingTasks(true);
|
||||
try {
|
||||
await loadTasks(currentProjectId);
|
||||
} finally {
|
||||
setIsRefreshingTasks(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCloseTaskDetail = () => {
|
||||
setSelectedTask(null);
|
||||
};
|
||||
@@ -626,6 +638,8 @@ export function App() {
|
||||
tasks={tasks}
|
||||
onTaskClick={handleTaskClick}
|
||||
onNewTaskClick={() => setIsNewTaskDialogOpen(true)}
|
||||
onRefresh={handleRefreshTasks}
|
||||
isRefreshing={isRefreshingTasks}
|
||||
/>
|
||||
)}
|
||||
{/* TerminalGrid is always mounted but hidden when not active to preserve terminal state */}
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
sortableKeyboardCoordinates,
|
||||
verticalListSortingStrategy
|
||||
} from '@dnd-kit/sortable';
|
||||
import { Plus, Inbox, Loader2, Eye, CheckCircle2, Archive } from 'lucide-react';
|
||||
import { Plus, Inbox, Loader2, Eye, CheckCircle2, Archive, RefreshCw } from 'lucide-react';
|
||||
import { ScrollArea } from './ui/scroll-area';
|
||||
import { Button } from './ui/button';
|
||||
import { Checkbox } from './ui/checkbox';
|
||||
@@ -33,6 +33,8 @@ interface KanbanBoardProps {
|
||||
tasks: Task[];
|
||||
onTaskClick: (task: Task) => void;
|
||||
onNewTaskClick?: () => void;
|
||||
onRefresh?: () => void;
|
||||
isRefreshing?: boolean;
|
||||
}
|
||||
|
||||
interface DroppableColumnProps {
|
||||
@@ -209,7 +211,7 @@ function DroppableColumn({ status, tasks, onTaskClick, isOver, onAddClick, onArc
|
||||
);
|
||||
}
|
||||
|
||||
export function KanbanBoard({ tasks, onTaskClick, onNewTaskClick }: KanbanBoardProps) {
|
||||
export function KanbanBoard({ tasks, onTaskClick, onNewTaskClick, onRefresh, isRefreshing }: KanbanBoardProps) {
|
||||
const [activeTask, setActiveTask] = useState<Task | null>(null);
|
||||
const [overColumnId, setOverColumnId] = useState<string | null>(null);
|
||||
const [showArchived, setShowArchived] = useState(false);
|
||||
@@ -337,8 +339,22 @@ export function KanbanBoard({ tasks, onTaskClick, onNewTaskClick }: KanbanBoardP
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
{/* Kanban header with filters */}
|
||||
<div className="flex items-center justify-end px-6 py-3 border-b border-border/50">
|
||||
<div className="flex items-center px-6 py-3 border-b border-border/50">
|
||||
<div className="flex items-center gap-2">
|
||||
{onRefresh && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={onRefresh}
|
||||
disabled={isRefreshing}
|
||||
className="gap-2"
|
||||
>
|
||||
<RefreshCw className={cn("h-4 w-4", isRefreshing && "animate-spin")} />
|
||||
{isRefreshing ? 'Refreshing...' : 'Refresh'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<Checkbox
|
||||
id="showArchived"
|
||||
checked={showArchived}
|
||||
|
||||
Reference in New Issue
Block a user