mirror of
https://github.com/lfnovo/open-notebook.git
synced 2026-05-02 21:30:38 +00:00
Feature/oss 312 notebook item counts (#175)
* fix: small issue where users cant change podcast segments * feat: display source and note counts on notebook cards (OSS-312) Add item counters to notebook listing page showing the number of sources and notes in each notebook. Counts are displayed in a footer section with FileText and StickyNote icons for visual consistency with ContextIndicator. Backend changes: - Add source_count and note_count to NotebookResponse model - Update /notebooks endpoint to use SurrealDB graph traversal query - Query: count(<-reference.in) for sources, count(<-artifact.in) for notes - Update all notebook endpoints to include counts Frontend changes: - Add source_count and note_count to TypeScript NotebookResponse interface - Add footer section to NotebookCard component - Display counts with FileText and StickyNote icons (h-3 w-3) - Use border-top separator and muted-foreground styling Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * style: use colorful badges for notebook counts matching ContextIndicator Update notebook card counts to use Badge components with primary color styling instead of plain text, matching the visual style of the ContextIndicator component in the chat window. Changes: - Replace plain text divs with Badge components - Apply text-primary and border-primary/50 styling - Use same spacing (gap-1.5, px-1.5, py-0.5) as ContextIndicator - Remove bullet separator (not needed with badge layout) Visual result matches the colorful badges shown in chat context. Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
1a67f1f912
commit
df0986cee0
5 changed files with 85 additions and 20 deletions
|
|
@ -24,6 +24,8 @@ class NotebookResponse(BaseModel):
|
|||
archived: bool
|
||||
created: str
|
||||
updated: str
|
||||
source_count: int
|
||||
note_count: int
|
||||
|
||||
|
||||
# Search models
|
||||
|
|
|
|||
|
|
@ -18,22 +18,33 @@ async def get_notebooks(
|
|||
):
|
||||
"""Get all notebooks with optional filtering and ordering."""
|
||||
try:
|
||||
notebooks = await Notebook.get_all(order_by=order_by)
|
||||
# Build the query with counts
|
||||
query = f"""
|
||||
SELECT *,
|
||||
count(<-reference.in) as source_count,
|
||||
count(<-artifact.in) as note_count
|
||||
FROM notebook
|
||||
ORDER BY {order_by}
|
||||
"""
|
||||
|
||||
result = await repo_query(query)
|
||||
|
||||
# Filter by archived status if specified
|
||||
if archived is not None:
|
||||
notebooks = [nb for nb in notebooks if nb.archived == archived]
|
||||
result = [nb for nb in result if nb.get("archived") == archived]
|
||||
|
||||
return [
|
||||
NotebookResponse(
|
||||
id=nb.id or "",
|
||||
name=nb.name,
|
||||
description=nb.description,
|
||||
archived=nb.archived or False,
|
||||
created=str(nb.created),
|
||||
updated=str(nb.updated),
|
||||
id=str(nb.get("id", "")),
|
||||
name=nb.get("name", ""),
|
||||
description=nb.get("description", ""),
|
||||
archived=nb.get("archived", False),
|
||||
created=str(nb.get("created", "")),
|
||||
updated=str(nb.get("updated", "")),
|
||||
source_count=nb.get("source_count", 0),
|
||||
note_count=nb.get("note_count", 0),
|
||||
)
|
||||
for nb in notebooks
|
||||
for nb in result
|
||||
]
|
||||
except Exception as e:
|
||||
logger.error(f"Error fetching notebooks: {str(e)}")
|
||||
|
|
@ -59,6 +70,8 @@ async def create_notebook(notebook: NotebookCreate):
|
|||
archived=new_notebook.archived or False,
|
||||
created=str(new_notebook.created),
|
||||
updated=str(new_notebook.updated),
|
||||
source_count=0, # New notebook has no sources
|
||||
note_count=0, # New notebook has no notes
|
||||
)
|
||||
except InvalidInputError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
|
@ -73,17 +86,28 @@ async def create_notebook(notebook: NotebookCreate):
|
|||
async def get_notebook(notebook_id: str):
|
||||
"""Get a specific notebook by ID."""
|
||||
try:
|
||||
notebook = await Notebook.get(notebook_id)
|
||||
if not notebook:
|
||||
# Query with counts for single notebook
|
||||
query = """
|
||||
SELECT *,
|
||||
count(<-reference.in) as source_count,
|
||||
count(<-artifact.in) as note_count
|
||||
FROM $notebook_id
|
||||
"""
|
||||
result = await repo_query(query, {"notebook_id": ensure_record_id(notebook_id)})
|
||||
|
||||
if not result:
|
||||
raise HTTPException(status_code=404, detail="Notebook not found")
|
||||
|
||||
nb = result[0]
|
||||
return NotebookResponse(
|
||||
id=notebook.id or "",
|
||||
name=notebook.name,
|
||||
description=notebook.description,
|
||||
archived=notebook.archived or False,
|
||||
created=str(notebook.created),
|
||||
updated=str(notebook.updated),
|
||||
id=str(nb.get("id", "")),
|
||||
name=nb.get("name", ""),
|
||||
description=nb.get("description", ""),
|
||||
archived=nb.get("archived", False),
|
||||
created=str(nb.get("created", "")),
|
||||
updated=str(nb.get("updated", "")),
|
||||
source_count=nb.get("source_count", 0),
|
||||
note_count=nb.get("note_count", 0),
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
|
|
@ -112,6 +136,29 @@ async def update_notebook(notebook_id: str, notebook_update: NotebookUpdate):
|
|||
|
||||
await notebook.save()
|
||||
|
||||
# Query with counts after update
|
||||
query = """
|
||||
SELECT *,
|
||||
count(<-reference.in) as source_count,
|
||||
count(<-artifact.in) as note_count
|
||||
FROM $notebook_id
|
||||
"""
|
||||
result = await repo_query(query, {"notebook_id": ensure_record_id(notebook_id)})
|
||||
|
||||
if result:
|
||||
nb = result[0]
|
||||
return NotebookResponse(
|
||||
id=str(nb.get("id", "")),
|
||||
name=nb.get("name", ""),
|
||||
description=nb.get("description", ""),
|
||||
archived=nb.get("archived", False),
|
||||
created=str(nb.get("created", "")),
|
||||
updated=str(nb.get("updated", "")),
|
||||
source_count=nb.get("source_count", 0),
|
||||
note_count=nb.get("note_count", 0),
|
||||
)
|
||||
|
||||
# Fallback if query fails
|
||||
return NotebookResponse(
|
||||
id=notebook.id or "",
|
||||
name=notebook.name,
|
||||
|
|
@ -119,6 +166,8 @@ async def update_notebook(notebook_id: str, notebook_update: NotebookUpdate):
|
|||
archived=notebook.archived or False,
|
||||
created=str(notebook.created),
|
||||
updated=str(notebook.updated),
|
||||
source_count=0,
|
||||
note_count=0,
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue