feat: 'Start agents (n)'-knop in Solo header, productname weg
SoloBoard-header toont nu een primary button die het aantal queueable TO_DO-taken telt (TO_DO zonder actieve ClaudeJob via claudeJobsByTaskId-store) en bij klik de nieuwe enqueueAllTodoJobsAction aanroept. Toast geeft het aantal gestarte agents terug. - productname-h1 verwijderd (staat al in NavBar-dropdown, dubbel) - sprintdoel blijft naast de knop - 'Toon openstaande stories'-link blijft rechts - demo-modus disabled met DemoTooltip - batch-pending state voorkomt dubbele klikken - productName-prop weg uit SoloBoard + page.tsx (was alleen voor h1) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7d76c3baee
commit
9cd6281816
2 changed files with 36 additions and 6 deletions
|
|
@ -105,7 +105,6 @@ export default async function SoloProductPage({ params }: Props) {
|
|||
return (
|
||||
<SoloBoard
|
||||
productId={id}
|
||||
productName={product.name}
|
||||
sprintGoal={sprint.sprint_goal}
|
||||
tasks={tasks}
|
||||
unassignedStories={unassignedStories}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import {
|
|||
import { toast } from 'sonner'
|
||||
import { useSoloStore } from '@/stores/solo-store'
|
||||
import { taskStatusToApi } from '@/lib/task-status'
|
||||
import { enqueueAllTodoJobsAction } from '@/actions/claude-jobs'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { DemoTooltip } from '@/components/shared/demo-tooltip'
|
||||
import { SplitPane } from '@/components/split-pane/split-pane'
|
||||
import { SoloColumn, type ColumnStatus } from './solo-column'
|
||||
import { SoloTaskCardOverlay } from './solo-task-card'
|
||||
|
|
@ -30,7 +33,6 @@ export interface SoloTask {
|
|||
|
||||
export interface SoloBoardProps {
|
||||
productId: string
|
||||
productName: string
|
||||
sprintGoal: string
|
||||
tasks: SoloTask[]
|
||||
unassignedStories: UnassignedStory[]
|
||||
|
|
@ -46,14 +48,16 @@ function getColumnStatus(status: SoloTask['status']): ColumnStatus {
|
|||
}
|
||||
|
||||
export function SoloBoard({
|
||||
productId, productName, sprintGoal, tasks: initialTasks, unassignedStories: initialUnassigned, isDemo,
|
||||
productId, sprintGoal, tasks: initialTasks, unassignedStories: initialUnassigned, isDemo,
|
||||
}: SoloBoardProps) {
|
||||
const { tasks, initTasks, optimisticMove, rollback, markPending, clearPending } = useSoloStore()
|
||||
const claudeJobsByTaskId = useSoloStore((s) => s.claudeJobsByTaskId)
|
||||
const [activeDragId, setActiveDragId] = useState<string | null>(null)
|
||||
const [selectedTask, setSelectedTask] = useState<SoloTask | null>(null)
|
||||
const [sheetOpen, setSheetOpen] = useState(false)
|
||||
const [unassignedStories, setUnassignedStories] = useState(initialUnassigned)
|
||||
const [, startTransition] = useTransition()
|
||||
const [batchPending, startBatchTransition] = useTransition()
|
||||
|
||||
const taskKey = initialTasks.map(t => t.id).join(',')
|
||||
useEffect(() => {
|
||||
|
|
@ -125,13 +129,40 @@ export function SoloBoard({
|
|||
|
||||
const activeTask = activeDragId ? tasks[activeDragId] : null
|
||||
|
||||
const queueableCount = columnTasks.TO_DO.filter(t => {
|
||||
const job = claudeJobsByTaskId[t.id]
|
||||
return !job || (job.status !== 'queued' && job.status !== 'claimed' && job.status !== 'running')
|
||||
}).length
|
||||
|
||||
function handleStartAll() {
|
||||
if (queueableCount === 0) return
|
||||
startBatchTransition(async () => {
|
||||
const result = await enqueueAllTodoJobsAction(productId)
|
||||
if ('error' in result) {
|
||||
toast.error(result.error)
|
||||
} else if (result.count === 0) {
|
||||
toast.info('Geen taken om te starten')
|
||||
} else {
|
||||
toast.success(`${result.count} ${result.count === 1 ? 'agent' : 'agents'} ingeschakeld`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full p-4 gap-4 min-h-0">
|
||||
<div className="flex items-start justify-between gap-4 shrink-0">
|
||||
<div className="min-w-0">
|
||||
<h1 className="text-base font-semibold text-foreground truncate">{productName}</h1>
|
||||
<div className="min-w-0 flex items-center gap-3">
|
||||
<DemoTooltip show={isDemo}>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={handleStartAll}
|
||||
disabled={isDemo || batchPending || queueableCount === 0}
|
||||
>
|
||||
{batchPending ? 'Starten…' : `Start agents (${queueableCount})`}
|
||||
</Button>
|
||||
</DemoTooltip>
|
||||
{sprintGoal && (
|
||||
<p className="text-sm text-muted-foreground mt-0.5 line-clamp-2">{sprintGoal}</p>
|
||||
<p className="text-sm text-muted-foreground line-clamp-2 min-w-0">{sprintGoal}</p>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue