Disable follow-up textbox during approvals (vibe-kanban) (#914)

* Perfect! All changes have been implemented successfully. Let me summarize what was done:

## Summary

I've successfully implemented the feature to disable the follow-up textbox during approvals. Here's what was changed:

### Changes Made:

1. **Created `usePendingApproval` hook** (`frontend/src/hooks/usePendingApproval.ts`):
   - This hook checks the conversation entries from `EntriesContext` to detect if any tool use entry has a `pending_approval` status
   - Returns a boolean indicating whether there's a pending approval

2. **Updated `TaskFollowUpSection` component** (`frontend/src/components/tasks/TaskFollowUpSection.tsx`):
   - Imported and used the new `usePendingApproval` hook
   - Updated `canTypeFollowUp` to include the `hasPendingApproval` check, preventing users from typing when an approval is pending
   - Updated `isEditable` to include `!hasPendingApproval`, which disables the textbox UI when there's a pending approval

### How It Works:

- When an agent requests approval for a tool use, the conversation entry will have a `status: 'pending_approval'`
- The `usePendingApproval` hook detects this by checking all entries in the `EntriesContext`
- When a pending approval is detected, the follow-up textbox becomes disabled, preventing users from typing and queueing follow-ups
- Once the approval is resolved (approved/denied), the entry status changes and the textbox becomes enabled again

The implementation follows the existing patterns in the codebase and integrates smoothly with the existing approval UI and context system. TypeScript type checking passes successfully.

* Cleanup script changes for task attempt bd98d75b-12d0-45da-b486-f516b274abff

* Perfect! The refactoring is complete. Here's what I did:

## Changes Made

1. **Deleted** `frontend/src/hooks/usePendingApproval.ts` - the custom hook was unnecessary

2. **Updated** `TaskFollowUpSection.tsx`:
   - Removed import of `usePendingApproval`
   - Added import of `useEntries` from `@/contexts/EntriesContext`
   - Replaced the hook call with inline logic using `useEntries()` and `useMemo()`

## Result

The implementation is now:
- **Simpler** - one less file to maintain
- **More consistent** - follows the same pattern as `TodoPanel.tsx` which also uses `useEntries()` directly
- **Just as efficient** - still memoized, same performance
- **Easier to understand** - all the logic is in one place

The functionality remains exactly the same - the follow-up textbox (and all related buttons) will be disabled when there's a pending approval in the conversation entries. TypeScript type checking passes successfully.
This commit is contained in:
Alex Netsch
2025-10-02 15:20:08 +01:00
committed by GitHub
parent a2153be98c
commit 2f2e85b6e0

View File

@@ -22,6 +22,7 @@ import { cn } from '@/lib/utils';
//
import { useReview } from '@/contexts/ReviewProvider';
import { useClickedElements } from '@/contexts/ClickedElementsProvider';
import { useEntries } from '@/contexts/EntriesContext';
//
import { VariantSelector } from '@/components/tasks/VariantSelector';
import { FollowUpStatusRow } from '@/components/tasks/FollowUpStatusRow';
@@ -147,6 +148,19 @@ export function TaskFollowUpSection({
const { activeRetryProcessId } = useRetryUi();
const isRetryActive = !!activeRetryProcessId;
// Check if there's a pending approval - users shouldn't be able to type during approvals
const { entries } = useEntries();
const hasPendingApproval = useMemo(() => {
return entries.some((entry) => {
if (entry.type !== 'NORMALIZED_ENTRY') return false;
const entryType = entry.content.entry_type;
return (
entryType.type === 'tool_use' &&
entryType.status.status === 'pending_approval'
);
});
}, [entries]);
// Autosave draft when editing
const { isSaving, saveStatus } = useDraftAutosave({
attemptId: selectedAttemptId,
@@ -199,6 +213,7 @@ export function TaskFollowUpSection({
}
if (isRetryActive) return false; // disable typing while retry editor is active
if (hasPendingApproval) return false; // disable typing during approval
return true;
}, [
selectedAttemptId,
@@ -206,6 +221,7 @@ export function TaskFollowUpSection({
isSendingFollowUp,
branchStatus?.merges,
isRetryActive,
hasPendingApproval,
]);
const canSendFollowUp = useMemo(() => {
@@ -231,7 +247,8 @@ export function TaskFollowUpSection({
const isDraftLocked =
displayQueued || isQueuing || isUnqueuing || !!draft?.sending;
const isEditable = isDraftLoaded && !isDraftLocked && !isRetryActive;
const isEditable =
isDraftLoaded && !isDraftLocked && !isRetryActive && !hasPendingApproval;
// When a process completes (e.g., agent resolved conflicts), refresh branch status promptly
const prevRunningRef = useRef<boolean>(isAttemptRunning);