1+ import {
2+ DiamondIcon ,
3+ FilesIcon ,
4+ GithubLogoIcon ,
5+ } from "@phosphor-icons/react" ;
16import {
27 Cross2Icon ,
38 EnterFullScreenIcon ,
49 ExitFullScreenIcon ,
510} from "@radix-ui/react-icons" ;
611import {
712 Button ,
13+ Callout ,
14+ DataList ,
815 Dialog ,
916 Flex ,
1017 IconButton ,
@@ -18,7 +25,9 @@ import { useHotkeys } from "react-hotkeys-hook";
1825import { useIntegrations , useRepositories } from "../hooks/useIntegrations" ;
1926import { useCreateTask } from "../hooks/useTasks" ;
2027import { useWorkflows } from "../hooks/useWorkflows" ;
28+ import { useAuthStore } from "../stores/authStore" ;
2129import { useTabStore } from "../stores/tabStore" ;
30+ import { useTaskExecutionStore } from "../stores/taskExecutionStore" ;
2231import { Combobox } from "./Combobox" ;
2332import { RichTextEditor } from "./RichTextEditor" ;
2433
@@ -28,10 +37,12 @@ interface TaskCreateProps {
2837}
2938
3039export function TaskCreate ( { open, onOpenChange } : TaskCreateProps ) {
31- const { mutate : createTask , isPending : isLoading } = useCreateTask ( ) ;
40+ const { mutate : createTask , isPending : isLoading , error } = useCreateTask ( ) ;
3241 const { createTab } = useTabStore ( ) ;
3342 const { data : integrations = [ ] } = useIntegrations ( ) ;
3443 const { data : workflows = [ ] } = useWorkflows ( ) ;
44+ const { client, isAuthenticated } = useAuthStore ( ) ;
45+ const { setRepoPath : saveRepoPath , setRepoWorkingDir } = useTaskExecutionStore ( ) ;
3546
3647 const githubIntegration = useMemo (
3748 ( ) => integrations . find ( ( i ) => i . kind === "github" ) ,
@@ -57,6 +68,16 @@ export function TaskCreate({ open, onOpenChange }: TaskCreateProps) {
5768 [ workflows ] ,
5869 ) ;
5970
71+ const displayRepoPath = useMemo ( ( ) => {
72+ if ( ! repoPath ) return null ;
73+ // Replace home directory with ~
74+ const homeDirPattern = / ^ \/ U s e r s \/ [ ^ / ] + / ; // macOS/Linux pattern
75+ if ( homeDirPattern . test ( repoPath ) ) {
76+ return repoPath . replace ( homeDirPattern , "~" ) ;
77+ }
78+ return repoPath ;
79+ } , [ repoPath ] ) ;
80+
6081 const { register, handleSubmit, reset, control } = useForm ( {
6182 defaultValues : {
6283 title : "" ,
@@ -72,8 +93,14 @@ export function TaskCreate({ open, onOpenChange }: TaskCreateProps) {
7293 repository : string ;
7394 workflow : string ;
7495 } ) => {
75- if ( ! data . title . trim ( ) || ! data . description . trim ( ) || ! data . workflow )
96+
97+ if ( ! isAuthenticated || ! client ) {
98+ return ;
99+ }
100+
101+ if ( ! data . title . trim ( ) || ! data . description . trim ( ) || ! data . workflow ) {
76102 return ;
103+ }
77104
78105 let repositoryConfig :
79106 | { organization : string ; repository : string }
@@ -95,16 +122,32 @@ export function TaskCreate({ open, onOpenChange }: TaskCreateProps) {
95122 } ,
96123 {
97124 onSuccess : ( newTask ) => {
125+
126+ // Save the local working directory to the task execution store
127+ if ( repoPath ) {
128+ saveRepoPath ( newTask . id , repoPath ) ;
129+
130+ // Also save the mapping for GitHub repos to reuse later
131+ if ( repositoryConfig ) {
132+ const repoKey = `${ repositoryConfig . organization } /${ repositoryConfig . repository } ` ;
133+ setRepoWorkingDir ( repoKey , repoPath ) ;
134+ }
135+ }
136+
98137 createTab ( {
99138 type : "task-detail" ,
100139 title : newTask . title ,
101140 data : newTask ,
102141 } ) ;
103142 reset ( ) ;
143+ setRepoPath ( null ) ; // Reset the local repo path for next task
104144 if ( ! createMore ) {
105145 onOpenChange ( false ) ;
106146 }
107147 } ,
148+ onError : ( error ) => {
149+ console . error ( "Failed to create task:" , error ) ;
150+ } ,
108151 } ,
109152 ) ;
110153 } ;
@@ -201,48 +244,49 @@ export function TaskCreate({ open, onOpenChange }: TaskCreateProps) {
201244 />
202245 </ Flex >
203246
204- { /* Local Working Directory - Primary Step */ }
205- < Flex direction = "column" gap = "3" >
206- < Flex direction = "column" gap = "2" >
207- < Text size = "2" weight = "medium" color = "gray" >
208- Local Working Directory
209- </ Text >
210- < Button
211- variant = { repoPath ? "soft" : "classic" }
212- size = "3"
213- onClick = { async ( ) => {
214- const selected = await window . electronAPI ?. selectDirectory ( ) ;
215- if ( selected ) {
216- setRepoPath ( selected ) ;
217- }
218- } }
219- style = { {
220- justifyContent : "flex-start" ,
221- backgroundColor : repoPath ? "var(--gray-a3)" : undefined ,
222- } }
223- >
247+ { /* Configuration */ }
248+ < DataList . Root >
249+ < DataList . Item >
250+ < DataList . Label > Working Directory</ DataList . Label >
251+ < DataList . Value >
224252 { repoPath ? (
225- < >
226- 📁 { repoPath . split ( '/' ) . pop ( ) || repoPath }
227- < Text size = "1" color = "gray" ml = "2" >
228- (Click to change)
229- </ Text >
230- </ >
253+ < Button
254+ size = "1"
255+ variant = "outline"
256+ color = "gray"
257+ onClick = { async ( ) => {
258+ const selected = await window . electronAPI ?. selectDirectory ( ) ;
259+ if ( selected ) {
260+ setRepoPath ( selected ) ;
261+ }
262+ } }
263+ >
264+ < FilesIcon />
265+ { displayRepoPath }
266+ </ Button >
231267 ) : (
232- "Choose Local Directory"
268+ < Button
269+ size = "1"
270+ variant = "outline"
271+ color = "gray"
272+ onClick = { async ( ) => {
273+ const selected = await window . electronAPI ?. selectDirectory ( ) ;
274+ if ( selected ) {
275+ setRepoPath ( selected ) ;
276+ }
277+ } }
278+ >
279+ < FilesIcon />
280+ Choose folder
281+ </ Button >
233282 ) }
234- </ Button >
235- </ Flex >
283+ </ DataList . Value >
284+ </ DataList . Item >
236285
237- { /* Configuration Row */ }
238- < Flex gap = "3" wrap = "wrap" >
239- { /* Workflow Selection */ }
240-
241- { workflowOptions . length > 0 && (
242- < Flex direction = "column" gap = "2" style = { { minWidth : "200px" , flex : 1 } } >
243- < Text size = "2" weight = "medium" color = "gray" >
244- Workflow *
245- </ Text >
286+ { workflowOptions . length > 0 && (
287+ < DataList . Item >
288+ < DataList . Label > Workflow</ DataList . Label >
289+ < DataList . Value >
246290 < Controller
247291 name = "workflow"
248292 control = { control }
@@ -255,23 +299,21 @@ export function TaskCreate({ open, onOpenChange }: TaskCreateProps) {
255299 placeholder = "Select a workflow..."
256300 searchPlaceholder = "Search workflows..."
257301 emptyMessage = "No workflows found"
258- size = "2"
302+ size = "1"
303+ variant = "outline"
304+ icon = { < DiamondIcon /> }
259305 side = "top"
260306 />
261307 ) }
262308 />
263- </ Flex >
264- ) }
309+ </ DataList . Value >
310+ </ DataList . Item >
311+ ) }
265312
266- { /* GitHub Repository Integration */ }
267- { repositories . length > 0 && (
268- < Flex direction = "column" gap = "2" style = { { minWidth : "200px" , flex : 1 } } >
269- < Text size = "2" weight = "medium" color = "gray" >
270- GitHub Repository
271- < Text size = "1" color = "gray" ml = "1" >
272- (For PRs & tracking )
273- </ Text >
274- </ Text >
313+ { repositories . length > 0 && (
314+ < DataList . Item >
315+ < DataList . Label > Repository</ DataList . Label >
316+ < DataList . Value >
275317 < Controller
276318 name = "repository"
277319 control = { control }
@@ -286,15 +328,41 @@ export function TaskCreate({ open, onOpenChange }: TaskCreateProps) {
286328 placeholder = "Select GitHub repo..."
287329 searchPlaceholder = "Search repositories..."
288330 emptyMessage = "No repositories found"
289- size = "2"
331+ size = "1"
332+ variant = "outline"
333+ icon = { < GithubLogoIcon /> }
290334 side = "top"
291335 />
292336 ) }
293337 />
294- </ Flex >
295- ) }
296- </ Flex >
297- </ Flex >
338+ </ DataList . Value >
339+ </ DataList . Item >
340+ ) }
341+ </ DataList . Root >
342+
343+ { error && (
344+ < Callout . Root color = "red" size = "1" >
345+ < Callout . Text >
346+ Failed to create task: { error instanceof Error ? error . message : "Unknown error" }
347+ </ Callout . Text >
348+ </ Callout . Root >
349+ ) }
350+
351+ { ! isAuthenticated && (
352+ < Callout . Root color = "orange" size = "1" >
353+ < Callout . Text >
354+ Not authenticated - please check your connection
355+ </ Callout . Text >
356+ </ Callout . Root >
357+ ) }
358+
359+ { workflows . length === 0 && (
360+ < Callout . Root color = "orange" size = "1" >
361+ < Callout . Text >
362+ No workflows available - please create a workflow first
363+ </ Callout . Text >
364+ </ Callout . Root >
365+ ) }
298366
299367 < Flex gap = "3" justify = "end" align = "end" >
300368 < Text as = "label" size = "1" style = { { cursor : "pointer" } } >
@@ -309,7 +377,11 @@ export function TaskCreate({ open, onOpenChange }: TaskCreateProps) {
309377 </ Text >
310378 </ Flex >
311379 </ Text >
312- < Button type = "submit" variant = "classic" disabled = { isLoading } >
380+ < Button
381+ type = "submit"
382+ variant = "classic"
383+ disabled = { isLoading || ! isAuthenticated || workflows . length === 0 }
384+ >
313385 { isLoading ? "Creating..." : "Create task" }
314386 </ Button >
315387 </ Flex >
0 commit comments