Skip to content

Commit 8807575

Browse files
Add Start Task button to repositories view
Add a button to create a new task directly from the repositories list and detail views with the repository prepopulated. This streamlines the workflow when users want to start working on a specific repository. - Add defaultRepository prop to CreateTaskModal to prepopulate the form - Add Task01Icon button to repository cards in the list view - Add Task01Icon button to repository detail view header
1 parent 1e3e3e2 commit 8807575

3 files changed

Lines changed: 61 additions & 1 deletion

File tree

src/components/kanban/create-task-modal.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { useBranches, checkIsGitRepo } from '@/hooks/use-filesystem'
4040
import { useWorktreeBasePath, useDefaultGitReposDir } from '@/hooks/use-config'
4141
import { useRepositories, useCreateRepository } from '@/hooks/use-repositories'
4242
import { FilesystemBrowser } from '@/components/ui/filesystem-browser'
43+
import type { Repository } from '@/types'
4344

4445
function slugify(text: string): string {
4546
return text
@@ -58,9 +59,10 @@ function generateBranchName(text: string): string {
5859
interface CreateTaskModalProps {
5960
open?: boolean
6061
onOpenChange?: (open: boolean) => void
62+
defaultRepository?: Repository
6163
}
6264

63-
export function CreateTaskModal({ open: controlledOpen, onOpenChange }: CreateTaskModalProps = {}) {
65+
export function CreateTaskModal({ open: controlledOpen, onOpenChange, defaultRepository }: CreateTaskModalProps = {}) {
6466
const { t } = useTranslation('tasks')
6567
const { t: tc } = useTranslation('common')
6668
const [internalOpen, setInternalOpen] = useState(false)
@@ -116,6 +118,16 @@ export function CreateTaskModal({ open: controlledOpen, onOpenChange }: CreateTa
116118
}
117119
}, [repositories])
118120

121+
// Initialize with default repository when modal opens
122+
useEffect(() => {
123+
if (open && defaultRepository) {
124+
setSelectedRepoId(defaultRepository.id)
125+
setRepoPath(defaultRepository.path)
126+
setRepoSearchQuery(defaultRepository.displayName)
127+
setRepoTab('saved')
128+
}
129+
}, [open, defaultRepository])
130+
119131
// Set default base branch when branches are loaded, reset when repo changes
120132
useEffect(() => {
121133
if (branchData) {

src/routes/repositories/$repoId.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ import {
2323
Loading03Icon,
2424
Alert02Icon,
2525
VisualStudioCodeIcon,
26+
Task01Icon,
2627
} from '@hugeicons/core-free-icons'
2728
import { useHostname, useSshPort } from '@/hooks/use-config'
2829
import { buildVSCodeUrl } from '@/lib/vscode-url'
30+
import { CreateTaskModal } from '@/components/kanban/create-task-modal'
2931

3032
export const Route = createFileRoute('/repositories/$repoId')({
3133
component: RepositoryDetailView,
@@ -44,6 +46,7 @@ function RepositoryDetailView() {
4446
const [startupScript, setStartupScript] = useState('')
4547
const [copyFiles, setCopyFiles] = useState('')
4648
const [hasChanges, setHasChanges] = useState(false)
49+
const [taskModalOpen, setTaskModalOpen] = useState(false)
4750

4851
// Initialize form state when repository loads
4952
useEffect(() => {
@@ -136,6 +139,16 @@ function RepositoryDetailView() {
136139
</div>
137140

138141
<div className="flex items-center gap-2">
142+
<Button
143+
variant="ghost"
144+
size="icon-sm"
145+
onClick={() => setTaskModalOpen(true)}
146+
className="text-muted-foreground hover:text-foreground"
147+
title="Start Task"
148+
>
149+
<HugeiconsIcon icon={Task01Icon} size={14} strokeWidth={2} />
150+
</Button>
151+
139152
<Button
140153
variant="ghost"
141154
size="icon-sm"
@@ -233,6 +246,12 @@ function RepositoryDetailView() {
233246
</FieldGroup>
234247
</div>
235248
</div>
249+
250+
<CreateTaskModal
251+
open={taskModalOpen}
252+
onOpenChange={setTaskModalOpen}
253+
defaultRepository={repository}
254+
/>
236255
</div>
237256
)
238257
}

src/routes/repositories/index.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ import {
4040
CommandLineIcon,
4141
Copy01Icon,
4242
VisualStudioCodeIcon,
43+
Task01Icon,
4344
} from '@hugeicons/core-free-icons'
4445
import { FilesystemBrowser } from '@/components/ui/filesystem-browser'
4546
import { useDefaultGitReposDir, useHostname, useSshPort } from '@/hooks/use-config'
4647
import { buildVSCodeUrl } from '@/lib/vscode-url'
4748
import type { Repository } from '@/types'
49+
import { CreateTaskModal } from '@/components/kanban/create-task-modal'
4850

4951
export const Route = createFileRoute('/repositories/')({
5052
component: RepositoriesView,
@@ -53,9 +55,11 @@ export const Route = createFileRoute('/repositories/')({
5355
function RepositoryCard({
5456
repository,
5557
onDelete,
58+
onStartTask,
5659
}: {
5760
repository: Repository
5861
onDelete: () => Promise<void>
62+
onStartTask: () => void
5963
}) {
6064
const [dialogOpen, setDialogOpen] = useState(false)
6165
const [isDeleting, setIsDeleting] = useState(false)
@@ -69,6 +73,12 @@ function RepositoryCard({
6973
window.open(url, '_blank')
7074
}
7175

76+
const handleStartTask = (e: React.MouseEvent) => {
77+
e.preventDefault()
78+
e.stopPropagation()
79+
onStartTask()
80+
}
81+
7282
const handleDelete = async (e: React.MouseEvent) => {
7383
e.preventDefault()
7484
e.stopPropagation()
@@ -93,6 +103,7 @@ function RepositoryCard({
93103
<div className="flex shrink-0 gap-1">
94104
<div className="size-6" />
95105
<div className="size-6" />
106+
<div className="size-6" />
96107
</div>
97108
</div>
98109

@@ -126,6 +137,16 @@ function RepositoryCard({
126137
</Link>
127138

128139
<div className="absolute right-3 top-3 flex gap-1">
140+
<Button
141+
variant="ghost"
142+
size="icon-sm"
143+
onClick={handleStartTask}
144+
className="shrink-0 text-muted-foreground hover:text-foreground"
145+
title="Start Task"
146+
>
147+
<HugeiconsIcon icon={Task01Icon} size={14} strokeWidth={2} />
148+
</Button>
149+
129150
<Button
130151
variant="ghost"
131152
size="icon-sm"
@@ -326,6 +347,7 @@ function CreateRepositoryDialog() {
326347
function RepositoriesView() {
327348
const { data: repositories, isLoading, error } = useRepositories()
328349
const deleteRepository = useDeleteRepository()
350+
const [taskModalRepo, setTaskModalRepo] = useState<Repository | null>(null)
329351

330352
const handleDelete = async (id: string) => {
331353
await deleteRepository.mutateAsync(id)
@@ -377,10 +399,17 @@ function RepositoriesView() {
377399
key={repo.id}
378400
repository={repo}
379401
onDelete={() => handleDelete(repo.id)}
402+
onStartTask={() => setTaskModalRepo(repo)}
380403
/>
381404
))}
382405
</div>
383406
</div>
407+
408+
<CreateTaskModal
409+
open={taskModalRepo !== null}
410+
onOpenChange={(open) => !open && setTaskModalRepo(null)}
411+
defaultRepository={taskModalRepo ?? undefined}
412+
/>
384413
</div>
385414
)
386415
}

0 commit comments

Comments
 (0)