library.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. """Pydantic schemas for library (File Manager) functionality."""
  2. from datetime import datetime
  3. from pydantic import BaseModel, Field
  4. # ============ Folder Schemas ============
  5. class FolderCreate(BaseModel):
  6. """Schema for creating a new folder."""
  7. name: str = Field(..., min_length=1, max_length=255)
  8. parent_id: int | None = None
  9. project_id: int | None = None
  10. archive_id: int | None = None
  11. class FolderUpdate(BaseModel):
  12. """Schema for updating a folder."""
  13. name: str | None = Field(None, min_length=1, max_length=255)
  14. parent_id: int | None = None
  15. project_id: int | None = None # 0 to unlink
  16. archive_id: int | None = None # 0 to unlink
  17. class FolderResponse(BaseModel):
  18. """Schema for folder response."""
  19. id: int
  20. name: str
  21. parent_id: int | None
  22. project_id: int | None = None
  23. archive_id: int | None = None
  24. project_name: str | None = None
  25. archive_name: str | None = None
  26. file_count: int = 0 # Computed field
  27. created_at: datetime
  28. updated_at: datetime
  29. class Config:
  30. from_attributes = True
  31. class FolderTreeItem(BaseModel):
  32. """Schema for folder tree item (includes children)."""
  33. id: int
  34. name: str
  35. parent_id: int | None
  36. project_id: int | None = None
  37. archive_id: int | None = None
  38. project_name: str | None = None
  39. archive_name: str | None = None
  40. file_count: int = 0
  41. children: list["FolderTreeItem"] = []
  42. class Config:
  43. from_attributes = True
  44. # ============ File Schemas ============
  45. class FileCreate(BaseModel):
  46. """Schema for creating a file entry (internal use after upload)."""
  47. filename: str
  48. file_path: str
  49. file_type: str
  50. file_size: int
  51. file_hash: str | None = None
  52. thumbnail_path: str | None = None
  53. metadata: dict | None = None
  54. folder_id: int | None = None
  55. project_id: int | None = None
  56. class FileUpdate(BaseModel):
  57. """Schema for updating a file."""
  58. filename: str | None = Field(None, min_length=1, max_length=255)
  59. folder_id: int | None = None
  60. project_id: int | None = None
  61. notes: str | None = None
  62. class FileDuplicate(BaseModel):
  63. """Reference to a duplicate file."""
  64. id: int
  65. filename: str
  66. folder_id: int | None
  67. folder_name: str | None
  68. created_at: datetime
  69. class FileResponse(BaseModel):
  70. """Schema for file response."""
  71. id: int
  72. folder_id: int | None
  73. folder_name: str | None = None
  74. project_id: int | None
  75. project_name: str | None = None
  76. filename: str
  77. file_path: str
  78. file_type: str
  79. file_size: int
  80. file_hash: str | None
  81. thumbnail_path: str | None
  82. metadata: dict | None
  83. print_count: int
  84. last_printed_at: datetime | None
  85. notes: str | None
  86. # Duplicate detection
  87. duplicates: list[FileDuplicate] | None = None
  88. duplicate_count: int = 0
  89. # User tracking (Issue #206)
  90. created_by_id: int | None = None
  91. created_by_username: str | None = None
  92. created_at: datetime
  93. updated_at: datetime
  94. # Metadata fields
  95. print_name: str | None = None
  96. print_time_seconds: int | None = None
  97. filament_used_grams: float | None = None
  98. sliced_for_model: str | None = None
  99. class Config:
  100. from_attributes = True
  101. class FileListResponse(BaseModel):
  102. """Schema for file list item (lighter than full response)."""
  103. id: int
  104. folder_id: int | None
  105. filename: str
  106. file_type: str
  107. file_size: int
  108. thumbnail_path: str | None
  109. print_count: int
  110. duplicate_count: int = 0
  111. # User tracking (Issue #206)
  112. created_by_id: int | None = None
  113. created_by_username: str | None = None
  114. created_at: datetime
  115. # Key metadata fields for display
  116. print_name: str | None = None
  117. print_time_seconds: int | None = None
  118. filament_used_grams: float | None = None
  119. sliced_for_model: str | None = None
  120. class Config:
  121. from_attributes = True
  122. class FileMoveRequest(BaseModel):
  123. """Schema for moving files to a folder."""
  124. file_ids: list[int]
  125. folder_id: int | None = None # None = move to root
  126. class FilePrintRequest(BaseModel):
  127. """Schema for printing a file from the library.
  128. Note: printer_id is passed as a query parameter, not in the body.
  129. """
  130. # Print options (same as archive reprint)
  131. plate_id: int | None = None
  132. ams_mapping: list[int] | None = None
  133. bed_levelling: bool = True
  134. flow_cali: bool = False
  135. vibration_cali: bool = True
  136. layer_inspect: bool = False
  137. timelapse: bool = False
  138. use_ams: bool = True
  139. class FileUploadResponse(BaseModel):
  140. """Schema for file upload response."""
  141. id: int
  142. filename: str
  143. file_type: str
  144. file_size: int
  145. thumbnail_path: str | None
  146. duplicate_of: int | None = None # ID of existing file with same hash
  147. metadata: dict | None = None
  148. # ============ Bulk Operations ============
  149. class BulkDeleteRequest(BaseModel):
  150. """Schema for bulk delete operations."""
  151. file_ids: list[int] = []
  152. folder_ids: list[int] = []
  153. class BulkDeleteResponse(BaseModel):
  154. """Schema for bulk delete response."""
  155. deleted_files: int
  156. deleted_folders: int
  157. # ============ Queue Operations ============
  158. class AddToQueueRequest(BaseModel):
  159. """Schema for adding library files to the print queue."""
  160. file_ids: list[int] = Field(..., min_length=1)
  161. class AddToQueueResult(BaseModel):
  162. """Result for a single file added to queue."""
  163. file_id: int
  164. filename: str
  165. queue_item_id: int
  166. class AddToQueueError(BaseModel):
  167. """Error for a file that couldn't be added to queue."""
  168. file_id: int
  169. filename: str
  170. error: str
  171. class AddToQueueResponse(BaseModel):
  172. """Schema for add-to-queue response."""
  173. added: list[AddToQueueResult]
  174. errors: list[AddToQueueError]
  175. # ============ ZIP Extraction ============
  176. class ZipExtractResult(BaseModel):
  177. """Result for a single file extracted from ZIP."""
  178. filename: str
  179. file_id: int
  180. folder_id: int | None = None
  181. class ZipExtractError(BaseModel):
  182. """Error for a file that couldn't be extracted."""
  183. filename: str
  184. error: str
  185. class ZipExtractResponse(BaseModel):
  186. """Schema for ZIP extraction response."""
  187. extracted: int
  188. folders_created: int
  189. files: list[ZipExtractResult]
  190. errors: list[ZipExtractError]
  191. # ============ STL Thumbnail Generation ============
  192. class BatchThumbnailRequest(BaseModel):
  193. """Schema for batch STL thumbnail generation request."""
  194. file_ids: list[int] | None = None
  195. folder_id: int | None = None
  196. all_missing: bool = False
  197. class BatchThumbnailResult(BaseModel):
  198. """Result for a single file thumbnail generation."""
  199. file_id: int
  200. filename: str
  201. success: bool
  202. error: str | None = None
  203. class BatchThumbnailResponse(BaseModel):
  204. """Schema for batch thumbnail generation response."""
  205. processed: int
  206. succeeded: int
  207. failed: int
  208. results: list[BatchThumbnailResult]