Skip to content

Commit 75360ba

Browse files
karthik reddyclaude
authored andcommitted
refactor: add pagination to list endpoints and extract calendar components
Backend: - Add proper pagination (offset/limit) to people and connections list endpoints - Update people_service.list_people to return tuple (people, total) - Update connection_service.get_connections to return tuple (connections, total) Mobile: - Extract DateStripScroller to separate component - Extract MeetingTypeConfig and MeetingTypeLogo to separate module - Reduce calendar.tsx from 2796 to 2532 lines (-264 lines) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 53070f8 commit 75360ba

8 files changed

Lines changed: 336 additions & 289 deletions

File tree

backend/app/api/connections.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,20 @@ async def list_connections(
4848
current_user: CurrentUser,
4949
db: Database,
5050
limit: int = Query(20, ge=1, le=50),
51+
offset: int = Query(0, ge=0),
5152
unnotified_only: bool = Query(False),
5253
):
5354
"""
54-
List discovered memory connections.
55+
List discovered memory connections with pagination.
5556
5657
Connections show related memories that were discovered automatically.
5758
Use unnotified_only=true to get only new connections.
5859
"""
5960
connection_service = ConnectionService(db)
60-
connections = await connection_service.get_connections(
61+
connections, total = await connection_service.get_connections(
6162
user_id=current_user.id,
6263
limit=limit,
64+
offset=offset,
6365
unnotified_only=unnotified_only,
6466
)
6567

@@ -100,7 +102,7 @@ async def list_connections(
100102

101103
return ConnectionListResponse(
102104
connections=results,
103-
total=len(results),
105+
total=total,
104106
)
105107

106108

backend/app/api/people.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,25 +109,27 @@ async def list_people(
109109
db: Database,
110110
sort_by: str = Query("recent", enum=["recent", "frequent", "alphabetical"]),
111111
limit: int = Query(50, ge=1, le=100),
112+
offset: int = Query(0, ge=0),
112113
):
113114
"""
114-
List all people the user knows about.
115+
List all people the user knows about with pagination.
115116
116117
Sort options:
117118
- recent: Most recently mentioned first
118119
- frequent: Most frequently mentioned first
119120
- alphabetical: Alphabetically by name
120121
"""
121122
people_service = PeopleService(db)
122-
people = await people_service.list_people(
123+
people, total = await people_service.list_people(
123124
user_id=current_user.id,
124125
sort_by=sort_by,
125126
limit=limit,
127+
offset=offset,
126128
)
127129

128130
return PeopleListResponse(
129131
people=[PersonSummary(**p) for p in people],
130-
total=len(people),
132+
total=total,
131133
)
132134

133135

backend/app/services/connection_service.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import logging
44
from uuid import UUID
55
from datetime import datetime, timedelta
6-
from sqlalchemy import select, and_, or_
6+
from sqlalchemy import select, and_, or_, func
77
from sqlalchemy.ext.asyncio import AsyncSession
88
from sqlalchemy.orm import selectinload
99
from openai import AsyncOpenAI
@@ -222,25 +222,32 @@ async def get_connections(
222222
self,
223223
user_id: UUID,
224224
limit: int = 20,
225+
offset: int = 0,
225226
unnotified_only: bool = False,
226227
undismissed_only: bool = True,
227-
) -> list[MemoryConnection]:
228-
"""Get connections for a user."""
229-
query = (
228+
) -> tuple[list[MemoryConnection], int]:
229+
"""Get connections for a user with pagination."""
230+
# Base query for filtering
231+
base_query = (
230232
select(MemoryConnection)
231233
.where(MemoryConnection.user_id == user_id)
232-
.order_by(MemoryConnection.created_at.desc())
233234
)
234235

235236
if unnotified_only:
236-
query = query.where(MemoryConnection.notified_at.is_(None))
237+
base_query = base_query.where(MemoryConnection.notified_at.is_(None))
237238

238239
if undismissed_only:
239-
query = query.where(MemoryConnection.dismissed_at.is_(None))
240+
base_query = base_query.where(MemoryConnection.dismissed_at.is_(None))
241+
242+
# Get total count
243+
count_query = select(func.count()).select_from(base_query.subquery())
244+
total_result = await self.db.execute(count_query)
245+
total = total_result.scalar() or 0
240246

241-
query = query.limit(limit)
247+
# Apply ordering and pagination
248+
query = base_query.order_by(MemoryConnection.created_at.desc()).offset(offset).limit(limit)
242249
result = await self.db.execute(query)
243-
return list(result.scalars().all())
250+
return list(result.scalars().all()), total
244251

245252
async def get_connection_with_memories(
246253
self, connection_id: UUID, user_id: UUID

backend/app/services/people_service.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,28 +61,37 @@ async def list_people(
6161
sort_by: str = "recent", # 'recent', 'frequent', 'alphabetical'
6262
entity_type: str = "person",
6363
limit: int = 50,
64-
) -> list[dict]:
65-
"""List all people (entities) with stats."""
66-
query = (
64+
offset: int = 0,
65+
) -> tuple[list[dict], int]:
66+
"""List all people (entities) with stats and pagination."""
67+
# Base query for filtering
68+
base_query = (
6769
select(Entity)
6870
.where(Entity.user_id == user_id)
6971
.where(Entity.entity_type == entity_type)
7072
)
7173

74+
# Get total count
75+
count_query = select(func.count()).select_from(base_query.subquery())
76+
total_result = await self.db.execute(count_query)
77+
total = total_result.scalar() or 0
78+
79+
# Apply sorting
7280
if sort_by == "recent":
73-
query = query.order_by(Entity.last_seen.desc())
81+
base_query = base_query.order_by(Entity.last_seen.desc())
7482
elif sort_by == "frequent":
75-
query = query.order_by(Entity.mention_count.desc())
83+
base_query = base_query.order_by(Entity.mention_count.desc())
7684
elif sort_by == "alphabetical":
77-
query = query.order_by(Entity.name.asc())
85+
base_query = base_query.order_by(Entity.name.asc())
7886
else:
79-
query = query.order_by(Entity.last_seen.desc())
87+
base_query = base_query.order_by(Entity.last_seen.desc())
8088

81-
query = query.limit(limit)
89+
# Apply pagination
90+
query = base_query.offset(offset).limit(limit)
8291
result = await self.db.execute(query)
8392
entities = list(result.scalars().all())
8493

85-
return [
94+
people = [
8695
{
8796
"id": str(e.id),
8897
"name": e.name,
@@ -94,6 +103,7 @@ async def list_people(
94103
}
95104
for e in entities
96105
]
106+
return people, total
97107

98108
async def search_contacts(
99109
self,

0 commit comments

Comments
 (0)