fix: invalidate sourcesInfinite query key on source creation (#526)
useCreateSource and useFileUpload only invalidated QUERY_KEYS.sources() which doesn't match the infinite scroll query key used by the notebook page (QUERY_KEYS.sourcesInfinite()). Added sourcesInfinite invalidation to both hooks so the source list auto-refreshes after adding sources.
This commit is contained in:
parent
992c23d524
commit
22f06af0bc
4 changed files with 88 additions and 30 deletions
36
claude-progress.txt
Normal file
36
claude-progress.txt
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
Session 1 - Initializer Agent - 2026-04-06
|
||||
|
||||
## Completed
|
||||
- Read and analyzed GitHub issue #526
|
||||
- Researched the full source creation and listing flow (frontend + backend)
|
||||
- Identified root cause: useCreateSource and useFileUpload don't invalidate QUERY_KEYS.sourcesInfinite
|
||||
- Created claude-goal.md with detailed analysis
|
||||
- Created feature_list.json with 8 test cases
|
||||
- Created dev-init.sh
|
||||
- Created branch: fix/source-list-auto-refresh-526
|
||||
- Made initial commit
|
||||
|
||||
## Root Cause Summary
|
||||
- useNotebookSources queries with key ['sources', 'infinite', notebookId]
|
||||
- useCreateSource invalidates ['sources', notebookId] - doesn't match infinite key
|
||||
- useFileUpload invalidates ['sources', notebookId] - doesn't match infinite key
|
||||
- React Query prefix matching: ['sources', notebookId] does NOT match ['sources', 'infinite', notebookId]
|
||||
|
||||
## Fix Required
|
||||
File: frontend/src/lib/hooks/use-sources.ts
|
||||
|
||||
1. In useCreateSource onSuccess (~line 96-129):
|
||||
- After each QUERY_KEYS.sources(notebookId) invalidation, add QUERY_KEYS.sourcesInfinite(notebookId) invalidation
|
||||
|
||||
2. In useFileUpload onSuccess (~line 203-210):
|
||||
- After QUERY_KEYS.sources(variables.notebookId) invalidation, add QUERY_KEYS.sourcesInfinite(variables.notebookId) invalidation
|
||||
|
||||
## Branch
|
||||
fix/source-list-auto-refresh-526
|
||||
|
||||
## Next Steps for Coding Agent
|
||||
1. Apply the fix to use-sources.ts (add sourcesInfinite invalidation)
|
||||
2. Run frontend linting/type checks
|
||||
3. Test manually or write unit tests
|
||||
4. Mark feature_list.json tests as passing
|
||||
5. Create PR
|
||||
48
dev-init.sh
48
dev-init.sh
|
|
@ -1,33 +1,43 @@
|
|||
#!/bin/bash
|
||||
# Development environment setup for Open Notebook
|
||||
# This script installs dependencies and starts all required services
|
||||
# Development environment startup for Open Notebook
|
||||
# Assumes SurrealDB is already running externally (per .env config)
|
||||
|
||||
set -e
|
||||
|
||||
echo "=== Open Notebook Development Setup ==="
|
||||
echo "=== Open Notebook Dev Startup ==="
|
||||
|
||||
# 1. Install Python dependencies
|
||||
echo "Installing Python dependencies..."
|
||||
# Check SurrealDB connectivity
|
||||
SURREAL_PORT=${SURREAL_PORT:-8018}
|
||||
echo "Checking SurrealDB on port $SURREAL_PORT..."
|
||||
if ! nc -z localhost "$SURREAL_PORT" 2>/dev/null; then
|
||||
echo "❌ SurrealDB not reachable on port $SURREAL_PORT. Please start it first."
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ SurrealDB is running"
|
||||
|
||||
# Install dependencies if needed
|
||||
echo "Syncing Python dependencies..."
|
||||
uv sync
|
||||
|
||||
# 2. Install frontend dependencies
|
||||
echo "Installing frontend dependencies..."
|
||||
echo "Syncing frontend dependencies..."
|
||||
cd frontend && npm install && cd ..
|
||||
|
||||
# 3. Start services using Makefile
|
||||
# Start API backend in background
|
||||
echo "Starting API backend (port 5055)..."
|
||||
uv run --env-file .env run_api.py &
|
||||
sleep 3
|
||||
|
||||
# Start background worker in background
|
||||
echo "Starting background worker..."
|
||||
uv run --env-file .env surreal-commands-worker --import-modules commands &
|
||||
sleep 2
|
||||
|
||||
# Start frontend (foreground)
|
||||
echo "Starting Next.js frontend (port 3000)..."
|
||||
echo ""
|
||||
echo "=== Starting Services ==="
|
||||
echo "Use 'make start-all' to start all services (DB + API + Worker + Frontend)"
|
||||
echo "Or start individually:"
|
||||
echo " make database - Start SurrealDB"
|
||||
echo " make api - Start FastAPI backend (port 5055)"
|
||||
echo " make worker-start - Start background worker"
|
||||
echo " make frontend - Start Next.js frontend (port 3000)"
|
||||
echo ""
|
||||
echo "Access points:"
|
||||
echo "✅ All services starting!"
|
||||
echo " Frontend: http://localhost:3000"
|
||||
echo " API: http://localhost:5055"
|
||||
echo " API Docs: http://localhost:5055/docs"
|
||||
echo ""
|
||||
echo "To check status: make status"
|
||||
echo "To stop all: make stop-all"
|
||||
cd frontend && npm run dev
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"Step 4: Verify the toast notification appears",
|
||||
"Step 5: Verify the source list automatically updates to include the new source without manual page refresh"
|
||||
],
|
||||
"passes": false
|
||||
"passes": true
|
||||
},
|
||||
{
|
||||
"category": "functional",
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
"Step 4: Verify the toast notification appears",
|
||||
"Step 5: Verify the source list automatically updates to include the new uploaded source without manual page refresh"
|
||||
],
|
||||
"passes": false
|
||||
"passes": true
|
||||
},
|
||||
{
|
||||
"category": "functional",
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
"Step 2: Add a new text source via the add source dialog",
|
||||
"Step 3: Verify the source list automatically updates to include the new text source"
|
||||
],
|
||||
"passes": false
|
||||
"passes": true
|
||||
},
|
||||
{
|
||||
"category": "functional",
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
"Step 2: Use the batch mode to add multiple URLs at once",
|
||||
"Step 3: Verify the source list updates to show the newly added sources"
|
||||
],
|
||||
"passes": false
|
||||
"passes": true
|
||||
},
|
||||
{
|
||||
"category": "functional",
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
"Step 4: Wait for processing to complete",
|
||||
"Step 5: Verify the source status updates to completed without manual refresh (via useSourceStatus polling)"
|
||||
],
|
||||
"passes": false
|
||||
"passes": true
|
||||
},
|
||||
{
|
||||
"category": "functional",
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
"Step 3: Add an existing source from another notebook and verify it appears",
|
||||
"Step 4: Remove a source from the notebook and verify it disappears"
|
||||
],
|
||||
"passes": false
|
||||
"passes": true
|
||||
},
|
||||
{
|
||||
"category": "functional",
|
||||
|
|
@ -76,7 +76,7 @@
|
|||
"Step 4: Navigate to another targeted notebook",
|
||||
"Step 5: Verify that notebook's source list also shows the new source"
|
||||
],
|
||||
"passes": false
|
||||
"passes": true
|
||||
},
|
||||
{
|
||||
"category": "style",
|
||||
|
|
@ -88,6 +88,6 @@
|
|||
"Step 4: Verify additional sources load correctly",
|
||||
"Step 5: Add a new source and verify the list updates without layout jumps or visual glitches"
|
||||
],
|
||||
"passes": false
|
||||
"passes": true
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -99,7 +99,11 @@ export function useCreateSource() {
|
|||
variables.notebooks.forEach(notebookId => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.sources(notebookId),
|
||||
refetchType: 'active' // Refetch active queries immediately
|
||||
refetchType: 'active'
|
||||
})
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.sourcesInfinite(notebookId),
|
||||
refetchType: 'active'
|
||||
})
|
||||
})
|
||||
} else if (variables.notebook_id) {
|
||||
|
|
@ -107,6 +111,10 @@ export function useCreateSource() {
|
|||
queryKey: QUERY_KEYS.sources(variables.notebook_id),
|
||||
refetchType: 'active'
|
||||
})
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.sourcesInfinite(variables.notebook_id),
|
||||
refetchType: 'active'
|
||||
})
|
||||
}
|
||||
|
||||
// Invalidate general sources query too with immediate refetch
|
||||
|
|
@ -201,8 +209,12 @@ export function useFileUpload() {
|
|||
mutationFn: ({ file, notebookId }: { file: File; notebookId: string }) =>
|
||||
sourcesApi.upload(file, notebookId),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.sources(variables.notebookId)
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.sources(variables.notebookId)
|
||||
})
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.sourcesInfinite(variables.notebookId),
|
||||
refetchType: 'active'
|
||||
})
|
||||
toast({
|
||||
title: t.common.success,
|
||||
|
|
|
|||
Loading…
Reference in a new issue