sync: feed pane UX from private repo
- Strip kanban, grid, and saved views from ViewsOverlay (1103→631 lines) - Add sort order dropdown (Updated/Edges/Created) with localStorage persistence - Polish filter button, dropdown, and filter chips - Switch to server-side dimension filtering with AND logic (dimensionsMatch=all) - Add description preview and edge count to node cards - Add 'created' sort option and dimensionsMatch param to types, service, API Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
86f43c9975
commit
2940e142c8
+16
-2
@@ -25,12 +25,26 @@ export async function GET(request: NextRequest) {
|
||||
filters.dimensions = dimensionsParam.split(',').map(dim => dim.trim()).filter(Boolean);
|
||||
}
|
||||
|
||||
// Handle sortBy parameter
|
||||
// Handle dimensionsMatch parameter (any|all)
|
||||
const dimensionsMatchParam = searchParams.get('dimensionsMatch');
|
||||
if (dimensionsMatchParam === 'all') {
|
||||
filters.dimensionsMatch = 'all';
|
||||
}
|
||||
|
||||
// Handle sortBy parameter (sortBy=edges|updated|created)
|
||||
const sortByParam = searchParams.get('sortBy');
|
||||
if (sortByParam === 'edges' || sortByParam === 'updated') {
|
||||
if (sortByParam === 'edges' || sortByParam === 'updated' || sortByParam === 'created') {
|
||||
filters.sortBy = sortByParam;
|
||||
}
|
||||
|
||||
// Also support sort=created_at|updated_at with order=asc|desc (used by feed)
|
||||
const sortParam = searchParams.get('sort');
|
||||
if (sortParam === 'created_at') {
|
||||
filters.sortBy = 'created';
|
||||
} else if (sortParam === 'updated_at') {
|
||||
filters.sortBy = 'updated';
|
||||
}
|
||||
|
||||
const nodes = await nodeService.getNodes(filters);
|
||||
|
||||
return NextResponse.json({
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@ export class NodeService {
|
||||
// PostgreSQL path removed in SQLite-only consolidation
|
||||
|
||||
private async getNodesSQLite(filters: NodeFilters = {}): Promise<Node[]> {
|
||||
const { dimensions, search, limit = 100, offset = 0, sortBy } = filters;
|
||||
const { dimensions, search, limit = 100, offset = 0, sortBy, dimensionsMatch = 'any' } = filters;
|
||||
const sqlite = getSQLiteClient();
|
||||
|
||||
// Use nodes_v view for array-like dimensions behavior (exclude embedding BLOB for performance)
|
||||
@@ -28,12 +28,23 @@ export class NodeService {
|
||||
|
||||
// Filter by dimensions (SQLite JOIN with node_dimensions)
|
||||
if (dimensions && dimensions.length > 0) {
|
||||
query += ` AND EXISTS (
|
||||
SELECT 1 FROM node_dimensions nd
|
||||
WHERE nd.node_id = n.id
|
||||
AND nd.dimension IN (${dimensions.map(() => '?').join(',')})
|
||||
)`;
|
||||
params.push(...dimensions);
|
||||
if (dimensionsMatch === 'all' && dimensions.length > 1) {
|
||||
// AND logic: node must have ALL specified dimensions
|
||||
query += ` AND (
|
||||
SELECT COUNT(DISTINCT nd.dimension) FROM node_dimensions nd
|
||||
WHERE nd.node_id = n.id
|
||||
AND nd.dimension IN (${dimensions.map(() => '?').join(',')})
|
||||
) = ?`;
|
||||
params.push(...dimensions, dimensions.length);
|
||||
} else {
|
||||
// OR logic: node must have at least one of the specified dimensions
|
||||
query += ` AND EXISTS (
|
||||
SELECT 1 FROM node_dimensions nd
|
||||
WHERE nd.node_id = n.id
|
||||
AND nd.dimension IN (${dimensions.map(() => '?').join(',')})
|
||||
)`;
|
||||
params.push(...dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
// Text search in title, description, and content (SQLite LIKE with COLLATE NOCASE)
|
||||
@@ -62,6 +73,8 @@ export class NodeService {
|
||||
} else if (sortBy === 'edges') {
|
||||
// Sort by edge count (most connected first)
|
||||
query += ' ORDER BY edge_count DESC, n.updated_at DESC';
|
||||
} else if (sortBy === 'created') {
|
||||
query += ' ORDER BY n.created_at DESC';
|
||||
} else {
|
||||
query += ' ORDER BY n.updated_at DESC';
|
||||
}
|
||||
|
||||
@@ -70,7 +70,8 @@ export interface NodeFilters {
|
||||
search?: string; // Text search in title/content
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
sortBy?: 'updated' | 'edges'; // Sort by updated_at or edge count
|
||||
sortBy?: 'updated' | 'edges' | 'created'; // Sort by updated_at, edge count, or created_at
|
||||
dimensionsMatch?: 'any' | 'all'; // 'any' = OR (default), 'all' = AND
|
||||
}
|
||||
|
||||
export interface ChunkData {
|
||||
|
||||
Reference in New Issue
Block a user