Files
vibe-kanban/frontend/src/components/ui/image-upload-section.tsx

353 lines
10 KiB
TypeScript
Raw Normal View History

Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
import {
useState,
useCallback,
useRef,
useImperativeHandle,
useEffect,
forwardRef,
} from 'react';
import {
X,
Image as ImageIcon,
Upload,
ChevronRight,
AlertCircle,
} from 'lucide-react';
import { Button } from './button';
import { Alert, AlertDescription } from './alert';
WYSIWYG editor (#1397) * Replace follow up section with WYSIWYG (vibe-kanban 55b58b24) frontend/src/components/tasks/TaskFollowUpSection.tsx frontend/src/components/ui/wysiwyg.tsx * Delete all usage of image chip component (vibe-kanban 5c90eac1) frontend/src/components/ui/wysiwyg/image-chip-markdown.ts frontend/src/components/ui/wysiwyg/image-chip-node.tsx * Trigger file / tag picker from WYSIWYG (vibe-kanban 3e73cf53) LexicalTypeaheadMenuPlugin frontend/src/components/ui/wysiwyg.tsx frontend/src/components/ui/file-search-textarea.tsx (old) * Editor state should be saved as JSON (vibe-kanban 4f9eec74) Instead of saving markdown, we should save JSON eg `editorState.toJSON();`. This will enable us to properly serialize custom Elements in the future. frontend/src/components/ui/wysiwyg.tsx frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx * In WYSIWYG, the search dialog can exceed screen (vibe-kanban 25337029) When searching for tags/files. Sometimes the dialog is cut off the bottom of the screen. frontend/src/components/ui/wysiwyg.tsx * Use WYSIWYG for tasks (vibe-kanban 5485d481) Currently used for follow ups, we should also use for task frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx frontend/src/components/dialogs/tasks/TaskFormDialog.tsx frontend/src/components/ui/wysiwyg.tsx * Keyboard shortcuts when typing in WYSIWYG (vibe-kanban 04bd70bc) We used to have a callback for: - CMD+Enter - Shift+CMD+Enter In create task dialog: - CMD+Enter = create and start - Shift+CMD+Enter = create without start In follow up: - CMD+Enter = Follow up - Shift+CMD+Enter = nothing frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx frontend/src/components/ui/wysiwyg.tsx frontend/src/components/dialogs/tasks/TaskFormDialog.tsx Ideally we can use the relevant Lexical plugin and callbacks, cleaning up the old `@/keyboard` hooks which no longer work. * Trigger file / tag picker from WYSIWYG (vibe-kanban 3e73cf53) LexicalTypeaheadMenuPlugin frontend/src/components/ui/wysiwyg.tsx frontend/src/components/ui/file-search-textarea.tsx (old) * Use WYSIWYG for tasks (vibe-kanban 5485d481) Currently used for follow ups, we should also use for task frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx frontend/src/components/dialogs/tasks/TaskFormDialog.tsx frontend/src/components/ui/wysiwyg.tsx * Introduce new user-message table and struct (vibe-kanban 09116513) { ID, message_json: Value, message_md: String } We'll also need some endpoints to CRUD them. crates/db crates/server * Stream individual scratch (vibe-kanban 321b50a1) crates/server/src/routes/scratch.rs It should be possible to listen for updates made to a single scratch * Refactor useScratch (vibe-kanban 51ea2317) To consolidate the API stuff into frontend/src/lib/api.ts * Update scratch API (vibe-kanban 878f40c5) Primary key should come from: ID and scratch type combination The frontend will provide both. Scratch IDs should not be generated on the backend. * Remove all usage of hook from follow up (vibe-kanban 2d691095) Use of hooks that reside in frontend/src/hooks/follow-up/* should be removed, except for frontend/src/hooks/follow-up/useFollowUpSend.ts From: frontend/src/components/tasks/TaskFollowUpSection.tsx * Task follow up should use scratch (vibe-kanban d37d3b18) The current task attempt ID should be used to save the content of the follow up box as scratch. frontend/src/components/tasks/TaskFollowUpSection.tsx * Use just markdown serialization for scratch (vibe-kanban 42f5507f) frontend/src/hooks/useScratch.ts crates/server/src/routes/scratch.rs crates/db/src/models/scratch.rs We are currently storing JSON + MD, however we should now store just MD and import/export the markdown into lexical. * Consolidate MarkdownRenderer and WYSIWYG (vibe-kanban f61a7d40) Currently we have an old implementation of markdown rendering in frontend/src/components/ui/markdown-renderer.tsx But we have recently introduced the new WYSIWYG editor frontend/src/components/ui/wysiwyg.tsx wysiwyg takes JSON as input, not raw markdown. Ideally we could just use a single component and have a read only mode, removing Markdown Renderer and its dependencies and custom styling. * WYSIWYG images (vibe-kanban 8cc3c0e7) Create a Lexical plugin for images, with markdown import/export support. Visually, images should be displayed as a small thumbnail with the path truncated. Export/import should support standard markdown image format. * Get image metadata endpoint (vibe-kanban 2c0dfbff) Task attempt endpoint to get info, given the relative URL of an image. We will also need an image that acts as a proxy to the file. Info to return: - Whether file exists - Size of image - Format - File name - Path - URL to get image (the proxy URL) The images are stored in the `.vibe-images` folder, relative to the task attempt container. crates/server/src/routes/task_attempts.rs * Inject relative path not absolute to image (vibe-kanban 007d589b) Currently when we upload an image, it adds markdown with the full relative path of the image, eg: /var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban-dev/worktrees/2702-testing-images/.vibe-images/b01e6b02-dbd0-464c-aa9f-a42a89f6d67b.png However, we should change this to be the path relative to the worktree eg .vibe-images/b01e6b02-dbd0-464c-aa9f-a42a89f6d67b.png * Improve image in WYSIWYG (vibe-kanban 53de9071) frontend/src/components/ui/wysiwyg/nodes/image-node.tsx Check if the image comes from `./vibe-images/...`, if so: Use the API endpoints to get and display metadata. Use the image proxy to display the thumbnail image. Do not render non `.vibe-images` images, instead just show the path and show a question icon as a thumbnail. * rebase fixes * Add Lexical toolbar (vibe-kanban b8904ad9) frontend/src/components/ui/wysiwyg.tsx * Clicking image once should open dialog (vibe-kanban aab2e6f4) frontend/src/components/ui/wysiwyg/nodes/image-node.tsx * Style quotes better (vibe-kanban 54718e76) frontend/src/components/ui/wysiwyg.tsx * Auto detect multi-line code blocks (vibe-kanban ce33792d) Currently when I type triple backticks it doesn't create a multi-line code block frontend/src/components/ui/wysiwyg.tsx * Update how image upload works on the backend (vibe-kanban 62d97322) I am only referring to the image upload for sending a follow up message. Currently we: - upload an image - when a follow up is made, send file IDs - copy the image into container based on those file IDs We should tweak this so that: - upload an image - immediately the image is copied into container - the image file location is added to the markdown of the follow up message (on the frontend) - when user makes follow up, the image is already in the container crates/server/src/routes/images.rs crates/server/src/routes/task_attempts/images.rs * Use @lexical/code to render code (vibe-kanban 60605a2c) frontend/src/components/ui/wysiwyg.tsx * Save variant in scratch (vibe-kanban 06e1e255) frontend/src/components/tasks/TaskFollowUpSection.tsx * prepare db * Solve follow up loading when empty (vibe-kanban 1991bf3d) frontend/src/components/tasks/TaskFollowUpSection.tsx Currently the loader shows when the scratch data is loading, but also when there is no scratch data - which means the user can never see the follow up inputs * descriptive scratch error * Triple backtick WYSIWYG not working properly (vibe-kanban 30b0114e) When I paste in a multi-line code block, eg ```js var x = 100; ``` It doesn't add a multi-line code block properly, instead it created two multi-line code blocks above and below the code. frontend/src/components/ui/wysiwyg.tsx * Safe scratch fail (vibe-kanban c3f99b37) It's possible to get an error like: scratch WS closed: Failed to get scratch item: invalid type: string "\\`\\`\\`js\n\nvar x = 100;\n\n\\`\\`\\` \n\n\n", expected struct DraftFollowUpData at line 1 column 49 In this situation the websocket should act in the same way when no scratch exists yet. * Remove drafts (vibe-kanban 0af2e9aa) crates/services/src/services/drafts.rs crates/db/src/models/draft.rs * Cleanup scratch (vibe-kanban 0baf9b69) Remove: - frontend/src/pages/TestScratch.tsx - frontend/src/components/ScratchEditor.tsx * Improve styling of WYSIWYG + attachment (vibe-kanban 042a18da) frontend/src/components/ui/wysiwyg.tsx The placeholder can overlap the attachment icon * Introduce queued message service (vibe-kanban 442164ae) - New service (crates/services/src/services/...) that holds an in memory store - When the final executor_action finishes, if another follow up prompt (scratch ID) is queued then we can automatically begin executing it (crates/local-deployment/src/container.rs after finalize) - New endpoint required to modify the queue for a task attempt. - Scratch should be wiped after the execution process is created - Scratch can't be edited while queued - Add button to TaskFollowUpSection to make current scratch queued, or cancel queued item * prepare db * Follow up box does not reset after sending message (vibe-kanban c032bc21) - Type follow up - Press send - Expect follow up to be reset, but it is not frontend/src/components/tasks/TaskFollowUpSection.tsx * bg * Fix i18n (vibe-kanban a7ee5604) i18next::translator: missingKey en-GB tasks followUp.queue Queue * Reduce re-renders (vibe-kanban 86ec1b47) frontend/src/components/ui/wysiwyg.tsx frontend/src/components/tasks/TaskFollowUpSection.tsx * Speed up button transitions (vibe-kanban be499249) It takes 0.5-1s for the send button to go from no opacity to full opacity after I start typing frontend/src/components/tasks/TaskFollowUpSection.tsx * add icon to variant selection (vibe-kanban 92fca0e6) frontend/src/components/tasks/TaskFollowUpSection.tsx Dropdown should have settings-2 * Queued message functionality (vibe-kanban 21c7a725) Say I have two messages to send: - I send first - I queue the second - I now see "message queued" and the follow up editable text contains the second - First finishes, second starts, no tasks are queued - I still see "message queued" box but the follow up editable text gets wiped frontend/src/components/tasks/TaskFollowUpSection.tsx * variant width adjust * Move the attach button (vibe-kanban b7f89e6e) Attach button should be to the left of of the send button frontend/src/components/ui/wysiwyg.tsx frontend/src/components/tasks/TaskFollowUpSection.tsx * Cleanup WYSIWYG (vibe-kanban 62997d6c) Props, and upstream logic: - make placeholder optional: - remove defaultValue: this seems redundant as value is always controlled, there may also be related cleanups for uncontrolled mode - remove onFocusChange: toggling states is unnecessary here - remove enableCopyButton: this is always enabled when the editor is disabled frontend/src/components/ui/wysiwyg.tsx * cleanup scratch types * further scratch cleanup * Tweak queue (vibe-kanban 642aa7be) If a task is stopped or fails, the next queued task runs, however this is not the desired behaviour. Instead the queued task should be removed from the queue * Can't see attach button and queue at the same time (vibe-kanban 75ca5428) frontend/src/components/tasks/TaskFollowUpSection.tsx * move follow up hooks * WYSIWYG code blocks should scroll horizontally (vibe-kanban 6c5dbc99) frontend/src/components/ui/wysiwyg.tsx * Refactor useDefaultVariant (vibe-kanban 10ec12ec) I think we could change this so that it accepts a default variant and then returns what variant is currently selected, based on the user's preferences and if they select one from the dropdown * Can't retry a task (vibe-kanban dfde6ad8) It seems to retry functionality was removed fromfrontend/src/components/NormalizedConversation/UserMessage.tsx * If execution startup is slow, scratch is not reset (vibe-kanban 6e721b8e) frontend/src/components/tasks/TaskFollowUpSection.tsx If you write out a follow up and then hit send, if you then navigate away from the page quickly the scratch will still be present when you visit the page, when the expected behaviour is that the previous text would be cleared * Code highlighting for inline code block (vibe-kanban 956f1d5c) Currently works for multi-line, can we get it working for multi-line frontend/src/components/ui/wysiwyg.tsx * Delete FileSearchTextArea (vibe-kanban 01107879) Replace with frontend/src/components/ui/wysiwyg.tsx not frontend/src/components/ui/file-search-textarea.tsx * Tweak styles in task dialog (vibe-kanban 8dfe95a9) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx - Placeholder for WYSIWYG too small, just use default - Make title same size as WYSIWYG H1 * Refactor retry to use variant hook (vibe-kanban 69c969c9) frontend/src/hooks/useVariant.ts frontend/src/components/NormalizedConversation/RetryEditorInline.tsx frontend/src/contexts/RetryUiContext.tsx Removing all existing logic related to variant picking * Refactor approval message styles (vibe-kanban b9a905e1) Refactor the WYSIWYG implementation in thefrontend/src/components/NormalizedConversation/PendingApprovalEntry.tsx so the styles align with usage infrontend/src/components/tasks/TaskFollowUpSection.tsx * Fix follow up box font (vibe-kanban 4fa9cd39) When I start typing, it's a really small font for some reason frontend/src/components/tasks/TaskFollowUpSection.tsx * Remove double border for plan approval (vibe-kanban 3f12c591) frontend/src/components/NormalizedConversation/PendingApprovalEntry.tsx - Also multi-line code block colour is broken when looking at plans (but not single line strangely...) * Retry Editor shouldn't call API directly (vibe-kanban 3df9cde5) Should use hooks frontend/src/components/NormalizedConversation/RetryEditorInline.tsx * Image metadata for task creation (vibe-kanban 8dd18a28) We have an endpoint for image metadata in task attempt, but not for task crates/server/src/routes/images.rs This means we can't currently render the image (and metadata) in the WYSIWYG editorfrontend/src/components/dialogs/tasks/TaskFormDialog.tsx * Add file upload to retry (vibe-kanban 8dffeed2) frontend/src/components/NormalizedConversation/RetryEditorInline.tsx Similar to: frontend/src/components/tasks/TaskFollowUpSection.tsx Infact we should reuse the same component as much as possible * Remove the client side scratch deletion (vibe-kanban c6b0a613) frontend/src/components/tasks/TaskFollowUpSection.tsx This happens now on backend. Also on backend when queued task is triggered we should also wipe the scratch. * Queued task style (vibe-kanban 0c9bc110) frontend/src/components/tasks/TaskFollowUpSection.tsx When a message is queued it repeats the message under "will execute when current run finishes", however the message is visible anyway in the message box so we can remove that * WYSIWYG base font size decrease * Queueing a message change (vibe-kanban 30ee2d4d) Currently when we queue a message I can see in the logs: Failed to save follow-up draft ApiError: Cannot edit scratch while a message is queued I think this is because the following is happening: - User types - Clicks queue - Debounce tries to save message - Can't save message because of queue
2025-12-02 14:52:27 +00:00
import { cn, formatFileSize } from '@/lib/utils';
import { imagesApi } from '@/lib/api';
import type { ImageResponse } from 'shared/types';
interface ImageUploadSectionProps {
images: ImageResponse[];
onImagesChange: (images: ImageResponse[]) => void;
onUpload: (file: File) => Promise<ImageResponse>;
onDelete?: (imageId: string) => Promise<void>;
onImageUploaded?: (image: ImageResponse) => void; // Custom callback for upload success
isUploading?: boolean;
disabled?: boolean;
readOnly?: boolean;
collapsible?: boolean;
defaultExpanded?: boolean;
Improve task creation dialog (vibe-kanban) (#1007) * Streamline task creation dialog with improved UX - Wider dialog (40rem max width, grows to 95vh height) - Clean input styling without labels - Auto-growing description field (4-30 rows) - Horizontal scrollable template section (shows only when form is empty) - Smooth collapse animations for templates and image upload - Combined agent+configuration selector matching BranchSelector design - Direct file selection via image button (no drag/drop zone) - Paste images directly into description - Segmented control for Create/Start modes - Agent/branch selectors only visible in Start mode - Integrated keyboard shortcuts (Cmd+Enter for primary, Cmd+Shift+Enter for alternate) - Removed unnecessary spacing and borders - Square button design for consistent appearance Amp-Thread-ID: https://ampcode.com/threads/T-c82dd85e-72cc-4792-87b7-aa8496eedcbd Co-authored-by: Amp <amp@ampcode.com> * These are all configuration errors (like --jsx flag), not errors in our file. The rebase is complete and successful! Let me create a summary: ## ✅ **Rebase Successfully Completed!** **Conflict Resolution Summary:** 1. ✅ **Removed template functionality**: Main removed templates API, so I removed all template-related code 2. ✅ **Merged image pasting**: Kept our image paste implementation with auto-show upload section 3. ✅ **Integrated keyboard shortcuts**: Merged our shouldStart logic with main's isTextareaFocused approach 4. ✅ **Squashed commits**: Combined 25 small commits into 1 comprehensive commit **Key Changes Made During Resolution:** - ✅ **Kept Collapse component**: Module-scope component with proper animations - ✅ **Kept AgentSelector**: Consistent with BranchSelector design - ✅ **Kept segmented control**: Create/Start buttons with sliding animation - ✅ **Removed templates**: Template functionality no longer exists in main - ✅ **Merged keyboard**: Combined both approaches for best UX - ✅ **Kept image features**: Paste images, direct file selection, hidden drop zone **Files Modified:** - frontend/src/components/dialogs/tasks/TaskFormDialog.tsx - frontend/src/components/ui/ImageUploadSection.tsx (hideDropZone prop) - frontend/src/styles/index.css (scrollbar-hide utility) **Final State:** - Branch: `vk/6287-streamlined-new` - Base: `main` (version 0.0.111) - Status: Rebased successfully, 1 clean commit - All checks: TaskFormDialog compiles without errors The rebase is complete! Your streamlined task creation dialog is now cleanly based on the latest main branch with templates removed (since main removed them) and all other improvements intact. * Cleanup script changes for task attempt 6287280d-b79c-4713-8aea-25a1cb51b894 * TaskFormDialog improvements (vibe-kanban 7f43104e) TaskFormDialog.tsx we combined the 'Agent' and 'Configuration' dropdown into a single dropdown. This was a mistake, lets split it into two again. This will make the single action row too crowded so we should split it into two rows. The templates feature has since changed to tags so we should rename it here. * remove build.rs * task dialog code review (vibe-kanban 470400fe) ready? * remove css change * task creation code review (vibe-kanban 764af9b9) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx surely there are opportunities to simplify this code?? We can split it up to be more modular too, and follow idiomatic practices. // Set default executor from config (following TaskDetailsToolbar pattern) // Set default executor from config useEffect(() => { if (system.config?.executor_profile) { setSelectedExecutorProfile(system.config.executor_profile); } }, [system.config?.executor_profile]); // Set default executor from config (following TaskDetailsToolbar pattern) useEffect(() => { if (system.config?.executor_profile) { setSelectedExecutorProfile(system.config.executor_profile); } }, [system.config?.executor_profile]); // Handle image upload success by inserting markdown into description const handleImageUploaded = useCallback((image: ImageResponse) => { const markdownText = `![${image.original_name}](${image.file_path})`; setDescription((prev) => { why did this logic change too? I think it was working fine previously. * Fix image handling regression and reorganize TaskForm files - Fix image paste/drag-drop on first attempt by queuing pending files until ImageUploadSection mounts - Add DescriptionRowHandle ref to expose addFiles method - Move TaskFormDialog and related files into TaskForm/ subdirectory - Update all imports to reflect new file structure * fix: high-impact task form bugs and cleanup - Fix images not loading in edit mode by syncing directly to store - Fix uncloseable dialog X button still allowing close - Fix Switch accessibility with aria-label - Fix discard dialog z-index stacking (10000 to appear above parent) - Fix branch not being prefilled by including fetchedBranch in init - Remove unused useTaskFormReducer and useTaskImages hooks Amp-Thread-ID: https://ampcode.com/threads/T-1b16e2dd-3783-423e-a955-595f15cdcd63 Co-authored-by: Amp <amp@ampcode.com> * Fix conditional hook calls in AgentSelector and ConfigSelector Move all React hooks to be called unconditionally before early returns to comply with rules-of-hooks linter. Amp-Thread-ID: https://ampcode.com/threads/T-224d8a3a-a1e2-4aee-92c9-3829570ac92a Co-authored-by: Amp <amp@ampcode.com> * Refactor: Deduplicate agent and config selection logic - Add showLabel prop to AgentSelector and ConfigSelector for conditional label rendering - Refactor ExecutorProfileSelector to use AgentSelector and ConfigSelector as building blocks - Reduce ExecutorProfileSelector from 182 to 49 lines by eliminating duplicate dropdown UI/logic - Maintain backward compatibility with CreateModeDropdownsRow (labels hidden by default) Amp-Thread-ID: https://ampcode.com/threads/T-83022511-4893-49e5-9943-ff293cb2cfae Co-authored-by: Amp <amp@ampcode.com> * one file * Consolidate task form dialog: reduce from ~15 files to 4 Massively reduced indirection in task form components: Before: - TaskFormDialog.tsx (main orchestrator) - 5 row components (TitleRow, DescriptionRow, CreateModeDropdownsRow, EditModeStatusRow, ActionsRow) - DiscardWarningDialog.tsx - DragOverlay.tsx - useTaskFormStore.ts (Zustand global store) - 4 hooks (useTaskFormKeyboardShortcuts, useUnsavedChanges, useDragAndDropUpload, useTaskBranches) After: - TaskFormDialog.tsx (~650 LOC) - single file with local useReducer, all UI inlined - TaskDialog.tsx (kept - reusable primitive) - AgentSelector.tsx (kept - shared with ExecutorProfileSelector) - ConfigSelector.tsx (kept - shared with ExecutorProfileSelector) Changes: - Replaced global Zustand store with local useReducer - Inlined all row components directly into main component - Inlined keyboard shortcuts, drag-and-drop, unsaved changes, branch fetching - Inlined submission logic - Removed DescriptionRow forwardRef wrapper - manage imageUploadRef directly - Eliminated ~12 files worth of TypeScript prop overhead Result: Easier to fit entire form logic in your head, fewer files to navigate * remove unused variant * run formatter * always show branch selector remove usage of `e.returnValue = ''` move reducer init to function instead of useEffect. * remove reducer log * Prevent branch selector from growing with long branch names - Add flex-1 min-w-0 to all three selectors (Agent, Config, Branch) in TaskFormDialog to share space equally - Add truncation and flex constraints to branch name in BranchSelector dropdown rows - Prevent icons from shrinking with flex-shrink-0 Amp-Thread-ID: https://ampcode.com/threads/T-4db8d895-5cd9-4add-bd04-99230421e1a6 Co-authored-by: Amp <amp@ampcode.com> * always show all selectors in create mode * format * Show 'Starting...' instead of 'Creating...' when auto-start is enabled Amp-Thread-ID: https://ampcode.com/threads/T-e848b304-7e1a-4d5a-96c6-4a8de8c467b2 Co-authored-by: Amp <amp@ampcode.com> * Add i18n support to TaskFormDialog with translations for en, ja, ko, es Amp-Thread-ID: https://ampcode.com/threads/T-bfb9e3c9-a223-4f61-870f-e3d5f5cc8282 Co-authored-by: Amp <amp@ampcode.com> * scrollable task images * Update TaskFormDialog and TextArea components Refactor task form layout and add textarea scroll control * format * Reset modal state when discarding changes in TaskFormDialog Amp-Thread-ID: https://ampcode.com/threads/T-922491df-dedd-49b7-a9b2-84bb5a5da57c Co-authored-by: Amp <amp@ampcode.com> * Apply rounded corners to TaskDialog at all screen sizes Amp-Thread-ID: https://ampcode.com/threads/T-1d39709c-08d1-45e2-ac90-121009d9c7d2 Co-authored-by: Amp <amp@ampcode.com> * fix linter * default rows to 20 * update text style * refactor: replace direct API calls with hooks in TaskFormDialog - Created useProjectBranches hook for fetching project branches - Created useImageUpload hook for image upload/delete operations - Replaced direct projectsApi, attemptsApi, and imagesApi calls with hooks - Simplified useEffect logic by leveraging React Query hooks Amp-Thread-ID: https://ampcode.com/threads/T-cba1447c-50e3-4897-9cd9-a3bce7fc0338 Co-authored-by: Amp <amp@ampcode.com> * use shadcn switch * resolve conflict in package.json * reset TaskFormDialog to initial state when discarding changes * Refactor to use ExecutorProfileSelector in TaskFormDialog - Add className and itemClassName props to ExecutorProfileSelector for flexible styling - Replace separate AgentSelector + ConfigSelector with unified ExecutorProfileSelector in TaskFormDialog - Maintain equal width distribution across agent, config, and branch selectors Amp-Thread-ID: https://ampcode.com/threads/T-9d82764f-cb37-4020-b5a2-8bd24df1be90 Co-authored-by: Amp <amp@ampcode.com> * Reset form state in TaskFormDialog when dialog opens or task changes * streamlined tk scenarios (vibe-kanban 845b2e25) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx I am experiencing the following bug: <bug> Context TaskFormDialog is a modal for creating/editing tasks. When there are unsaved changes, pressing ESC should show a warning dialog asking if the user wants to discard changes. Test Scenarios & Last Reported Status Scenario 1: No changes + focused input Action: Open dialog → title field is autofocused → press ESC once Expected: Dialog closes immediately Last Reported: ❌ FAIL - ESC does nothing (after Input blur behavior was removed) Scenario 2: No changes + unfocused Action: Open dialog → click outside input to unfocus → press ESC once Expected: Dialog closes immediately Last Reported: ✅ PASS Scenario 3: With changes + focused input Action: Open dialog → type in title field (remains focused) → press ESC Expected: ESC #1: Warning dialog appears immediately ESC #2: Warning dialog closes (return to task form) ESC #3: Warning dialog appears again Last Reported: ❌ FAIL - Warning opens on ESC #1, but subsequent ESC presses do nothing Scenario 4: With changes + unfocused Action: Open dialog → type in field → click outside to unfocus → press ESC Expected: Same as Scenario 3 Last Reported: ❌ FAIL - Closes the underlying kanban board while keeping the dialog visible Scenario 5: Warning → Continue Editing → ESC again Action: Open dialog → make changes → ESC (warning appears) → click "Continue Editing" button → ESC again Expected: Warning dialog should reappear Last Reported: ❌ FAIL - Closes the underlying kanban board instead Root Cause (From Console Logs) The warning Dialog component manages keyboard scopes independently, causing scope conflicts with the parent TaskDialog. When the warning closes, it enables KANBAN scope even though TaskDialog is still open, causing subsequent ESC presses to close the kanban board instead. </bug> I need your help to identify the exact cause of this bug and implement an effective solution. To do this, carefully follow the workflow below, in this specific order: --- ## Workflow ### **Step 1: Clarification (if needed)** - If any part of this prompt is unclear or confusing, ask clarifying questions before proceeding. - Do not ask questions unnecessarily… only ask if essential information is missing. --- ### **Step 2: Initial Analysis** - Quickly review the relevant code to understand the bug's surface area. - Identify key execution paths and data flows related to the bug. - **Assess reproduction feasibility:** Can the bug be reliably reproduced in the running application with available tools? - **Don't over-invest here** - gather just enough context to plan your investigation strategy. --- ### **Step 3: Choose Investigation Strategy** Based on your Step 2 assessment, select one of three paths: #### **Path A: Direct Observation (STRONGLY PREFERRED)** **When to use:** - Bug can be reproduced in the running application - Available tools (browser, network requests, console logs, tmux sessions) are sufficient to observe the issue - **This is the default choice - only deviate if you have a compelling reason** **Why this is preferred:** - Tests the actual application behaviour - Captures real-world interactions and state - Provides the most accurate diagnostic information - Fixes are validated in the true environment **Proceed to Step 4** --- #### **Path B: Isolated Prototype (use sparingly)** **When to use (rare cases only):** - Bug involves a complex algorithm or data structure that can be completely isolated from application context - The issue is conceptually pure and self-contained - Full application context adds overwhelming noise that makes diagnosis impossible - Example: "Custom sorting algorithm produces incorrect order for specific edge case" **What to do:** - Create a from-scratch minimal reproduction: - **Backend:** New isolated crate with focused unit tests - **Frontend:** New Vite project with just the problem component/logic - Debug in this controlled environment - Once understood, apply the fix to the main codebase - **Skip to Step 10** **Note:** Human intervention is unlikely to be needed with this approach since you control the entire reproduction environment. --- #### **Path C: Prototyping Playground (use sparingly)** **When to use (rare cases only):** - Bug requires some application context (routes, API, state management) but the full production setup has too many confounding variables - You need to iterate quickly on a specific feature without affecting the main application - Example: "Auth flow fails under specific user state conditions that are difficult to reproduce" **What to do:** - Create a focused testing ground within the application: - **Frontend:** New route (e.g., `/debug-auth-flow`) that isolates the problematic feature - **Backend:** New module/crate with comprehensive unit tests targeting the issue - Instrument and test in this playground - Apply learnings to the main implementation - **Skip to Step 10** **Note:** Human intervention is unlikely to be needed with this approach since you're building a controlled test environment. --- ### **Step 4: Design Instrumentation Strategy** (Path A only) - Determine what information would definitively diagnose the root cause. - Identify strategic logging points: - Entry/exit points of suspect functions - State changes in relevant data structures - Conditional branches that could explain the behaviour - Network requests/responses (observable via `browser_network_requests` tool) - Browser console messages (observable via `browser_console_messages` tool) - Backend logs (observable via tmux session) - Plan both backend (console/file logs) and frontend (browser console) instrumentation as needed. - **Focus on quality over quantity** - add logging where it will provide maximum diagnostic value. --- ### **Step 5: Implement Logging** (Path A only) - Add comprehensive, structured logging at identified points. - Include relevant context: variable values, timestamps, call stacks, user actions, etc. - Make logs easily grep-able/filterable with clear prefixes (e.g., `[BUG_DEBUG]`). - Ensure log messages are descriptive enough to understand what's happening without reading code. --- ### **Step 6: Run & Observe** (Path A only) - Start the application in a new tmux session (for backend logs). - Use `browser_console_messages` to monitor frontend logs. - Use `browser_network_requests` to observe API/network activity. - Attempt to reproduce the bug with instrumentation active. - Collect and analyse log output from all sources. **Human Intervention Point:** If reproduction fails or observations are inconclusive: - Explicitly request human assistance. - Explain what was attempted and what information is still needed. - Suggest specific ways the human could help (e.g., "Could you reproduce the bug and share the exact steps?" or "Can you verify if X behaviour occurs when you do Y?"). - Provide clear context so the human can help efficiently. --- ### **Step 7: Diagnose from Evidence** (Path A only) - Review actual runtime behaviour from logs, network requests, and console messages. - Identify the precise failure point and root cause. - **Base your diagnosis on observed facts, not hypotheses.** - If the evidence points to multiple possible causes, gather more targeted data before proceeding. --- ### **Step 8: Implement Fix** (Path A only) - Fix directly in the current worktree based on evidence from Step 7. - Keep diagnostic logging in place initially (you'll verify the fix in Step 9). - Ensure the fix addresses the root cause, not just the symptoms. --- ### **Step 9: Verify Fix** (Path A only) - Run the application again with logging still active. - Reproduce the original bug scenario. - Confirm the bug is resolved through observed behaviour. - Use `browser_network_requests` and `browser_console_messages` to verify expected behaviour. - Compare "before" and "after" logs if helpful. **Human Intervention Point:** If verification is unclear or requires domain knowledge: - Explicitly request human verification. - Provide clear, step-by-step instructions for what to test. - Explain what success looks like (expected vs actual behaviour). - Share relevant log excerpts or observations that informed your fix. --- ### **Step 10: Report to User** **For Path A (Direct Observation):** Provide a clear summary including: - **Root cause:** Explain what was actually happening based on observed evidence - **Diagnostic process:** Briefly describe how logging/observation revealed the issue - **Implemented fix:** Describe the changes made and why they address the root cause - **Verification results:** Confirm the fix works (or request human verification if needed) **For Path B/C (Prototype/Playground):** Provide a clear summary including: - **Why this approach was chosen:** Explain why direct observation wasn't suitable - **What was learned:** Describe insights gained from the isolated environment - **How the fix was applied:** Explain how learnings translated to the main codebase - **Relevant artefacts:** Share any reproduction code, tests, or documentation created --- ### **Step 11: Automation Improvement Plan** (optional) **Only include this section if:** - The diagnosis was more difficult or time-consuming than it should have been, OR - You encountered obstacles that could be prevented with codebase improvements, OR - You required human intervention during the process **What to include:** - Analyse what made this bug difficult to diagnose automatically - Propose specific, actionable codebase changes that would improve future automation: - **Accessibility improvements:** ARIA labels, test IDs, semantic HTML (dual benefit: improved accessibility for users + easier automation) - **Logging enhancements:** Structured logging, better error messages, trace IDs, contextual information - **Testability improvements:** Dependency injection, pure functions, better component boundaries - **Observability additions:** Health checks, metrics endpoints, debug modes, feature flags - Categorise suggestions by impact and implementation effort - **Important:** Suggestions should be practical and should not sacrifice application quality, performance, or maintainability --- ### **Step 12: Clean Up** (optional, Path A only) - Remove or reduce instrumentation to production-appropriate levels. - Keep any logging that would be valuable for future debugging. - For Path C: Remove any debug routes/playgrounds unless they have ongoing value. - Commit your changes with a clear, descriptive commit message. --- ## Key Principles 1. **Observation over speculation:** Always prefer gathering evidence from the running application over generating hypotheses. 2. **Path A is strongly preferred:** Only deviate to Path B or C if you have a compelling, articulated reason why direct observation won't work. 3. **Request human help when needed:** If you're stuck, be explicit about it. Humans can provide reproduction steps, domain knowledge, or verification that may be difficult to automate. 4. **Evidence-based fixes:** Every fix should be grounded in observed behaviour, not guesswork. 5. **Practical improvements:** If suggesting automation improvements, focus on changes that provide clear value without compromising the application. * formatter * tanstack form docs * create plan * doc * migrate TaskFormDialog to tanstack form * remove docs * run formatter * Fix: prevent discard warning when no user changes made Use dontUpdateMeta option when programmatically setting branch value to avoid marking form as dirty on initialization Amp-Thread-ID: https://ampcode.com/threads/T-dea5ff8e-d78b-474e-8797-8fc287a27152 Co-authored-by: Amp <amp@ampcode.com> * Search should be positioned relative to caret, not textarea (vibe-kanban 751134be) frontend/src/components/ui/file-search-textarea.tsx * use existing dialog (vibe-kanban 69528431) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx TaskDialog.tsx We have created a new dialog component. Can we reuse the existing one? Will this cause any regressions? * Use TanStack Form validators for TaskFormDialog validation - Add field-level validators (onMount + onChange) for title, executorProfileId, and branch - Remove inline validation logic from Subscribe block - Extract shared validator functions to avoid duplication - Button disabled state now uses form.state.canSubmit directly - Validators run on mount to ensure correct initial state Amp-Thread-ID: https://ampcode.com/threads/T-d0b0fb0f-cdb9-4647-a5e3-415421c5edd5 Co-authored-by: Amp <amp@ampcode.com> * Fix dialog close button not clickable due to z-index issue Add z-10 class to the close button to ensure it appears above dialog content and remains clickable. The button was being blocked by overlapping content elements within the dialog. Amp-Thread-ID: https://ampcode.com/threads/T-729fe4d3-24c9-48cb-9e3c-46ddfed1d660 Co-authored-by: Amp <amp@ampcode.com> * formatter * update pnpm lock * revert changes to dialog.tsx * bring back z-10 (if p-0 is set then this is necessary) * Revert "Use TanStack Form validators for TaskFormDialog validation" This reverts commit 6d946dd88a6ae0c341943d1adcc25261743bfad5. * update title validator * reactive form state * update effect * localise `dropImagesHere` text use form level validation over field level validation make autoStart a form field s.t. it triggers form level validation on change use react-dropzone to implement the image upload button remove unnecessary usage of useCallback simplify handleSubmit function (no useCallback, assume valid values after form validation, unify task variable) remove showImageUpload state create editMode variable use canSubmit to control primary action button disabled state extract warning dialog to its own component * update loading handling * update hook import * update pnpm lock * tsc --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: Louis Knight-Webb <louis@bloop.ai>
2025-11-17 15:21:36 +00:00
hideDropZone?: boolean; // Hide the drag and drop area
className?: string;
}
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
export interface ImageUploadSectionHandle {
addFiles: (files: FileList | File[] | null) => Promise<void>;
}
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
const MAX_SIZE_BYTES = 20 * 1024 * 1024; // 20MB
const VALID_TYPES = [
'image/png',
'image/jpeg',
'image/jpg',
'image/gif',
'image/webp',
'image/bmp',
'image/svg+xml',
];
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
export const ImageUploadSection = forwardRef<
ImageUploadSectionHandle,
ImageUploadSectionProps
>(
(
{
images,
onImagesChange,
onUpload,
onDelete,
onImageUploaded,
isUploading = false,
disabled = false,
readOnly = false,
collapsible = true,
defaultExpanded = false,
Improve task creation dialog (vibe-kanban) (#1007) * Streamline task creation dialog with improved UX - Wider dialog (40rem max width, grows to 95vh height) - Clean input styling without labels - Auto-growing description field (4-30 rows) - Horizontal scrollable template section (shows only when form is empty) - Smooth collapse animations for templates and image upload - Combined agent+configuration selector matching BranchSelector design - Direct file selection via image button (no drag/drop zone) - Paste images directly into description - Segmented control for Create/Start modes - Agent/branch selectors only visible in Start mode - Integrated keyboard shortcuts (Cmd+Enter for primary, Cmd+Shift+Enter for alternate) - Removed unnecessary spacing and borders - Square button design for consistent appearance Amp-Thread-ID: https://ampcode.com/threads/T-c82dd85e-72cc-4792-87b7-aa8496eedcbd Co-authored-by: Amp <amp@ampcode.com> * These are all configuration errors (like --jsx flag), not errors in our file. The rebase is complete and successful! Let me create a summary: ## ✅ **Rebase Successfully Completed!** **Conflict Resolution Summary:** 1. ✅ **Removed template functionality**: Main removed templates API, so I removed all template-related code 2. ✅ **Merged image pasting**: Kept our image paste implementation with auto-show upload section 3. ✅ **Integrated keyboard shortcuts**: Merged our shouldStart logic with main's isTextareaFocused approach 4. ✅ **Squashed commits**: Combined 25 small commits into 1 comprehensive commit **Key Changes Made During Resolution:** - ✅ **Kept Collapse component**: Module-scope component with proper animations - ✅ **Kept AgentSelector**: Consistent with BranchSelector design - ✅ **Kept segmented control**: Create/Start buttons with sliding animation - ✅ **Removed templates**: Template functionality no longer exists in main - ✅ **Merged keyboard**: Combined both approaches for best UX - ✅ **Kept image features**: Paste images, direct file selection, hidden drop zone **Files Modified:** - frontend/src/components/dialogs/tasks/TaskFormDialog.tsx - frontend/src/components/ui/ImageUploadSection.tsx (hideDropZone prop) - frontend/src/styles/index.css (scrollbar-hide utility) **Final State:** - Branch: `vk/6287-streamlined-new` - Base: `main` (version 0.0.111) - Status: Rebased successfully, 1 clean commit - All checks: TaskFormDialog compiles without errors The rebase is complete! Your streamlined task creation dialog is now cleanly based on the latest main branch with templates removed (since main removed them) and all other improvements intact. * Cleanup script changes for task attempt 6287280d-b79c-4713-8aea-25a1cb51b894 * TaskFormDialog improvements (vibe-kanban 7f43104e) TaskFormDialog.tsx we combined the 'Agent' and 'Configuration' dropdown into a single dropdown. This was a mistake, lets split it into two again. This will make the single action row too crowded so we should split it into two rows. The templates feature has since changed to tags so we should rename it here. * remove build.rs * task dialog code review (vibe-kanban 470400fe) ready? * remove css change * task creation code review (vibe-kanban 764af9b9) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx surely there are opportunities to simplify this code?? We can split it up to be more modular too, and follow idiomatic practices. // Set default executor from config (following TaskDetailsToolbar pattern) // Set default executor from config useEffect(() => { if (system.config?.executor_profile) { setSelectedExecutorProfile(system.config.executor_profile); } }, [system.config?.executor_profile]); // Set default executor from config (following TaskDetailsToolbar pattern) useEffect(() => { if (system.config?.executor_profile) { setSelectedExecutorProfile(system.config.executor_profile); } }, [system.config?.executor_profile]); // Handle image upload success by inserting markdown into description const handleImageUploaded = useCallback((image: ImageResponse) => { const markdownText = `![${image.original_name}](${image.file_path})`; setDescription((prev) => { why did this logic change too? I think it was working fine previously. * Fix image handling regression and reorganize TaskForm files - Fix image paste/drag-drop on first attempt by queuing pending files until ImageUploadSection mounts - Add DescriptionRowHandle ref to expose addFiles method - Move TaskFormDialog and related files into TaskForm/ subdirectory - Update all imports to reflect new file structure * fix: high-impact task form bugs and cleanup - Fix images not loading in edit mode by syncing directly to store - Fix uncloseable dialog X button still allowing close - Fix Switch accessibility with aria-label - Fix discard dialog z-index stacking (10000 to appear above parent) - Fix branch not being prefilled by including fetchedBranch in init - Remove unused useTaskFormReducer and useTaskImages hooks Amp-Thread-ID: https://ampcode.com/threads/T-1b16e2dd-3783-423e-a955-595f15cdcd63 Co-authored-by: Amp <amp@ampcode.com> * Fix conditional hook calls in AgentSelector and ConfigSelector Move all React hooks to be called unconditionally before early returns to comply with rules-of-hooks linter. Amp-Thread-ID: https://ampcode.com/threads/T-224d8a3a-a1e2-4aee-92c9-3829570ac92a Co-authored-by: Amp <amp@ampcode.com> * Refactor: Deduplicate agent and config selection logic - Add showLabel prop to AgentSelector and ConfigSelector for conditional label rendering - Refactor ExecutorProfileSelector to use AgentSelector and ConfigSelector as building blocks - Reduce ExecutorProfileSelector from 182 to 49 lines by eliminating duplicate dropdown UI/logic - Maintain backward compatibility with CreateModeDropdownsRow (labels hidden by default) Amp-Thread-ID: https://ampcode.com/threads/T-83022511-4893-49e5-9943-ff293cb2cfae Co-authored-by: Amp <amp@ampcode.com> * one file * Consolidate task form dialog: reduce from ~15 files to 4 Massively reduced indirection in task form components: Before: - TaskFormDialog.tsx (main orchestrator) - 5 row components (TitleRow, DescriptionRow, CreateModeDropdownsRow, EditModeStatusRow, ActionsRow) - DiscardWarningDialog.tsx - DragOverlay.tsx - useTaskFormStore.ts (Zustand global store) - 4 hooks (useTaskFormKeyboardShortcuts, useUnsavedChanges, useDragAndDropUpload, useTaskBranches) After: - TaskFormDialog.tsx (~650 LOC) - single file with local useReducer, all UI inlined - TaskDialog.tsx (kept - reusable primitive) - AgentSelector.tsx (kept - shared with ExecutorProfileSelector) - ConfigSelector.tsx (kept - shared with ExecutorProfileSelector) Changes: - Replaced global Zustand store with local useReducer - Inlined all row components directly into main component - Inlined keyboard shortcuts, drag-and-drop, unsaved changes, branch fetching - Inlined submission logic - Removed DescriptionRow forwardRef wrapper - manage imageUploadRef directly - Eliminated ~12 files worth of TypeScript prop overhead Result: Easier to fit entire form logic in your head, fewer files to navigate * remove unused variant * run formatter * always show branch selector remove usage of `e.returnValue = ''` move reducer init to function instead of useEffect. * remove reducer log * Prevent branch selector from growing with long branch names - Add flex-1 min-w-0 to all three selectors (Agent, Config, Branch) in TaskFormDialog to share space equally - Add truncation and flex constraints to branch name in BranchSelector dropdown rows - Prevent icons from shrinking with flex-shrink-0 Amp-Thread-ID: https://ampcode.com/threads/T-4db8d895-5cd9-4add-bd04-99230421e1a6 Co-authored-by: Amp <amp@ampcode.com> * always show all selectors in create mode * format * Show 'Starting...' instead of 'Creating...' when auto-start is enabled Amp-Thread-ID: https://ampcode.com/threads/T-e848b304-7e1a-4d5a-96c6-4a8de8c467b2 Co-authored-by: Amp <amp@ampcode.com> * Add i18n support to TaskFormDialog with translations for en, ja, ko, es Amp-Thread-ID: https://ampcode.com/threads/T-bfb9e3c9-a223-4f61-870f-e3d5f5cc8282 Co-authored-by: Amp <amp@ampcode.com> * scrollable task images * Update TaskFormDialog and TextArea components Refactor task form layout and add textarea scroll control * format * Reset modal state when discarding changes in TaskFormDialog Amp-Thread-ID: https://ampcode.com/threads/T-922491df-dedd-49b7-a9b2-84bb5a5da57c Co-authored-by: Amp <amp@ampcode.com> * Apply rounded corners to TaskDialog at all screen sizes Amp-Thread-ID: https://ampcode.com/threads/T-1d39709c-08d1-45e2-ac90-121009d9c7d2 Co-authored-by: Amp <amp@ampcode.com> * fix linter * default rows to 20 * update text style * refactor: replace direct API calls with hooks in TaskFormDialog - Created useProjectBranches hook for fetching project branches - Created useImageUpload hook for image upload/delete operations - Replaced direct projectsApi, attemptsApi, and imagesApi calls with hooks - Simplified useEffect logic by leveraging React Query hooks Amp-Thread-ID: https://ampcode.com/threads/T-cba1447c-50e3-4897-9cd9-a3bce7fc0338 Co-authored-by: Amp <amp@ampcode.com> * use shadcn switch * resolve conflict in package.json * reset TaskFormDialog to initial state when discarding changes * Refactor to use ExecutorProfileSelector in TaskFormDialog - Add className and itemClassName props to ExecutorProfileSelector for flexible styling - Replace separate AgentSelector + ConfigSelector with unified ExecutorProfileSelector in TaskFormDialog - Maintain equal width distribution across agent, config, and branch selectors Amp-Thread-ID: https://ampcode.com/threads/T-9d82764f-cb37-4020-b5a2-8bd24df1be90 Co-authored-by: Amp <amp@ampcode.com> * Reset form state in TaskFormDialog when dialog opens or task changes * streamlined tk scenarios (vibe-kanban 845b2e25) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx I am experiencing the following bug: <bug> Context TaskFormDialog is a modal for creating/editing tasks. When there are unsaved changes, pressing ESC should show a warning dialog asking if the user wants to discard changes. Test Scenarios & Last Reported Status Scenario 1: No changes + focused input Action: Open dialog → title field is autofocused → press ESC once Expected: Dialog closes immediately Last Reported: ❌ FAIL - ESC does nothing (after Input blur behavior was removed) Scenario 2: No changes + unfocused Action: Open dialog → click outside input to unfocus → press ESC once Expected: Dialog closes immediately Last Reported: ✅ PASS Scenario 3: With changes + focused input Action: Open dialog → type in title field (remains focused) → press ESC Expected: ESC #1: Warning dialog appears immediately ESC #2: Warning dialog closes (return to task form) ESC #3: Warning dialog appears again Last Reported: ❌ FAIL - Warning opens on ESC #1, but subsequent ESC presses do nothing Scenario 4: With changes + unfocused Action: Open dialog → type in field → click outside to unfocus → press ESC Expected: Same as Scenario 3 Last Reported: ❌ FAIL - Closes the underlying kanban board while keeping the dialog visible Scenario 5: Warning → Continue Editing → ESC again Action: Open dialog → make changes → ESC (warning appears) → click "Continue Editing" button → ESC again Expected: Warning dialog should reappear Last Reported: ❌ FAIL - Closes the underlying kanban board instead Root Cause (From Console Logs) The warning Dialog component manages keyboard scopes independently, causing scope conflicts with the parent TaskDialog. When the warning closes, it enables KANBAN scope even though TaskDialog is still open, causing subsequent ESC presses to close the kanban board instead. </bug> I need your help to identify the exact cause of this bug and implement an effective solution. To do this, carefully follow the workflow below, in this specific order: --- ## Workflow ### **Step 1: Clarification (if needed)** - If any part of this prompt is unclear or confusing, ask clarifying questions before proceeding. - Do not ask questions unnecessarily… only ask if essential information is missing. --- ### **Step 2: Initial Analysis** - Quickly review the relevant code to understand the bug's surface area. - Identify key execution paths and data flows related to the bug. - **Assess reproduction feasibility:** Can the bug be reliably reproduced in the running application with available tools? - **Don't over-invest here** - gather just enough context to plan your investigation strategy. --- ### **Step 3: Choose Investigation Strategy** Based on your Step 2 assessment, select one of three paths: #### **Path A: Direct Observation (STRONGLY PREFERRED)** **When to use:** - Bug can be reproduced in the running application - Available tools (browser, network requests, console logs, tmux sessions) are sufficient to observe the issue - **This is the default choice - only deviate if you have a compelling reason** **Why this is preferred:** - Tests the actual application behaviour - Captures real-world interactions and state - Provides the most accurate diagnostic information - Fixes are validated in the true environment **Proceed to Step 4** --- #### **Path B: Isolated Prototype (use sparingly)** **When to use (rare cases only):** - Bug involves a complex algorithm or data structure that can be completely isolated from application context - The issue is conceptually pure and self-contained - Full application context adds overwhelming noise that makes diagnosis impossible - Example: "Custom sorting algorithm produces incorrect order for specific edge case" **What to do:** - Create a from-scratch minimal reproduction: - **Backend:** New isolated crate with focused unit tests - **Frontend:** New Vite project with just the problem component/logic - Debug in this controlled environment - Once understood, apply the fix to the main codebase - **Skip to Step 10** **Note:** Human intervention is unlikely to be needed with this approach since you control the entire reproduction environment. --- #### **Path C: Prototyping Playground (use sparingly)** **When to use (rare cases only):** - Bug requires some application context (routes, API, state management) but the full production setup has too many confounding variables - You need to iterate quickly on a specific feature without affecting the main application - Example: "Auth flow fails under specific user state conditions that are difficult to reproduce" **What to do:** - Create a focused testing ground within the application: - **Frontend:** New route (e.g., `/debug-auth-flow`) that isolates the problematic feature - **Backend:** New module/crate with comprehensive unit tests targeting the issue - Instrument and test in this playground - Apply learnings to the main implementation - **Skip to Step 10** **Note:** Human intervention is unlikely to be needed with this approach since you're building a controlled test environment. --- ### **Step 4: Design Instrumentation Strategy** (Path A only) - Determine what information would definitively diagnose the root cause. - Identify strategic logging points: - Entry/exit points of suspect functions - State changes in relevant data structures - Conditional branches that could explain the behaviour - Network requests/responses (observable via `browser_network_requests` tool) - Browser console messages (observable via `browser_console_messages` tool) - Backend logs (observable via tmux session) - Plan both backend (console/file logs) and frontend (browser console) instrumentation as needed. - **Focus on quality over quantity** - add logging where it will provide maximum diagnostic value. --- ### **Step 5: Implement Logging** (Path A only) - Add comprehensive, structured logging at identified points. - Include relevant context: variable values, timestamps, call stacks, user actions, etc. - Make logs easily grep-able/filterable with clear prefixes (e.g., `[BUG_DEBUG]`). - Ensure log messages are descriptive enough to understand what's happening without reading code. --- ### **Step 6: Run & Observe** (Path A only) - Start the application in a new tmux session (for backend logs). - Use `browser_console_messages` to monitor frontend logs. - Use `browser_network_requests` to observe API/network activity. - Attempt to reproduce the bug with instrumentation active. - Collect and analyse log output from all sources. **Human Intervention Point:** If reproduction fails or observations are inconclusive: - Explicitly request human assistance. - Explain what was attempted and what information is still needed. - Suggest specific ways the human could help (e.g., "Could you reproduce the bug and share the exact steps?" or "Can you verify if X behaviour occurs when you do Y?"). - Provide clear context so the human can help efficiently. --- ### **Step 7: Diagnose from Evidence** (Path A only) - Review actual runtime behaviour from logs, network requests, and console messages. - Identify the precise failure point and root cause. - **Base your diagnosis on observed facts, not hypotheses.** - If the evidence points to multiple possible causes, gather more targeted data before proceeding. --- ### **Step 8: Implement Fix** (Path A only) - Fix directly in the current worktree based on evidence from Step 7. - Keep diagnostic logging in place initially (you'll verify the fix in Step 9). - Ensure the fix addresses the root cause, not just the symptoms. --- ### **Step 9: Verify Fix** (Path A only) - Run the application again with logging still active. - Reproduce the original bug scenario. - Confirm the bug is resolved through observed behaviour. - Use `browser_network_requests` and `browser_console_messages` to verify expected behaviour. - Compare "before" and "after" logs if helpful. **Human Intervention Point:** If verification is unclear or requires domain knowledge: - Explicitly request human verification. - Provide clear, step-by-step instructions for what to test. - Explain what success looks like (expected vs actual behaviour). - Share relevant log excerpts or observations that informed your fix. --- ### **Step 10: Report to User** **For Path A (Direct Observation):** Provide a clear summary including: - **Root cause:** Explain what was actually happening based on observed evidence - **Diagnostic process:** Briefly describe how logging/observation revealed the issue - **Implemented fix:** Describe the changes made and why they address the root cause - **Verification results:** Confirm the fix works (or request human verification if needed) **For Path B/C (Prototype/Playground):** Provide a clear summary including: - **Why this approach was chosen:** Explain why direct observation wasn't suitable - **What was learned:** Describe insights gained from the isolated environment - **How the fix was applied:** Explain how learnings translated to the main codebase - **Relevant artefacts:** Share any reproduction code, tests, or documentation created --- ### **Step 11: Automation Improvement Plan** (optional) **Only include this section if:** - The diagnosis was more difficult or time-consuming than it should have been, OR - You encountered obstacles that could be prevented with codebase improvements, OR - You required human intervention during the process **What to include:** - Analyse what made this bug difficult to diagnose automatically - Propose specific, actionable codebase changes that would improve future automation: - **Accessibility improvements:** ARIA labels, test IDs, semantic HTML (dual benefit: improved accessibility for users + easier automation) - **Logging enhancements:** Structured logging, better error messages, trace IDs, contextual information - **Testability improvements:** Dependency injection, pure functions, better component boundaries - **Observability additions:** Health checks, metrics endpoints, debug modes, feature flags - Categorise suggestions by impact and implementation effort - **Important:** Suggestions should be practical and should not sacrifice application quality, performance, or maintainability --- ### **Step 12: Clean Up** (optional, Path A only) - Remove or reduce instrumentation to production-appropriate levels. - Keep any logging that would be valuable for future debugging. - For Path C: Remove any debug routes/playgrounds unless they have ongoing value. - Commit your changes with a clear, descriptive commit message. --- ## Key Principles 1. **Observation over speculation:** Always prefer gathering evidence from the running application over generating hypotheses. 2. **Path A is strongly preferred:** Only deviate to Path B or C if you have a compelling, articulated reason why direct observation won't work. 3. **Request human help when needed:** If you're stuck, be explicit about it. Humans can provide reproduction steps, domain knowledge, or verification that may be difficult to automate. 4. **Evidence-based fixes:** Every fix should be grounded in observed behaviour, not guesswork. 5. **Practical improvements:** If suggesting automation improvements, focus on changes that provide clear value without compromising the application. * formatter * tanstack form docs * create plan * doc * migrate TaskFormDialog to tanstack form * remove docs * run formatter * Fix: prevent discard warning when no user changes made Use dontUpdateMeta option when programmatically setting branch value to avoid marking form as dirty on initialization Amp-Thread-ID: https://ampcode.com/threads/T-dea5ff8e-d78b-474e-8797-8fc287a27152 Co-authored-by: Amp <amp@ampcode.com> * Search should be positioned relative to caret, not textarea (vibe-kanban 751134be) frontend/src/components/ui/file-search-textarea.tsx * use existing dialog (vibe-kanban 69528431) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx TaskDialog.tsx We have created a new dialog component. Can we reuse the existing one? Will this cause any regressions? * Use TanStack Form validators for TaskFormDialog validation - Add field-level validators (onMount + onChange) for title, executorProfileId, and branch - Remove inline validation logic from Subscribe block - Extract shared validator functions to avoid duplication - Button disabled state now uses form.state.canSubmit directly - Validators run on mount to ensure correct initial state Amp-Thread-ID: https://ampcode.com/threads/T-d0b0fb0f-cdb9-4647-a5e3-415421c5edd5 Co-authored-by: Amp <amp@ampcode.com> * Fix dialog close button not clickable due to z-index issue Add z-10 class to the close button to ensure it appears above dialog content and remains clickable. The button was being blocked by overlapping content elements within the dialog. Amp-Thread-ID: https://ampcode.com/threads/T-729fe4d3-24c9-48cb-9e3c-46ddfed1d660 Co-authored-by: Amp <amp@ampcode.com> * formatter * update pnpm lock * revert changes to dialog.tsx * bring back z-10 (if p-0 is set then this is necessary) * Revert "Use TanStack Form validators for TaskFormDialog validation" This reverts commit 6d946dd88a6ae0c341943d1adcc25261743bfad5. * update title validator * reactive form state * update effect * localise `dropImagesHere` text use form level validation over field level validation make autoStart a form field s.t. it triggers form level validation on change use react-dropzone to implement the image upload button remove unnecessary usage of useCallback simplify handleSubmit function (no useCallback, assume valid values after form validation, unify task variable) remove showImageUpload state create editMode variable use canSubmit to control primary action button disabled state extract warning dialog to its own component * update loading handling * update hook import * update pnpm lock * tsc --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: Louis Knight-Webb <louis@bloop.ai>
2025-11-17 15:21:36 +00:00
hideDropZone = false,
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
className,
},
ref
) => {
const [isExpanded, setIsExpanded] = useState(
defaultExpanded || images.length > 0
);
const [isDragging, setIsDragging] = useState(false);
const [uploadingFiles, setUploadingFiles] = useState<Set<string>>(
new Set()
);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const latestImagesRef = useRef(images);
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
useEffect(() => {
latestImagesRef.current = images;
}, [images]);
useEffect(() => {
if (collapsible && images.length > 0 && !isExpanded) {
setIsExpanded(true);
}
Batch B: Fix React Hooks dependency warnings in core files (vibe-kanban) (#1307) * Excellent! All done! Let me create a summary: ## ✅ Batch B Complete: All React Hooks Exhaustive-Deps Warnings Fixed Successfully fixed **all 22 exhaustive-deps warnings** across the codebase. The changes improved code correctness and stability. ### Files Fixed (15 total): 1. **useProjectTasks.ts** - Wrapped logical expressions in useMemo 2. **useConversationHistory.ts** - Wrapped functions in useCallback, added missing deps 3. **useShowcasePersistence.ts** - Wrapped logical expression in useMemo 4. **auto-expanding-textarea.tsx** - Added missing deps, destructured props 5. **App.tsx** - Added missing updateAndSaveConfig dep 6. **EditDiffRenderer.tsx** - Removed unnecessary path dep 7. **PreviewPanel.tsx** - Fixed latestDevServerProcess dependency 8. **project-form-fields.tsx** - Wrapped loadRecentRepos in useCallback 9. **project-list.tsx** - Wrapped fetchProjects in useCallback 10. **ImageUploadSection.tsx** - Added isExpanded dep 11. **file-search-textarea.tsx** - Added textareaRef dep 12. **useJsonPatchWsStream.ts** - Fixed options dependency 13. **useSemanticKey.ts** - Removed unnecessary action dep 14. **McpSettings.tsx** - Added profiles dep 15. **project-tasks.tsx** - Moved navigateWithSearch before usage ### Key Changes: - Added `useCallback` where functions are used in dependency arrays - Added `useMemo` to stabilize object/array references - Fixed function declaration order to avoid hoisting issues - One ESLint disable for circular dependency case (documented) ### Verification: - ✅ **0 exhaustive-deps warnings** (down from 22) - ✅ **Type check passes** (`pnpm run check`) - ✅ **All changes follow style guide** (simplest, most readable) * Cleanup script changes for task attempt 0564411a-2cf4-488a-a082-d0f7ebcfc101 * Perfect! All fixed. Let me create a summary: ## ✅ Fixed Infinite Re-render Issue in useJsonPatchWsStream ### Root Cause The `options` object had a new identity on every render (from default `= {}`), causing the useEffect to restart infinitely and trigger continuous re-renders. ### Changes Applied **useJsonPatchWsStream.ts:** 1. ✅ Removed default parameter: `options?: UseJsonPatchStreamOptions<T>` (no more `= {}`) 2. ✅ Destructured options at the top: ```typescript const injectInitialEntry = options?.injectInitialEntry; const deduplicatePatches = options?.deduplicatePatches; ``` 3. ✅ Updated all usages to use destructured variables 4. ✅ Fixed dependency array: ```typescript }, [endpoint, enabled, initialData, injectInitialEntry, deduplicatePatches, retryNonce]); ``` **useConversationHistory.ts:** - Added comment explaining why `emitEntries` is omitted from deps (it's stable) ### Verification - ✅ **Type check passes** (`pnpm run check`) - ✅ **0 exhaustive-deps warnings** - ✅ **No infinite re-renders** (destructured variables have stable identities) ### Why This Works - Destructured variables (`injectInitialEntry`, `deduplicatePatches`) maintain stable identities across renders (undefined stays undefined) - Only changes when callbacks are actually different, not on every render - More explicit and readable - shows exactly what triggers reconnection * Cleanup script changes for task attempt 0564411a-2cf4-488a-a082-d0f7ebcfc101 * Perfect! Let me create a final summary of all the work done: ## ✅ Complete: Removed eslint-disable Tech Debt ### What Was Done Refactored `useConversationHistory.ts` to eliminate the eslint-disable by reordering function definitions so dependencies are declared before use. ### Changes **Reordered functions in useConversationHistory.ts:** ``` Old order: loadRunningAndEmit → emitEntries (hoisting error) New order: 1. patchWithKey (helper) 2. flattenEntries (helper) 3. getActiveAgentProcess (helper) 4. flattenEntriesForEmit (useCallback) 5. emitEntries (useCallback, depends on flattenEntriesForEmit) ✅ 6. loadRunningAndEmit (useCallback, depends on emitEntries) ✅ 7. loadRunningAndEmitWithBackoff (depends on loadRunningAndEmit) ``` **Updated dependency array:** - `loadRunningAndEmit`: Now properly includes `[emitEntries]` - Removed eslint-disable comment ### Final Results - ✅ **0 exhaustive-deps warnings** (down from 22) - ✅ **TypeScript check passes** - ✅ **No eslint-disable tech debt** - ✅ **No infinite re-renders** - ✅ **More readable** (dependencies declared before use) All React Hooks warnings properly fixed with clean, maintainable code! * Cleanup script changes for task attempt 0564411a-2cf4-488a-a082-d0f7ebcfc101
2025-11-17 22:12:23 +00:00
}, [collapsible, images.length, isExpanded]);
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
const handleFiles = useCallback(
async (filesInput: FileList | File[] | null) => {
if (!filesInput || disabled || readOnly) return;
const files = Array.isArray(filesInput)
? filesInput
: Array.from(filesInput);
setErrorMessage(null);
const invalidFiles: string[] = [];
const oversizedFiles: string[] = [];
const validFiles: File[] = [];
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
files.forEach((file) => {
if (!VALID_TYPES.includes(file.type.toLowerCase())) {
invalidFiles.push(file.name);
return;
}
if (file.size > MAX_SIZE_BYTES) {
oversizedFiles.push(
`${file.name} (${(file.size / 1048576).toFixed(1)} MB)`
);
return;
}
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
validFiles.push(file);
});
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
if (invalidFiles.length > 0 || oversizedFiles.length > 0) {
const errors: string[] = [];
if (invalidFiles.length > 0) {
errors.push(`Unsupported file type: ${invalidFiles.join(', ')}`);
}
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
if (oversizedFiles.length > 0) {
errors.push(
`Files too large (max 20 MB): ${oversizedFiles.join(', ')}`
);
}
setErrorMessage(errors.join('. '));
}
for (const file of validFiles) {
const tempId = `uploading-${Date.now()}-${file.name}`;
setUploadingFiles((prev) => new Set(prev).add(tempId));
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
try {
const uploadedImage = await onUpload(file);
// Call custom upload callback if provided, otherwise use default behavior
if (onImageUploaded) {
onImageUploaded(uploadedImage);
} else {
const nextImages = [...latestImagesRef.current, uploadedImage];
latestImagesRef.current = nextImages;
onImagesChange(nextImages);
}
setErrorMessage(null);
## ✅ Batch D Complete (#1313) Successfully fixed all low-priority `any` types and catch blocks across 7 files: ### Changes Made: **1. [lib/types.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/lib/types.ts)** - Added imports: `NormalizedEntry`, `ExecutionProcessStatus` - `entry: any` → `entry: NormalizedEntry` - `process: any` → `process: ExecutionProcess` - `processStatus: string` → `processStatus: ExecutionProcessStatus` **2. [lib/modals.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/lib/modals.ts)** - Removed `any[]` and `component as any` - Properly typed function arguments with `ShowArgs<P>` - Used `React.FC<ComponentProps<P>>` for NiceModal compatibility **3. [EditBranchNameDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/dialogs/tasks/EditBranchNameDialog.tsx)** - `catch (err: any)` → `catch (err: unknown)` - Used `getErrorMessage(err)` helper **4. [TagEditDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/dialogs/tasks/TagEditDialog.tsx)** - `catch (err: any)` → `catch (err: unknown)` - Used `getErrorMessage(err)` helper **5. [GhCliSetupDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/dialogs/auth/GhCliSetupDialog.tsx)** - `catch (err: any)` → `catch (err: unknown)` - Added safe type narrowing with `isGhCliSetupError` guard - Used `getErrorMessage(err)` helper **6. [ImageUploadSection.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/ui/ImageUploadSection.tsx)** - `catch (error: any)` → `catch (error: unknown)` - Used `instanceof Error` check **7. [McpSettings.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/pages/settings/McpSettings.tsx)** - `catch (err: any)` → `catch (err: unknown)` - `Record<string, any>` → `Record<string, unknown>` for preconfigured/meta/servers - Added safe narrowing for meta access All type checks pass ✓ All formatting complete ✓
2025-11-17 22:54:11 +00:00
} catch (error: unknown) {
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
console.error('Failed to upload image:', error);
const message =
## ✅ Batch D Complete (#1313) Successfully fixed all low-priority `any` types and catch blocks across 7 files: ### Changes Made: **1. [lib/types.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/lib/types.ts)** - Added imports: `NormalizedEntry`, `ExecutionProcessStatus` - `entry: any` → `entry: NormalizedEntry` - `process: any` → `process: ExecutionProcess` - `processStatus: string` → `processStatus: ExecutionProcessStatus` **2. [lib/modals.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/lib/modals.ts)** - Removed `any[]` and `component as any` - Properly typed function arguments with `ShowArgs<P>` - Used `React.FC<ComponentProps<P>>` for NiceModal compatibility **3. [EditBranchNameDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/dialogs/tasks/EditBranchNameDialog.tsx)** - `catch (err: any)` → `catch (err: unknown)` - Used `getErrorMessage(err)` helper **4. [TagEditDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/dialogs/tasks/TagEditDialog.tsx)** - `catch (err: any)` → `catch (err: unknown)` - Used `getErrorMessage(err)` helper **5. [GhCliSetupDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/dialogs/auth/GhCliSetupDialog.tsx)** - `catch (err: any)` → `catch (err: unknown)` - Added safe type narrowing with `isGhCliSetupError` guard - Used `getErrorMessage(err)` helper **6. [ImageUploadSection.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/components/ui/ImageUploadSection.tsx)** - `catch (error: any)` → `catch (error: unknown)` - Used `instanceof Error` check **7. [McpSettings.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/3da6-batch-d-fix-low/frontend/src/pages/settings/McpSettings.tsx)** - `catch (err: any)` → `catch (err: unknown)` - `Record<string, any>` → `Record<string, unknown>` for preconfigured/meta/servers - Added safe narrowing for meta access All type checks pass ✓ All formatting complete ✓
2025-11-17 22:54:11 +00:00
error instanceof Error
? error.message
: 'Failed to upload image. Please try again.';
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
setErrorMessage(message);
} finally {
setUploadingFiles((prev) => {
const next = new Set(prev);
next.delete(tempId);
return next;
});
}
}
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
},
[disabled, readOnly, onUpload, onImageUploaded, onImagesChange]
);
useImperativeHandle(
ref,
() => ({
addFiles: async (files: FileList | File[] | null) => {
await handleFiles(files);
},
}),
[handleFiles]
);
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
const handleDrop = useCallback(
(e: React.DragEvent) => {
e.preventDefault();
setIsDragging(false);
void handleFiles(e.dataTransfer.files);
},
[handleFiles]
);
const handleDragOver = useCallback((e: React.DragEvent) => {
e.preventDefault();
setIsDragging(true);
}, []);
const handleDragLeave = useCallback((e: React.DragEvent) => {
e.preventDefault();
setIsDragging(false);
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
}, []);
const handleRemoveImage = useCallback(
async (imageId: string) => {
if (onDelete) {
try {
await onDelete(imageId);
} catch (error) {
console.error('Failed to delete image:', error);
}
}
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
onImagesChange(images.filter((img) => img.id !== imageId));
},
[images, onImagesChange, onDelete]
);
const content = (
<div className={cn('space-y-3', className)}>
{/* Error message */}
{errorMessage && (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertDescription>{errorMessage}</AlertDescription>
</Alert>
)}
{/* Read-only message */}
{readOnly && images.length === 0 && (
<p className="text-sm text-muted-foreground">No images attached</p>
)}
Improve task creation dialog (vibe-kanban) (#1007) * Streamline task creation dialog with improved UX - Wider dialog (40rem max width, grows to 95vh height) - Clean input styling without labels - Auto-growing description field (4-30 rows) - Horizontal scrollable template section (shows only when form is empty) - Smooth collapse animations for templates and image upload - Combined agent+configuration selector matching BranchSelector design - Direct file selection via image button (no drag/drop zone) - Paste images directly into description - Segmented control for Create/Start modes - Agent/branch selectors only visible in Start mode - Integrated keyboard shortcuts (Cmd+Enter for primary, Cmd+Shift+Enter for alternate) - Removed unnecessary spacing and borders - Square button design for consistent appearance Amp-Thread-ID: https://ampcode.com/threads/T-c82dd85e-72cc-4792-87b7-aa8496eedcbd Co-authored-by: Amp <amp@ampcode.com> * These are all configuration errors (like --jsx flag), not errors in our file. The rebase is complete and successful! Let me create a summary: ## ✅ **Rebase Successfully Completed!** **Conflict Resolution Summary:** 1. ✅ **Removed template functionality**: Main removed templates API, so I removed all template-related code 2. ✅ **Merged image pasting**: Kept our image paste implementation with auto-show upload section 3. ✅ **Integrated keyboard shortcuts**: Merged our shouldStart logic with main's isTextareaFocused approach 4. ✅ **Squashed commits**: Combined 25 small commits into 1 comprehensive commit **Key Changes Made During Resolution:** - ✅ **Kept Collapse component**: Module-scope component with proper animations - ✅ **Kept AgentSelector**: Consistent with BranchSelector design - ✅ **Kept segmented control**: Create/Start buttons with sliding animation - ✅ **Removed templates**: Template functionality no longer exists in main - ✅ **Merged keyboard**: Combined both approaches for best UX - ✅ **Kept image features**: Paste images, direct file selection, hidden drop zone **Files Modified:** - frontend/src/components/dialogs/tasks/TaskFormDialog.tsx - frontend/src/components/ui/ImageUploadSection.tsx (hideDropZone prop) - frontend/src/styles/index.css (scrollbar-hide utility) **Final State:** - Branch: `vk/6287-streamlined-new` - Base: `main` (version 0.0.111) - Status: Rebased successfully, 1 clean commit - All checks: TaskFormDialog compiles without errors The rebase is complete! Your streamlined task creation dialog is now cleanly based on the latest main branch with templates removed (since main removed them) and all other improvements intact. * Cleanup script changes for task attempt 6287280d-b79c-4713-8aea-25a1cb51b894 * TaskFormDialog improvements (vibe-kanban 7f43104e) TaskFormDialog.tsx we combined the 'Agent' and 'Configuration' dropdown into a single dropdown. This was a mistake, lets split it into two again. This will make the single action row too crowded so we should split it into two rows. The templates feature has since changed to tags so we should rename it here. * remove build.rs * task dialog code review (vibe-kanban 470400fe) ready? * remove css change * task creation code review (vibe-kanban 764af9b9) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx surely there are opportunities to simplify this code?? We can split it up to be more modular too, and follow idiomatic practices. // Set default executor from config (following TaskDetailsToolbar pattern) // Set default executor from config useEffect(() => { if (system.config?.executor_profile) { setSelectedExecutorProfile(system.config.executor_profile); } }, [system.config?.executor_profile]); // Set default executor from config (following TaskDetailsToolbar pattern) useEffect(() => { if (system.config?.executor_profile) { setSelectedExecutorProfile(system.config.executor_profile); } }, [system.config?.executor_profile]); // Handle image upload success by inserting markdown into description const handleImageUploaded = useCallback((image: ImageResponse) => { const markdownText = `![${image.original_name}](${image.file_path})`; setDescription((prev) => { why did this logic change too? I think it was working fine previously. * Fix image handling regression and reorganize TaskForm files - Fix image paste/drag-drop on first attempt by queuing pending files until ImageUploadSection mounts - Add DescriptionRowHandle ref to expose addFiles method - Move TaskFormDialog and related files into TaskForm/ subdirectory - Update all imports to reflect new file structure * fix: high-impact task form bugs and cleanup - Fix images not loading in edit mode by syncing directly to store - Fix uncloseable dialog X button still allowing close - Fix Switch accessibility with aria-label - Fix discard dialog z-index stacking (10000 to appear above parent) - Fix branch not being prefilled by including fetchedBranch in init - Remove unused useTaskFormReducer and useTaskImages hooks Amp-Thread-ID: https://ampcode.com/threads/T-1b16e2dd-3783-423e-a955-595f15cdcd63 Co-authored-by: Amp <amp@ampcode.com> * Fix conditional hook calls in AgentSelector and ConfigSelector Move all React hooks to be called unconditionally before early returns to comply with rules-of-hooks linter. Amp-Thread-ID: https://ampcode.com/threads/T-224d8a3a-a1e2-4aee-92c9-3829570ac92a Co-authored-by: Amp <amp@ampcode.com> * Refactor: Deduplicate agent and config selection logic - Add showLabel prop to AgentSelector and ConfigSelector for conditional label rendering - Refactor ExecutorProfileSelector to use AgentSelector and ConfigSelector as building blocks - Reduce ExecutorProfileSelector from 182 to 49 lines by eliminating duplicate dropdown UI/logic - Maintain backward compatibility with CreateModeDropdownsRow (labels hidden by default) Amp-Thread-ID: https://ampcode.com/threads/T-83022511-4893-49e5-9943-ff293cb2cfae Co-authored-by: Amp <amp@ampcode.com> * one file * Consolidate task form dialog: reduce from ~15 files to 4 Massively reduced indirection in task form components: Before: - TaskFormDialog.tsx (main orchestrator) - 5 row components (TitleRow, DescriptionRow, CreateModeDropdownsRow, EditModeStatusRow, ActionsRow) - DiscardWarningDialog.tsx - DragOverlay.tsx - useTaskFormStore.ts (Zustand global store) - 4 hooks (useTaskFormKeyboardShortcuts, useUnsavedChanges, useDragAndDropUpload, useTaskBranches) After: - TaskFormDialog.tsx (~650 LOC) - single file with local useReducer, all UI inlined - TaskDialog.tsx (kept - reusable primitive) - AgentSelector.tsx (kept - shared with ExecutorProfileSelector) - ConfigSelector.tsx (kept - shared with ExecutorProfileSelector) Changes: - Replaced global Zustand store with local useReducer - Inlined all row components directly into main component - Inlined keyboard shortcuts, drag-and-drop, unsaved changes, branch fetching - Inlined submission logic - Removed DescriptionRow forwardRef wrapper - manage imageUploadRef directly - Eliminated ~12 files worth of TypeScript prop overhead Result: Easier to fit entire form logic in your head, fewer files to navigate * remove unused variant * run formatter * always show branch selector remove usage of `e.returnValue = ''` move reducer init to function instead of useEffect. * remove reducer log * Prevent branch selector from growing with long branch names - Add flex-1 min-w-0 to all three selectors (Agent, Config, Branch) in TaskFormDialog to share space equally - Add truncation and flex constraints to branch name in BranchSelector dropdown rows - Prevent icons from shrinking with flex-shrink-0 Amp-Thread-ID: https://ampcode.com/threads/T-4db8d895-5cd9-4add-bd04-99230421e1a6 Co-authored-by: Amp <amp@ampcode.com> * always show all selectors in create mode * format * Show 'Starting...' instead of 'Creating...' when auto-start is enabled Amp-Thread-ID: https://ampcode.com/threads/T-e848b304-7e1a-4d5a-96c6-4a8de8c467b2 Co-authored-by: Amp <amp@ampcode.com> * Add i18n support to TaskFormDialog with translations for en, ja, ko, es Amp-Thread-ID: https://ampcode.com/threads/T-bfb9e3c9-a223-4f61-870f-e3d5f5cc8282 Co-authored-by: Amp <amp@ampcode.com> * scrollable task images * Update TaskFormDialog and TextArea components Refactor task form layout and add textarea scroll control * format * Reset modal state when discarding changes in TaskFormDialog Amp-Thread-ID: https://ampcode.com/threads/T-922491df-dedd-49b7-a9b2-84bb5a5da57c Co-authored-by: Amp <amp@ampcode.com> * Apply rounded corners to TaskDialog at all screen sizes Amp-Thread-ID: https://ampcode.com/threads/T-1d39709c-08d1-45e2-ac90-121009d9c7d2 Co-authored-by: Amp <amp@ampcode.com> * fix linter * default rows to 20 * update text style * refactor: replace direct API calls with hooks in TaskFormDialog - Created useProjectBranches hook for fetching project branches - Created useImageUpload hook for image upload/delete operations - Replaced direct projectsApi, attemptsApi, and imagesApi calls with hooks - Simplified useEffect logic by leveraging React Query hooks Amp-Thread-ID: https://ampcode.com/threads/T-cba1447c-50e3-4897-9cd9-a3bce7fc0338 Co-authored-by: Amp <amp@ampcode.com> * use shadcn switch * resolve conflict in package.json * reset TaskFormDialog to initial state when discarding changes * Refactor to use ExecutorProfileSelector in TaskFormDialog - Add className and itemClassName props to ExecutorProfileSelector for flexible styling - Replace separate AgentSelector + ConfigSelector with unified ExecutorProfileSelector in TaskFormDialog - Maintain equal width distribution across agent, config, and branch selectors Amp-Thread-ID: https://ampcode.com/threads/T-9d82764f-cb37-4020-b5a2-8bd24df1be90 Co-authored-by: Amp <amp@ampcode.com> * Reset form state in TaskFormDialog when dialog opens or task changes * streamlined tk scenarios (vibe-kanban 845b2e25) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx I am experiencing the following bug: <bug> Context TaskFormDialog is a modal for creating/editing tasks. When there are unsaved changes, pressing ESC should show a warning dialog asking if the user wants to discard changes. Test Scenarios & Last Reported Status Scenario 1: No changes + focused input Action: Open dialog → title field is autofocused → press ESC once Expected: Dialog closes immediately Last Reported: ❌ FAIL - ESC does nothing (after Input blur behavior was removed) Scenario 2: No changes + unfocused Action: Open dialog → click outside input to unfocus → press ESC once Expected: Dialog closes immediately Last Reported: ✅ PASS Scenario 3: With changes + focused input Action: Open dialog → type in title field (remains focused) → press ESC Expected: ESC #1: Warning dialog appears immediately ESC #2: Warning dialog closes (return to task form) ESC #3: Warning dialog appears again Last Reported: ❌ FAIL - Warning opens on ESC #1, but subsequent ESC presses do nothing Scenario 4: With changes + unfocused Action: Open dialog → type in field → click outside to unfocus → press ESC Expected: Same as Scenario 3 Last Reported: ❌ FAIL - Closes the underlying kanban board while keeping the dialog visible Scenario 5: Warning → Continue Editing → ESC again Action: Open dialog → make changes → ESC (warning appears) → click "Continue Editing" button → ESC again Expected: Warning dialog should reappear Last Reported: ❌ FAIL - Closes the underlying kanban board instead Root Cause (From Console Logs) The warning Dialog component manages keyboard scopes independently, causing scope conflicts with the parent TaskDialog. When the warning closes, it enables KANBAN scope even though TaskDialog is still open, causing subsequent ESC presses to close the kanban board instead. </bug> I need your help to identify the exact cause of this bug and implement an effective solution. To do this, carefully follow the workflow below, in this specific order: --- ## Workflow ### **Step 1: Clarification (if needed)** - If any part of this prompt is unclear or confusing, ask clarifying questions before proceeding. - Do not ask questions unnecessarily… only ask if essential information is missing. --- ### **Step 2: Initial Analysis** - Quickly review the relevant code to understand the bug's surface area. - Identify key execution paths and data flows related to the bug. - **Assess reproduction feasibility:** Can the bug be reliably reproduced in the running application with available tools? - **Don't over-invest here** - gather just enough context to plan your investigation strategy. --- ### **Step 3: Choose Investigation Strategy** Based on your Step 2 assessment, select one of three paths: #### **Path A: Direct Observation (STRONGLY PREFERRED)** **When to use:** - Bug can be reproduced in the running application - Available tools (browser, network requests, console logs, tmux sessions) are sufficient to observe the issue - **This is the default choice - only deviate if you have a compelling reason** **Why this is preferred:** - Tests the actual application behaviour - Captures real-world interactions and state - Provides the most accurate diagnostic information - Fixes are validated in the true environment **Proceed to Step 4** --- #### **Path B: Isolated Prototype (use sparingly)** **When to use (rare cases only):** - Bug involves a complex algorithm or data structure that can be completely isolated from application context - The issue is conceptually pure and self-contained - Full application context adds overwhelming noise that makes diagnosis impossible - Example: "Custom sorting algorithm produces incorrect order for specific edge case" **What to do:** - Create a from-scratch minimal reproduction: - **Backend:** New isolated crate with focused unit tests - **Frontend:** New Vite project with just the problem component/logic - Debug in this controlled environment - Once understood, apply the fix to the main codebase - **Skip to Step 10** **Note:** Human intervention is unlikely to be needed with this approach since you control the entire reproduction environment. --- #### **Path C: Prototyping Playground (use sparingly)** **When to use (rare cases only):** - Bug requires some application context (routes, API, state management) but the full production setup has too many confounding variables - You need to iterate quickly on a specific feature without affecting the main application - Example: "Auth flow fails under specific user state conditions that are difficult to reproduce" **What to do:** - Create a focused testing ground within the application: - **Frontend:** New route (e.g., `/debug-auth-flow`) that isolates the problematic feature - **Backend:** New module/crate with comprehensive unit tests targeting the issue - Instrument and test in this playground - Apply learnings to the main implementation - **Skip to Step 10** **Note:** Human intervention is unlikely to be needed with this approach since you're building a controlled test environment. --- ### **Step 4: Design Instrumentation Strategy** (Path A only) - Determine what information would definitively diagnose the root cause. - Identify strategic logging points: - Entry/exit points of suspect functions - State changes in relevant data structures - Conditional branches that could explain the behaviour - Network requests/responses (observable via `browser_network_requests` tool) - Browser console messages (observable via `browser_console_messages` tool) - Backend logs (observable via tmux session) - Plan both backend (console/file logs) and frontend (browser console) instrumentation as needed. - **Focus on quality over quantity** - add logging where it will provide maximum diagnostic value. --- ### **Step 5: Implement Logging** (Path A only) - Add comprehensive, structured logging at identified points. - Include relevant context: variable values, timestamps, call stacks, user actions, etc. - Make logs easily grep-able/filterable with clear prefixes (e.g., `[BUG_DEBUG]`). - Ensure log messages are descriptive enough to understand what's happening without reading code. --- ### **Step 6: Run & Observe** (Path A only) - Start the application in a new tmux session (for backend logs). - Use `browser_console_messages` to monitor frontend logs. - Use `browser_network_requests` to observe API/network activity. - Attempt to reproduce the bug with instrumentation active. - Collect and analyse log output from all sources. **Human Intervention Point:** If reproduction fails or observations are inconclusive: - Explicitly request human assistance. - Explain what was attempted and what information is still needed. - Suggest specific ways the human could help (e.g., "Could you reproduce the bug and share the exact steps?" or "Can you verify if X behaviour occurs when you do Y?"). - Provide clear context so the human can help efficiently. --- ### **Step 7: Diagnose from Evidence** (Path A only) - Review actual runtime behaviour from logs, network requests, and console messages. - Identify the precise failure point and root cause. - **Base your diagnosis on observed facts, not hypotheses.** - If the evidence points to multiple possible causes, gather more targeted data before proceeding. --- ### **Step 8: Implement Fix** (Path A only) - Fix directly in the current worktree based on evidence from Step 7. - Keep diagnostic logging in place initially (you'll verify the fix in Step 9). - Ensure the fix addresses the root cause, not just the symptoms. --- ### **Step 9: Verify Fix** (Path A only) - Run the application again with logging still active. - Reproduce the original bug scenario. - Confirm the bug is resolved through observed behaviour. - Use `browser_network_requests` and `browser_console_messages` to verify expected behaviour. - Compare "before" and "after" logs if helpful. **Human Intervention Point:** If verification is unclear or requires domain knowledge: - Explicitly request human verification. - Provide clear, step-by-step instructions for what to test. - Explain what success looks like (expected vs actual behaviour). - Share relevant log excerpts or observations that informed your fix. --- ### **Step 10: Report to User** **For Path A (Direct Observation):** Provide a clear summary including: - **Root cause:** Explain what was actually happening based on observed evidence - **Diagnostic process:** Briefly describe how logging/observation revealed the issue - **Implemented fix:** Describe the changes made and why they address the root cause - **Verification results:** Confirm the fix works (or request human verification if needed) **For Path B/C (Prototype/Playground):** Provide a clear summary including: - **Why this approach was chosen:** Explain why direct observation wasn't suitable - **What was learned:** Describe insights gained from the isolated environment - **How the fix was applied:** Explain how learnings translated to the main codebase - **Relevant artefacts:** Share any reproduction code, tests, or documentation created --- ### **Step 11: Automation Improvement Plan** (optional) **Only include this section if:** - The diagnosis was more difficult or time-consuming than it should have been, OR - You encountered obstacles that could be prevented with codebase improvements, OR - You required human intervention during the process **What to include:** - Analyse what made this bug difficult to diagnose automatically - Propose specific, actionable codebase changes that would improve future automation: - **Accessibility improvements:** ARIA labels, test IDs, semantic HTML (dual benefit: improved accessibility for users + easier automation) - **Logging enhancements:** Structured logging, better error messages, trace IDs, contextual information - **Testability improvements:** Dependency injection, pure functions, better component boundaries - **Observability additions:** Health checks, metrics endpoints, debug modes, feature flags - Categorise suggestions by impact and implementation effort - **Important:** Suggestions should be practical and should not sacrifice application quality, performance, or maintainability --- ### **Step 12: Clean Up** (optional, Path A only) - Remove or reduce instrumentation to production-appropriate levels. - Keep any logging that would be valuable for future debugging. - For Path C: Remove any debug routes/playgrounds unless they have ongoing value. - Commit your changes with a clear, descriptive commit message. --- ## Key Principles 1. **Observation over speculation:** Always prefer gathering evidence from the running application over generating hypotheses. 2. **Path A is strongly preferred:** Only deviate to Path B or C if you have a compelling, articulated reason why direct observation won't work. 3. **Request human help when needed:** If you're stuck, be explicit about it. Humans can provide reproduction steps, domain knowledge, or verification that may be difficult to automate. 4. **Evidence-based fixes:** Every fix should be grounded in observed behaviour, not guesswork. 5. **Practical improvements:** If suggesting automation improvements, focus on changes that provide clear value without compromising the application. * formatter * tanstack form docs * create plan * doc * migrate TaskFormDialog to tanstack form * remove docs * run formatter * Fix: prevent discard warning when no user changes made Use dontUpdateMeta option when programmatically setting branch value to avoid marking form as dirty on initialization Amp-Thread-ID: https://ampcode.com/threads/T-dea5ff8e-d78b-474e-8797-8fc287a27152 Co-authored-by: Amp <amp@ampcode.com> * Search should be positioned relative to caret, not textarea (vibe-kanban 751134be) frontend/src/components/ui/file-search-textarea.tsx * use existing dialog (vibe-kanban 69528431) frontend/src/components/dialogs/tasks/TaskFormDialog.tsx TaskDialog.tsx We have created a new dialog component. Can we reuse the existing one? Will this cause any regressions? * Use TanStack Form validators for TaskFormDialog validation - Add field-level validators (onMount + onChange) for title, executorProfileId, and branch - Remove inline validation logic from Subscribe block - Extract shared validator functions to avoid duplication - Button disabled state now uses form.state.canSubmit directly - Validators run on mount to ensure correct initial state Amp-Thread-ID: https://ampcode.com/threads/T-d0b0fb0f-cdb9-4647-a5e3-415421c5edd5 Co-authored-by: Amp <amp@ampcode.com> * Fix dialog close button not clickable due to z-index issue Add z-10 class to the close button to ensure it appears above dialog content and remains clickable. The button was being blocked by overlapping content elements within the dialog. Amp-Thread-ID: https://ampcode.com/threads/T-729fe4d3-24c9-48cb-9e3c-46ddfed1d660 Co-authored-by: Amp <amp@ampcode.com> * formatter * update pnpm lock * revert changes to dialog.tsx * bring back z-10 (if p-0 is set then this is necessary) * Revert "Use TanStack Form validators for TaskFormDialog validation" This reverts commit 6d946dd88a6ae0c341943d1adcc25261743bfad5. * update title validator * reactive form state * update effect * localise `dropImagesHere` text use form level validation over field level validation make autoStart a form field s.t. it triggers form level validation on change use react-dropzone to implement the image upload button remove unnecessary usage of useCallback simplify handleSubmit function (no useCallback, assume valid values after form validation, unify task variable) remove showImageUpload state create editMode variable use canSubmit to control primary action button disabled state extract warning dialog to its own component * update loading handling * update hook import * update pnpm lock * tsc --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: Louis Knight-Webb <louis@bloop.ai>
2025-11-17 15:21:36 +00:00
{/* Drop zone - only show when not read-only and not hidden */}
{!readOnly && !hideDropZone && (
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
<div
className={cn(
'border-2 border-dashed rounded-lg p-6 text-center transition-colors',
isDragging
? 'border-primary bg-primary/5'
: 'border-muted-foreground/25 hover:border-muted-foreground/50',
disabled && 'opacity-50 cursor-not-allowed'
)}
onDrop={handleDrop}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
>
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
<Upload className="h-8 w-8 mx-auto mb-3 text-muted-foreground" />
<p className="text-sm text-muted-foreground mb-1">
Drag and drop images here, or click to select
</p>
<Button
variant="secondary"
size="sm"
onClick={() => fileInputRef.current?.click()}
disabled={disabled || isUploading}
>
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
Select Images
</Button>
<input
ref={fileInputRef}
type="file"
accept="image/*"
multiple
className="hidden"
onChange={(e) => {
void handleFiles(e.target.files);
}}
disabled={disabled}
/>
</div>
)}
{/* Image previews */}
{images.length > 0 && (
<div className="grid grid-cols-2 gap-2">
{images.map((image) => (
<div
key={image.id}
className="relative group border rounded-lg p-2 bg-background"
>
<div className="flex items-center gap-2">
<img
src={imagesApi.getImageUrl(image.id)}
alt={image.original_name}
className="h-16 w-16 object-cover rounded"
/>
<div className="flex-1 min-w-0">
<p className="text-xs font-medium truncate">
{image.original_name}
</p>
<p className="text-xs text-muted-foreground">
{formatFileSize(image.size_bytes)}
</p>
</div>
</div>
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
{!disabled && !readOnly && (
<Button
variant="ghost"
size="icon"
className="absolute top-1 right-1 h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity"
onClick={() => handleRemoveImage(image.id)}
>
<X className="h-3 w-3" />
</Button>
)}
</div>
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
))}
</div>
)}
{/* Uploading indicators */}
{uploadingFiles.size > 0 && (
<div className="space-y-1">
{Array.from(uploadingFiles).map((tempId) => (
<div
key={tempId}
className="flex items-center gap-2 text-xs text-muted-foreground"
>
<div className="h-3 w-3 border-2 border-primary border-t-transparent rounded-full animate-spin" />
<span>Uploading...</span>
</div>
))}
</div>
)}
</div>
);
if (!collapsible) {
return content;
}
return (
<div className="space-y-2">
<button
type="button"
onClick={() => setIsExpanded(!isExpanded)}
className="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
>
<ChevronRight
className={cn(
'h-3 w-3 transition-transform',
isExpanded && 'rotate-90'
)}
/>
<ImageIcon className="h-4 w-4" />
<span>Images {images.length > 0 && `(${images.length})`}</span>
</button>
{isExpanded && content}
</div>
);
}
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
);
Allow image pasting into task field (#883) * **Changes** - Made `ImageUploadSection` ref-aware with an `addFiles` imperative handle and auto-expansion when images appear, enabling non-UI triggers to reuse its validation/upload flow (frontend/src/components/ui/ImageUploadSection.tsx:36-348). - Captured clipboard image blobs in the shared textarea component and exposed them via a new `onPasteFiles` hook for upstream consumers (frontend/src/components/ui/file-search-textarea.tsx:111-137). - Task creation dialog now routes pasted images straight into the uploader through the new ref, keeping the description markdown in sync (frontend/src/components/dialogs/tasks/TaskFormDialog.tsx:102-357). - Follow-up editor keeps the image panel mounted but hidden, reveals it on paste, and forwards the new prop through its wrapper so task attempts accept clipboard images (frontend/src/components/tasks/TaskFollowUpSection.tsx:89-325; frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx:13-47). **Tests** - `npm run check` (frontend) - `pnpm run check` (timed out after backend cargo check kicked off; see log) **Next Steps** 1. Re-run `pnpm run check` or `npm run backend:check` when you can let Cargo finish to confirm backend continues to build. 2. Manually paste a few image formats/sizes into the task form and follow-up editor to confirm UX and markdown output look right. * Update frontend/src/components/ui/ImageUploadSection.tsx Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> * fmt --------- Co-authored-by: Greg Burch <gburch@styleseat.com> Co-authored-by: Gabriel Gordon-Hall <gabriel@bloop.ai> Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2025-10-01 12:17:51 -04:00
ImageUploadSection.displayName = 'ImageUploadSection';