@@ -170,12 +170,38 @@ export default function Page() {
170170 return < div > </ div > ;
171171 }
172172
173+ const params = useParams ( ) ;
174+ const queueFetcher = useFetcher < typeof queuesLoader > ( ) ;
175+
176+ useEffect ( ( ) => {
177+ if ( params . organizationSlug && params . projectParam && params . envParam ) {
178+ const searchParams = new URLSearchParams ( ) ;
179+ searchParams . set ( "type" , "custom" ) ;
180+ searchParams . set ( "per_page" , "100" ) ;
181+
182+ queueFetcher . load (
183+ `/resources/orgs/${ params . organizationSlug } /projects/${ params . projectParam } /env/${
184+ params . envParam
185+ } /queues?${ searchParams . toString ( ) } `
186+ ) ;
187+ }
188+ } , [ params . organizationSlug , params . projectParam , params . envParam ] ) ;
189+
190+ const defaultTaskQueue = result . task . queue ;
191+ const queues = useMemo ( ( ) => {
192+ const customQueues = queueFetcher . data ?. queues ?? [ ] ;
193+
194+ return defaultTaskQueue && ! customQueues . some ( ( q ) => q . id === defaultTaskQueue . id )
195+ ? [ defaultTaskQueue , ...customQueues ]
196+ : customQueues ;
197+ } , [ queueFetcher . data ?. queues , defaultTaskQueue ] ) ;
198+
173199 switch ( result . task . triggerSource ) {
174200 case "STANDARD" : {
175201 return (
176202 < StandardTaskForm
177203 task = { result . task . task }
178- defaultQueue = { result . task . queue }
204+ queues = { queues }
179205 runs = { result . task . runs }
180206 versions = { result . task . latestVersions }
181207 disableVersionSelection = { result . disableVersionSelection }
@@ -193,6 +219,9 @@ export default function Page() {
193219 />
194220 ) ;
195221 }
222+ default : {
223+ return result . task satisfies never ;
224+ }
196225 }
197226}
198227
@@ -209,14 +238,14 @@ const machinePresets = [
209238
210239function StandardTaskForm ( {
211240 task,
212- defaultQueue ,
241+ queues ,
213242 runs,
214243 versions,
215244 disableVersionSelection,
216245 allowArbitraryQueues,
217246} : {
218247 task : TestTask [ "task" ] ;
219- defaultQueue : TestTask [ "queue" ] ;
248+ queues : Required < TestTask > [ "queue" ] [ ] ;
220249 runs : StandardRun [ ] ;
221250 versions : string [ ] ;
222251 disableVersionSelection : boolean ;
@@ -225,7 +254,6 @@ function StandardTaskForm({
225254 const environment = useEnvironment ( ) ;
226255 const { value, replace } = useSearchParams ( ) ;
227256 const tab = value ( "tab" ) ;
228- const params = useParams ( ) ;
229257
230258 //form submission
231259 const lastSubmission = useActionData ( ) ;
@@ -270,50 +298,14 @@ function StandardTaskForm({
270298 ) ;
271299 const [ tagsValue , setTagsValue ] = useState < string [ ] > ( selectedCodeSample ?. runTags ?? [ ] ) ;
272300
273- const queueFetcher = useFetcher < typeof queuesLoader > ( ) ;
274-
275- useEffect ( ( ) => {
276- if ( params . organizationSlug && params . projectParam && params . envParam ) {
277- const searchParams = new URLSearchParams ( ) ;
278- searchParams . set ( "type" , "custom" ) ;
279- searchParams . set ( "per_page" , "100" ) ;
280-
281- queueFetcher . load (
282- `/resources/orgs/${ params . organizationSlug } /projects/${ params . projectParam } /env/${
283- params . envParam
284- } /queues?${ searchParams . toString ( ) } `
285- ) ;
286- }
287- } , [ params . organizationSlug , params . projectParam , params . envParam ] ) ;
288-
289- const queues = useMemo ( ( ) => {
290- const defaultQueueItem = defaultQueue
291- ? {
292- value : defaultQueue . type === "task" ? `task/${ defaultQueue . name } ` : defaultQueue . name ,
293- label : defaultQueue . name ,
294- type : defaultQueue . type ,
295- paused : defaultQueue . paused ,
296- }
297- : undefined ;
298-
299- if ( ! queueFetcher . data ?. queues ) {
300- return defaultQueueItem ? [ defaultQueueItem ] : [ ] ;
301- }
302-
303- const customQueues = queueFetcher . data ?. queues . map ( ( queue ) => ( {
304- value : queue . name ,
305- label : queue . name ,
306- type : queue . type ,
307- paused : queue . paused ,
308- } ) ) ;
309-
310- return defaultQueueItem && ! customQueues . some ( ( q ) => q . value === defaultQueueItem . value )
311- ? [ defaultQueueItem , ...customQueues ]
312- : customQueues ;
313- } , [ queueFetcher . data ?. queues , defaultQueue ] ) ;
301+ const queueItems = queues . map ( ( q ) => ( {
302+ value : q . type === "task" ? `task/${ q . name } ` : q . name ,
303+ label : q . name ,
304+ type : q . type ,
305+ paused : q . paused ,
306+ } ) ) ;
314307
315308 const fetcher = useFetcher ( ) ;
316- const [ isRecentRunsPopoverOpen , setIsRecentRunsPopoverOpen ] = useState ( false ) ;
317309 const [
318310 form ,
319311 {
@@ -379,67 +371,21 @@ function StandardTaskForm({
379371 </ TabButton >
380372 </ div >
381373 < div className = "flex items-center gap-3" >
382- < Popover open = { isRecentRunsPopoverOpen } onOpenChange = { setIsRecentRunsPopoverOpen } >
383- < PopoverTrigger asChild >
384- { runs . length === 0 ? (
385- < SimpleTooltip
386- button = {
387- < Button
388- type = "button"
389- variant = "tertiary/small"
390- LeadingIcon = { ClockIcon }
391- disabled = { true }
392- >
393- Recent runs
394- </ Button >
395- }
396- content = "No runs yet"
397- />
398- ) : (
399- < Button type = "button" variant = "tertiary/small" LeadingIcon = { ClockIcon } >
400- Recent runs
401- </ Button >
402- ) }
403- </ PopoverTrigger >
404- < PopoverContent className = "min-w-[279px] p-0" align = "end" sideOffset = { 6 } >
405- < div className = "max-h-80 overflow-y-auto" >
406- < div className = "p-1" >
407- { runs . map ( ( run ) => (
408- < button
409- key = { run . id }
410- type = "button"
411- onClick = { ( ) => {
412- setPayload ( run . payload ) ;
413- run . seedMetadata && setMetadata ( run . seedMetadata ) ;
414- setSelectedCodeSampleId ( run . id ) ;
415- setIsRecentRunsPopoverOpen ( false ) ;
416- setTtlValue ( run . ttlSeconds ) ;
417- setConcurrencyKeyValue ( run . concurrencyKey ) ;
418- setMaxAttemptsValue ( run . maxAttempts ) ;
419- setMaxDurationValue ( run . maxDurationInSeconds ) ;
420- setTagsValue ( run . runTags ?? [ ] ) ;
421- setQueueValue ( run . queue ) ;
422- setMachineValue ( run . machinePreset ) ;
423- } }
424- className = "flex w-full items-center gap-2 rounded-sm px-2 py-2 outline-none transition-colors focus-custom hover:bg-charcoal-900 "
425- >
426- < div className = "flex flex-col items-start" >
427- < Paragraph variant = "small" >
428- < DateTime date = { run . createdAt } showTooltip = { false } />
429- </ Paragraph >
430- < div className = "flex items-center gap-2 text-xs text-text-dimmed" >
431- < div >
432- Run < span className = "font-mono" > { run . friendlyId . slice ( - 8 ) } </ span >
433- </ div >
434- < TaskRunStatusCombo status = { run . status } />
435- </ div >
436- </ div >
437- </ button >
438- ) ) }
439- </ div >
440- </ div >
441- </ PopoverContent >
442- </ Popover >
374+ < RecentRunsPopover
375+ runs = { runs }
376+ onRunSelected = { ( run ) => {
377+ setPayload ( run . payload ) ;
378+ run . seedMetadata && setMetadata ( run . seedMetadata ) ;
379+ setSelectedCodeSampleId ( run . id ) ;
380+ setTtlValue ( run . ttlSeconds ) ;
381+ setConcurrencyKeyValue ( run . concurrencyKey ) ;
382+ setMaxAttemptsValue ( run . maxAttempts ) ;
383+ setMaxDurationValue ( run . maxDurationInSeconds ) ;
384+ setTagsValue ( run . runTags ?? [ ] ) ;
385+ setQueueValue ( run . queue ) ;
386+ setMachineValue ( run . machinePreset ) ;
387+ } }
388+ />
443389 </ div >
444390 </ TabContainer >
445391 < ResizablePanelGroup orientation = "horizontal" >
@@ -524,7 +470,7 @@ function StandardTaskForm({
524470 placeholder = "Select queue"
525471 variant = "tertiary/small"
526472 dropdownIcon
527- items = { queues }
473+ items = { queueItems }
528474 filter = { { keys : [ "label" ] } }
529475 value = { queueValue }
530476 setValue = { setQueueValue }
@@ -892,3 +838,68 @@ function ScheduledTaskForm({
892838 </ Form >
893839 ) ;
894840}
841+
842+ function RecentRunsPopover < T extends StandardRun | ScheduledRun > ( {
843+ runs,
844+ onRunSelected,
845+ } : {
846+ runs : T [ ] ;
847+ onRunSelected : ( run : T ) => void ;
848+ } ) {
849+ const [ isRecentRunsPopoverOpen , setIsRecentRunsPopoverOpen ] = useState ( false ) ;
850+
851+ return (
852+ < Popover open = { isRecentRunsPopoverOpen } onOpenChange = { setIsRecentRunsPopoverOpen } >
853+ < PopoverTrigger asChild >
854+ { runs . length === 0 ? (
855+ < SimpleTooltip
856+ button = {
857+ < Button
858+ type = "button"
859+ variant = "tertiary/small"
860+ LeadingIcon = { ClockIcon }
861+ disabled = { true }
862+ >
863+ Recent runs
864+ </ Button >
865+ }
866+ content = "No runs yet"
867+ />
868+ ) : (
869+ < Button type = "button" variant = "tertiary/small" LeadingIcon = { ClockIcon } >
870+ Recent runs
871+ </ Button >
872+ ) }
873+ </ PopoverTrigger >
874+ < PopoverContent className = "min-w-[279px] p-0" align = "end" sideOffset = { 6 } >
875+ < div className = "max-h-80 overflow-y-auto" >
876+ < div className = "p-1" >
877+ { runs . map ( ( run ) => (
878+ < button
879+ key = { run . id }
880+ type = "button"
881+ onClick = { ( ) => {
882+ onRunSelected ( run ) ;
883+ setIsRecentRunsPopoverOpen ( false ) ;
884+ } }
885+ className = "flex w-full items-center gap-2 rounded-sm px-2 py-2 outline-none transition-colors focus-custom hover:bg-charcoal-900 "
886+ >
887+ < div className = "flex flex-col items-start" >
888+ < Paragraph variant = "small" >
889+ < DateTime date = { run . createdAt } showTooltip = { false } />
890+ </ Paragraph >
891+ < div className = "flex items-center gap-2 text-xs text-text-dimmed" >
892+ < div >
893+ Run < span className = "font-mono" > { run . friendlyId . slice ( - 8 ) } </ span >
894+ </ div >
895+ < TaskRunStatusCombo status = { run . status } />
896+ </ div >
897+ </ div >
898+ </ button >
899+ ) ) }
900+ </ div >
901+ </ div >
902+ </ PopoverContent >
903+ </ Popover >
904+ ) ;
905+ }
0 commit comments