-
-
{column.title}
+
+
{column.title}
{tasks.length}
@@ -65,24 +65,21 @@ export function KanbanColumn({ column, tasks, onPreviewTask, onOpenTask, onEditT
{/* Tasks */}
-
- {tasks.length === 0 ? (
-
No tasks yet
- ) : (
- tasks.map((task) => (
-
- ))
- )}
+
+ {tasks.map((task) => (
+
+ ))
+ }
);
diff --git a/apps/web/components/kanban-display-dropdown.tsx b/apps/web/components/kanban-display-dropdown.tsx
index 8aec783ff2..802a8c253a 100644
--- a/apps/web/components/kanban-display-dropdown.tsx
+++ b/apps/web/components/kanban-display-dropdown.tsx
@@ -20,6 +20,7 @@ import { IconAdjustmentsHorizontal } from '@tabler/icons-react';
import { useKanbanDisplaySettings } from '@/hooks/use-kanban-display-settings';
import type { Workspace, Repository } from '@/lib/types/http';
import type { BoardState } from '@/lib/state/slices';
+import { Badge } from '@kandev/ui/badge';
export function KanbanDisplayDropdown() {
const {
@@ -126,7 +127,10 @@ export function KanbanDisplayDropdown() {
onTogglePreviewOnClick?.(!!checked);
}}
/>
-
Open preview on click
+
+ Open preview on click {" "}
+ beta
+
When enabled, clicking a task opens the preview panel. When disabled, clicking navigates directly to the session.
diff --git a/apps/web/components/kanban/kanban-header.tsx b/apps/web/components/kanban/kanban-header.tsx
index c6e5782d9e..c72debc43e 100644
--- a/apps/web/components/kanban/kanban-header.tsx
+++ b/apps/web/components/kanban/kanban-header.tsx
@@ -6,7 +6,6 @@ import { Button } from '@kandev/ui/button';
import { ToggleGroup, ToggleGroupItem } from '@kandev/ui/toggle-group';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@kandev/ui/tooltip';
import { IconPlus, IconSettings, IconList, IconLayoutKanban } from '@tabler/icons-react';
-import { ConnectionStatus } from '../connection-status';
import { KanbanDisplayDropdown } from '../kanban-display-dropdown';
import { TaskSearchInput } from './task-search-input';
import { linkToTasks } from '@/lib/links';
@@ -35,9 +34,8 @@ export function KanbanHeader({ onCreateTask, workspaceId, currentPage = 'kanban'
- KanDev.ai
+ KanDev
-
{onSearchChange && (
diff --git a/apps/web/components/task-create-dialog.tsx b/apps/web/components/task-create-dialog.tsx
index b66553dc87..e6d59d52af 100644
--- a/apps/web/components/task-create-dialog.tsx
+++ b/apps/web/components/task-create-dialog.tsx
@@ -398,7 +398,17 @@ export function TaskCreateDialog({
useEffect(() => {
if (!open || !workspaceId) return;
- if (!repositoryId && !selectedLocalRepo && repositories.length === 1) {
+ if (repositoryId || selectedLocalRepo) return;
+
+ // Priority 1: Last used repository
+ const lastUsedRepoId = getLocalStorage(STORAGE_KEYS.LAST_REPOSITORY_ID, null);
+ if (lastUsedRepoId && repositories.some((repo: Repository) => repo.id === lastUsedRepoId)) {
+ setRepositoryId(lastUsedRepoId);
+ return;
+ }
+
+ // Priority 2: Auto-select if only one repository
+ if (repositories.length === 1) {
setRepositoryId(repositories[0].id);
}
}, [open, repositories, repositoryId, selectedLocalRepo, workspaceId]);
@@ -436,11 +446,22 @@ export function TaskCreateDialog({
useEffect(() => {
if (!repositoryId) return;
- if (!branch) {
- const preferredBranch = selectPreferredBranch(branches);
- if (preferredBranch) {
- setBranch(preferredBranch);
- }
+ if (branch) return;
+
+ // Priority 1: Last used branch
+ const lastUsedBranch = getLocalStorage(STORAGE_KEYS.LAST_BRANCH, null);
+ if (lastUsedBranch && branches.some((b: Branch) => {
+ const displayName = b.type === 'remote' && b.remote ? `${b.remote}/${b.name}` : b.name;
+ return displayName === lastUsedBranch;
+ })) {
+ setBranch(lastUsedBranch);
+ return;
+ }
+
+ // Priority 2: Preferred branch (main/master)
+ const preferredBranch = selectPreferredBranch(branches);
+ if (preferredBranch) {
+ setBranch(preferredBranch);
}
}, [branch, branches, repositoryId]);
@@ -458,6 +479,7 @@ export function TaskCreateDialog({
const workspaceRepo = repositories.find((repo: Repository) => repo.id === value);
if (workspaceRepo) {
setRepositoryId(value);
+ setLocalStorage(STORAGE_KEYS.LAST_REPOSITORY_ID, value);
setDiscoveredRepoPath('');
setSelectedLocalRepo(null);
setLocalBranches([]);
@@ -473,6 +495,12 @@ export function TaskCreateDialog({
setLocalStorage(STORAGE_KEYS.LAST_AGENT_PROFILE_ID, value);
}, []);
+ // Memoized callback for BranchSelector to save selection to localStorage
+ const handleBranchChange = useCallback((value: string) => {
+ setBranch(value);
+ setLocalStorage(STORAGE_KEYS.LAST_BRANCH, value);
+ }, []);
+
const hasRepositorySelection = Boolean(repositoryId || selectedLocalRepo);
const branchOptionsRaw = repositoryId
? branches
@@ -592,6 +620,18 @@ export function TaskCreateDialog({
useEffect(() => {
if (repositoryId || localBranches.length === 0) return;
if (branch) return;
+
+ // Priority 1: Last used branch
+ const lastUsedBranch = getLocalStorage(STORAGE_KEYS.LAST_BRANCH, null);
+ if (lastUsedBranch && localBranches.some((b: Branch) => {
+ const displayName = b.type === 'remote' && b.remote ? `${b.remote}/${b.name}` : b.name;
+ return displayName === lastUsedBranch;
+ })) {
+ setBranch(lastUsedBranch);
+ return;
+ }
+
+ // Priority 2: Preferred branch (main/master)
const preferredBranch = selectPreferredBranch(localBranches);
if (preferredBranch) {
setBranch(preferredBranch);
@@ -931,34 +971,34 @@ export function TaskCreateDialog({
disabled={!workspaceId || repositoriesLoading || discoverReposLoading || isEditMode}
/>
-
- 0
- ? 'Select branch'
- : 'No branches found'
- }
- searchPlaceholder="Search branches..."
- emptyMessage="No branch found."
- disabled={
- isEditMode ||
- !hasRepositorySelection ||
- (repositoryId && branchesLoading) ||
- (!repositoryId && (localBranchesLoading || branchOptions.length === 0))
- }
- />
-
+
+ 0
+ ? 'Select branch'
+ : 'No branches found'
+ }
+ searchPlaceholder="Search branches..."
+ emptyMessage="No branch found."
+ disabled={
+ isEditMode ||
+ !hasRepositorySelection ||
+ (repositoryId && branchesLoading) ||
+ (!repositoryId && (localBranchesLoading || branchOptions.length === 0))
+ }
+ />
+
{startAgent && (
{agentProfiles.length === 0 && !agentProfilesLoading ? (
@@ -969,19 +1009,19 @@ export function TaskCreateDialog({
) : (
-
+
)}
)}
diff --git a/apps/web/lib/settings/constants.ts b/apps/web/lib/settings/constants.ts
index 2aebc158b8..3a74075438 100644
--- a/apps/web/lib/settings/constants.ts
+++ b/apps/web/lib/settings/constants.ts
@@ -2,6 +2,8 @@ export const STORAGE_KEYS = {
BACKEND_URL: 'kandev.settings.backendUrl',
ONBOARDING_COMPLETED: 'kandev.onboarding.completed',
LAST_AGENT_PROFILE_ID: 'kandev.dialog.lastAgentProfileId',
+ LAST_REPOSITORY_ID: 'kandev.dialog.lastRepositoryId',
+ LAST_BRANCH: 'kandev.dialog.lastBranch',
} as const;
export const DEFAULT_BACKEND_URL = 'http://localhost:8080';