feat: implement Story 1.4 — recent view and drag-and-drop organization

Add sortOrder column to diagrams, extend PATCH endpoint with projectId
and sortOrder fields, add POST /diagrams/reorder bulk endpoint with
ownership verification and duplicate ID validation. Enhance RecentList
with lastAiMessage preview subtitle. Implement @dnd-kit drag-and-drop
in ProjectTree sidebar with cross-project moves, intra-project reorder,
optimistic updates, drag overlay, drop indicators, and keyboard/pointer
sensor support. Context-aware GET ordering: sortOrder for project views,
updatedAt for recent/all views. 141 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-02-23 23:21:09 +00:00
parent e9cd685d3d
commit 098f4968be
14 changed files with 3366 additions and 363 deletions

View File

@@ -110,12 +110,8 @@
"name": "account_user_id_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -218,12 +214,8 @@
"name": "invitation_organization_id_organization_id_fk",
"tableFrom": "invitation",
"tableTo": "organization",
"columnsFrom": [
"organization_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["organization_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
},
@@ -231,12 +223,8 @@
"name": "invitation_inviter_id_user_id_fk",
"tableFrom": "invitation",
"tableTo": "user",
"columnsFrom": [
"inviter_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["inviter_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -320,12 +308,8 @@
"name": "member_organization_id_organization_id_fk",
"tableFrom": "member",
"tableTo": "organization",
"columnsFrom": [
"organization_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["organization_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
},
@@ -333,12 +317,8 @@
"name": "member_user_id_user_id_fk",
"tableFrom": "member",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -397,9 +377,7 @@
"organization_slug_unique": {
"name": "organization_slug_unique",
"nullsNotDistinct": false,
"columns": [
"slug"
]
"columns": ["slug"]
}
},
"policies": {},
@@ -514,12 +492,8 @@
"name": "passkey_user_id_user_id_fk",
"tableFrom": "passkey",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -618,12 +592,8 @@
"name": "session_user_id_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -633,9 +603,7 @@
"session_token_unique": {
"name": "session_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
"columns": ["token"]
}
},
"policies": {},
@@ -708,12 +676,8 @@
"name": "two_factor_user_id_user_id_fk",
"tableFrom": "two_factor",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -820,9 +784,7 @@
"user_email_unique": {
"name": "user_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
"columns": ["email"]
}
},
"policies": {},
@@ -963,12 +925,8 @@
"name": "credit_transaction_customer_id_customer_id_fk",
"tableFrom": "credit_transaction",
"tableTo": "customer",
"columnsFrom": [
"customer_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["customer_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -1042,12 +1000,8 @@
"name": "customer_user_id_user_id_fk",
"tableFrom": "customer",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -1057,16 +1011,12 @@
"customer_userId_unique": {
"name": "customer_userId_unique",
"nullsNotDistinct": false,
"columns": [
"user_id"
]
"columns": ["user_id"]
},
"customer_customerId_unique": {
"name": "customer_customerId_unique",
"nullsNotDistinct": false,
"columns": [
"customer_id"
]
"columns": ["customer_id"]
}
},
"policies": {},
@@ -1147,12 +1097,8 @@
"name": "diagram_user_id_user_id_fk",
"tableFrom": "diagram",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -1212,12 +1158,8 @@
"name": "project_user_id_user_id_fk",
"tableFrom": "project",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
@@ -1264,12 +1206,8 @@
"name": "chat_user_id_user_id_fk",
"tableFrom": "chat",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -1318,12 +1256,8 @@
"tableFrom": "message",
"tableTo": "chat",
"schemaTo": "chat",
"columnsFrom": [
"chat_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["chat_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -1383,12 +1317,8 @@
"tableFrom": "part",
"tableTo": "message",
"schemaTo": "chat",
"columnsFrom": [
"message_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["message_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -1435,12 +1365,8 @@
"name": "chat_user_id_user_id_fk",
"tableFrom": "chat",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -1635,12 +1561,8 @@
"tableFrom": "citation_unit",
"tableTo": "document",
"schemaTo": "pdf",
"columnsFrom": [
"document_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["document_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
},
@@ -1649,12 +1571,8 @@
"tableFrom": "citation_unit",
"tableTo": "retrieval_chunk",
"schemaTo": "pdf",
"columnsFrom": [
"retrieval_chunk_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["retrieval_chunk_id"],
"columnsTo": ["id"],
"onDelete": "set null",
"onUpdate": "cascade"
}
@@ -1722,12 +1640,8 @@
"tableFrom": "document",
"tableTo": "chat",
"schemaTo": "pdf",
"columnsFrom": [
"chat_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["chat_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -1822,12 +1736,8 @@
"tableFrom": "embedding",
"tableTo": "document",
"schemaTo": "pdf",
"columnsFrom": [
"document_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["document_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -1882,12 +1792,8 @@
"tableFrom": "message",
"tableTo": "chat",
"schemaTo": "pdf",
"columnsFrom": [
"chat_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["chat_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -1998,12 +1904,8 @@
"tableFrom": "retrieval_chunk",
"tableTo": "document",
"schemaTo": "pdf",
"columnsFrom": [
"document_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["document_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -2077,12 +1979,8 @@
"name": "generation_user_id_user_id_fk",
"tableFrom": "generation",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -2130,12 +2028,8 @@
"tableFrom": "image",
"tableTo": "generation",
"schemaTo": "image",
"columnsFrom": [
"generation_id"
],
"columnsTo": [
"id"
],
"columnsFrom": ["generation_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "cascade"
}
@@ -2180,11 +2074,7 @@
"public.plan": {
"name": "plan",
"schema": "public",
"values": [
"free",
"premium",
"enterprise"
]
"values": ["free", "premium", "enterprise"]
},
"public.diagram_type": {
"name": "diagram_type",
@@ -2201,51 +2091,27 @@
"chat.role": {
"name": "role",
"schema": "chat",
"values": [
"system",
"assistant",
"user"
]
"values": ["system", "assistant", "user"]
},
"pdf.role": {
"name": "role",
"schema": "pdf",
"values": [
"user",
"assistant",
"system"
]
"values": ["user", "assistant", "system"]
},
"pdf.processing_status": {
"name": "processing_status",
"schema": "pdf",
"values": [
"pending",
"processing",
"ready",
"failed"
]
"values": ["pending", "processing", "ready", "failed"]
},
"pdf.unit_type": {
"name": "unit_type",
"schema": "pdf",
"values": [
"prose",
"heading",
"list",
"table",
"code"
]
"values": ["prose", "heading", "list", "table", "code"]
},
"image.aspect_ratio": {
"name": "aspect_ratio",
"schema": "image",
"values": [
"square",
"standard",
"landscape",
"portrait"
]
"values": ["square", "standard", "landscape", "portrait"]
}
},
"schemas": {
@@ -2260,4 +2126,4 @@
"schemas": {},
"tables": {}
}
}
}