From 518230f8a08f75ff8ed6887f736d12ba6f3665d2 Mon Sep 17 00:00:00 2001 From: Louis Knight-Webb Date: Thu, 16 Oct 2025 18:28:56 +0100 Subject: [PATCH] WIP FE revision (#975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * scaffold new sidebar * wysiwyg * Task context and hook (vibe-kanban 29f71b17) Can you please create a context for getting info about the current Task, and also tanstack query mutation for get, update, delete. @frontend/src/hooks/ @frontend/src/contexts/ Ultimately this will be implemented in frontend/src/components/panels/TaskPanel - but that's a future change * attempts section * Add table of task attempts (vibe-kanban a069161c) frontend/src/components/panels/TaskPanel.tsx * Proper routing between task and task attempt panel (vibe-kanban 0cf73011) When the user clicks on a task attempt in the task panel, it should switch to the task attempt panel frontend/src/components/panels/TaskPanel.tsx frontend/src/components/panels/TaskAttemptPanel.tsx * Fill out TaskAttemptPanel (vibe-kanban 219a1bde) frontend/src/components/panels/TaskAttemptPanel.tsx This should have conversation history logs and the follow up box below * Navigation changes (vibe-kanban 35767666) frontend/src/components/panels/KanbanSidebar.tsx - Upon opening a task, if there are task attempts, the latest task attempt should be shown by default - We should add a close button and a fullscreen button to the right of the breadcrumbs - The close actions should close the task/attempt - The fullscreen button should have no action for now * table styles * Create a task attempt (vibe-kanban 5c84e9cd) It should be possible to create a task attempt from frontend/src/components/panels/TaskPanel.tsx * Refactor the fullscreen approach (vibe-kanban e9d988af) frontend/src/lib/responsive-config.ts frontend/src/pages/project-tasks.tsx I'd like to take a different approach to handling the responsive content. - In kanban mode, the kanbansidebar should be shown next to tasks - In full screen mode the kanban sidebar should be shown next to a new component (leave blank for now, but rest of space), with sidebar on the right - Transitioning between the two shouldn't cause a re-render of the sidebar, as we want to preserve scroll position of the sidebar * Navigating from task attempt to task (vibe-kanban 0072d295) Navigating to task attempt from task in the sidebar forces the full screen mode to exit. frontend/src/hooks/useTaskViewManager.ts should navigate while maintaining the current status of fullscreen/non-full screen, unless it is specifically specified in options * Introduce fullscreen tabs (vibe-kanban 9fb1a248) /projects/:projectId/tasks/:taskId/attempts/:attemptId/full/preview - this should have logs next to preview /projects/:projectId/tasks/:taskId/attempts/:attemptId/full/diffs - this should have logs next to diffs We should refactor the code so that these tabs are displayed next to the logs using ResponsiveTwoPane. There should be tabs to navigate between these different views, next to the close and fullscreen toggles. Don't fill out any content for preview or diffs yet, just scaffold the page structure and we'll fill out the content after. * Remove the fullscreen mode for tasks and task attempts (vibe-kanban 8acb7c95) Remove any /full pages and associated components frontend/src/App.tsx * Update layout of project tasks (vibe-kanban e0c841fb) frontend/src/pages/project-tasks.tsx We are completely refactoring this page, there will be 5 layouts: - Just kanban - Kanban on left (2/3) and attempt on the right (1/3) - Kanban on left (1/3) and attempt on right (2/3) - Task/attempt on left (1/3) and preview on right (1/3) - Task/attempt on left (1/3) and logs on right (1/3) The layout will be determined: - If no attempt selected, show just kanban - If attempt selected, a toggle will be shown with three options: widen, preview or logs When transitioning between these different states, the UI should animate. Do not worry about the content of the preview or logs tabs for now, leave as a placeholder for now and we'll fill them in later. The task panel will be removed. * Fill out diffs panel (vibe-kanban 020da7b1) frontend/src/components/panels/DiffsPanel.tsx should be populated based on frontend/src/components/tasks/TaskDetails/DiffTab.tsx * Fill out preview panel (vibe-kanban bd87888f) frontend/src/components/panels/PreviewPanel.tsx should be populated, based on frontend/src/components/tasks/TaskDetails/PreviewTab.tsx * Tweak sized (vibe-kanban 7b656420) frontend/src/pages/project-tasks.tsx - In diff or preview mode, the diff/preview should take 2/3 of the width and attempt 1/3 - The attempt conversation should have a max width, after which the conversation and follow up gets centred with a buffer either side * When navigating between task attempts, toggle state should be maintained (vibe-kanban ce85ec02) frontend/src/pages/project-tasks.tsx expand, preview, diffs mode should be maintained * Replace the expand mode with resizeable (vibe-kanban b82de0a3) Instead of having a fixed 'expand' mode, we should make it so the user can resize the width of the attempt logs panel. They should also be able to resize the width between the attempt logs panel and the preview/diffs view. * Add stop dev server button (vibe-kanban 9a45fa65) frontend/src/components/tasks/TaskDetails/preview/PreviewToolbar.tsx Improvements: - Add stop dev server button - Align styles of this header with frontend/src/components/panels/AttemptHeaderActions.tsx and frontend/src/components/panels/DiffsPanel.tsx header (eg icon button styles) * Add GitOperations to DiffsPanel (vibe-kanban 9432b071) At the top of DiffsPanel we should place the GitOperations for the selected task attempt * Tweak user message style (vibe-kanban 3bee10fe) frontend/src/components/NormalizedConversation/UserMessage.tsx - No border - Edit icon should only be shown when user hovers anywhere over this component * Add todos in between logs and follow ups (vibe-kanban b7969dd8) Add the attempt todos to a new collapsible area between the follow up area and the message logs frontend/src/components/panels/TaskAttemptPanel.tsx frontend/src/components/tasks/TodoPanel.tsx * Animate when opening panels (vibe-kanban 83767ab6) frontend/src/pages/project-tasks.tsx When - Attempt panel opens - Preview/diff panel opens We should have a smooth opening of the panel * Add a dropdown menu to task attempt (vibe-kanban 4552f274) frontend/src/pages/project-tasks.tsx To the left of the 'X' button, we should have a dropdown menu with the options: - Open attempt in IDE - View processes - Create new attempt - Create subtask The actual content of where these link to will be filled out in a future change, just implement the menu for now. * Wire up dropdown to Create new attempt (vibe-kanban 64e416ea) When user clicks this option in the dropdown frontend/src/pages/project-tasks.tsx * Wire up dropdown to Create subtask (vibe-kanban f391ba78) When user clicks this option in the dropdown frontend/src/pages/project-tasks.tsx * Wire up dropdown to Open attempt in IDE (vibe-kanban b0f720c4) When user clicks this in the dropdown frontend/src/pages/project-tasks.tsx * Wire up dropdown to View Processes (vibe-kanban 08b15309) When user clicks 'View processes' option in the dropdown they be taken to a new dialog where they can navigate through each of the execution processes in the current task attempt, and see logs for whatever process is selected. frontend/src/pages/project-tasks.tsx * fix lint * Simplify TasksLayout (vibe-kanban 5ba0ab47) frontend/src/components/layout/TasksLayout.tsx I feel like kaAttemptRef, aaAttemptRef and slotEl are indicative of overengineering. Could we refactor this component to be simpler and easier to maintain. * Dividers should be hidden (vibe-kanban d3941761) frontend/src/pages/project-tasks.tsx When attempt+preview/diff is shown two dividers are shown on the screen one to the left of attempt panel and one in between attempt panel and preview/diff. When kanban+attempt is shown two dividers are shown on the screen, one to the right of attempt and one in between kanban and attempt. In both cases, only one divider should be shown, the non-redundant one. * Console spam (vibe-kanban 02903bc4) When I open a task attempt, I get this 5x in the chat: useJsonPatchWsStream.ts:177 WebSocket connection to 'ws://localhost:3002/api/execution-processes/stream/ws?task_attempt_id=9daf34c3-a0f5-43e1-8bf7-354b4d7c041b' failed: WebSocket is closed before the connection is established. frontend/src/pages/project-tasks.tsx * Fix click to edit (vibe-kanban fe6c8196) frontend/src/components/panels/PreviewPanel.tsx frontend/src/pages/project-tasks.tsx When I use the click to edit functionality, the follow up box doesn't get change state to show an item has been selected. * Improve GitOperations styles in smaller views (vibe-kanban d5595a90) frontend/src/components/tasks/Toolbar/GitOperations.tsx On smaller views the merge, rebase, create pr buttons can end up pushed to the line below * Solve this issue (vibe-kanban ddc897fb) @sentry_react.js?v=084cd90b:10599 Uncaught Error: useExecutionProcessesContext must be used within ExecutionProcessesProvider at useExecutionProcessesContext (ExecutionProcessesContext.tsx:93:11) at useAttemptExecution (useAttemptExecution.ts:16:7) at DiffsPanelContainer (project-tasks.tsx:85:32) * Update keyboard shortcuts (vibe-kanban b3593e29) frontend/src/pages/project-tasks.tsx CMD+enter should cycle through: attempt, preview, diff No other keyboard shortcuts should trigger these states * Debug issue (vibe-kanban 2336c359) Uncaught Error: useExecutionProcessesContext must be used within ExecutionProcessesProvider at useExecutionProcessesContext (ExecutionProcessesContext.tsx:93:11) at useDevserverPreview (useDevserverPreview.ts:29:7) at PreviewPanel (PreviewPanel.tsx:34:24) at renderWithHooks (chunk-ILO4JA4Q.js?v=672d6a56:11548:26) at mountIndeterminateComponent (chunk-ILO4JA4Q.js?v=672d6a56:14926:21) at beginWork (chunk-ILO4JA4Q.js?v=672d6a56:15914:22) at HTMLUnknownElement.callCallback2 (chunk-ILO4JA4Q.js?v=672d6a56:3674:22) at HTMLUnknownElement.sentryWrapped (@sentry_react.js?v=672d6a56:10582:17) at Object.invokeGuardedCallbackDev (chunk-ILO4JA4Q.js?v=672d6a56:3699:24) at invokeGuardedCallback (chunk-ILO4JA4Q.js?v=672d6a56:3733:39) at beginWork$1 (chunk-ILO4JA4Q.js?v=672d6a56:19765:15) at performUnitOfWork (chunk-ILO4JA4Q.js?v=672d6a56:19198:20) at workLoopSync (chunk-ILO4JA4Q.js?v=672d6a56:19137:13) at renderRootSync (chunk-ILO4JA4Q.js?v=672d6a56:19116:15) at recoverFromConcurrentError (chunk-ILO4JA4Q.js?v=672d6a56:18736:28) at performSyncWorkOnRoot (chunk-ILO4JA4Q.js?v=672d6a56:18879:28) at flushSyncCallbacks (chunk-ILO4JA4Q.js?v=672d6a56:9119:30) at chunk-ILO4JA4Q.js?v=672d6a56:18627:21 * Activate TaskPanel (vibe-kanban 7724d879) frontend/src/components/panels/TaskPanel.tsx TaskPanel component is not currently used anywhere. Instead, let's display it: - If there are no task attempts - If the user clicks on the task in the breadcrumbs frontend/src/pages/project-tasks.tsx * Remove the icons (vibe-kanban d9f49a9b) frontend/src/components/ui/ActionsDropdown.tsx * Move the attempt header higher (vibe-kanban 91d9c48c) When the attempt is shown with the diff/preview, the attempt header should take the width of both panels. Currently it just takes the width of the attempt * Fix animation (vibe-kanban 77a4f176) When the task attempt closes, the entire kanban moves from right to left which is weird. Can we change the animations to fade * Update headers (vibe-kanban 6995d76f) When preview/diff is shown we should not show the frontend/src/components/layout/navbar.tsx as there can be three levels of navigation which looks terrible. frontend/src/pages/project-tasks.tsx * Perfect! I've fixed the settings scroll issue. **File**: `frontend/src/components/layout/NormalLayout.tsx:10` Changed `overflow-hidden` to `overflow-y-auto` on the main content container. ```tsx // Before
// After
``` The general settings page can now scroll vertically, making all settings accessible including those at the bottom. The fix is minimal and surgical - it only affects the overflow behavior while maintaining the existing layout structure. Other pages (Projects, Tasks) will continue to work as expected since they have their own internal scroll containers. Perfect! I've fixed the settings scroll issue by following the established codebase pattern. Restored `overflow-hidden` to maintain the consistent pattern used throughout the app. Added the scroll container wrapper that Projects and other pages use: **Before:** ```tsx
{/* content */}
``` **After:** ```tsx
{/* content */}
``` Removed the `lg:sticky lg:top-8 lg:h-fit lg:max-h-[calc(100vh-4rem)] lg:overflow-y-auto` classes from the sidebar since they're no longer needed with the new scroll container pattern. ✅ **Follows the established pattern** - Same approach as Projects page ✅ **No global changes** - Only affects Settings pages ✅ **Maintains consistency** - NormalLayout keeps its `overflow-hidden` behavior ✅ **Simpler sidebar** - Removed complex sticky positioning logic ✅ **All settings accessible** - Page scrolls properly now The Settings page now works exactly like the Projects page: it creates its own scroll container with `h-full overflow-auto` inside the `overflow-hidden` parent. Perfect! I've restored the sticky sidebar functionality. **Line 40 of SettingsLayout.tsx:** ```tsx - {/* Main Content */} -
- -
+ {/* Main Content */} +
+ +
+
); diff --git a/frontend/src/styles/index.css b/frontend/src/styles/index.css index e1012882..2d7f52f9 100644 --- a/frontend/src/styles/index.css +++ b/frontend/src/styles/index.css @@ -264,3 +264,29 @@ @apply underline; } } + +/* BASIC STYLES (mainly for rendering markdown) */ + +@layer base { + .wysiwyg { + h1 { + @apply text-lg leading-tight font-medium; + } + + h2 { + @apply leading-tight font-medium; + } + + ul { + @apply list-disc list-outside space-y-1 ps-6; + } + + ol { + @apply list-decimal list-outside space-y-1 ps-6; + } + + li { + @apply leading-tight; + } + } +} diff --git a/package.json b/package.json index 578791a9..d262086d 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,11 @@ "pnpm": ">=8" }, "dependencies": { - "lodash": "^4.17.21", "@dnd-kit/utilities": "^3.2.2", - "@ebay/nice-modal-react": "^1.2.13" + "@ebay/nice-modal-react": "^1.2.13", + "@radix-ui/react-toggle-group": "^1.1.11", + "framer-motion": "^12.23.22", + "lodash": "^4.17.21", + "react-resizable-panels": "^3.0.6" } } diff --git a/scripts/check-i18n.sh b/scripts/check-i18n.sh index 993fc152..f62a8cf8 100755 --- a/scripts/check-i18n.sh +++ b/scripts/check-i18n.sh @@ -44,6 +44,51 @@ get_json_keys() { ' "$file" 2>/dev/null | LC_ALL=C sort -u } +check_duplicate_keys() { + local file=$1 + if [ ! -f "$file" ]; then + return 2 + fi + + # Strategy: Use jq's --stream flag to detect duplicate keys + # jq --stream processes JSON before parsing (preserves duplicates) + # jq tostream processes JSON after parsing (duplicates already collapsed) + # If the outputs differ, duplicate keys exist + if ! diff -q <(jq --stream . "$file" 2>/dev/null) <(jq tostream "$file" 2>/dev/null) > /dev/null 2>&1; then + # Duplicates found + echo "duplicate keys detected" + return 1 + fi + return 0 +} + +check_duplicate_json_keys() { + local locales_dir="$REPO_ROOT/frontend/src/i18n/locales" + local exit_code=0 + + if [ ! -d "$locales_dir" ]; then + echo "❌ Locales directory not found: $locales_dir" + return 1 + fi + + # Check all JSON files in all locale directories + while IFS= read -r file; do + local rel_path="${file#$locales_dir/}" + local duplicates + + if duplicates=$(check_duplicate_keys "$file"); then + : # No duplicates found + else + echo "❌ [$rel_path] Duplicate keys found:" + printf ' - %s\n' $duplicates + echo " JSON silently overwrites duplicate keys - only the last occurrence is used!" + exit_code=1 + fi + done < <(find "$locales_dir" -type f -name "*.json" 2>/dev/null) + + return "$exit_code" +} + check_key_consistency() { local locales_dir="$REPO_ROOT/frontend/src/i18n/locales" local exit_code=0 @@ -175,6 +220,14 @@ else echo "✅ No new literal strings introduced." fi +echo "" +echo "▶️ Checking for duplicate JSON keys..." +if ! check_duplicate_json_keys; then + EXIT_STATUS=1 +else + echo "✅ No duplicate keys found in JSON files." +fi + echo "" echo "▶️ Checking translation key consistency..." if ! check_key_consistency; then