move files into folders
This commit is contained in:
@@ -120,7 +120,7 @@ func (q *Queries) GetFile(ctx context.Context, id string) (File, error) {
|
||||
const listFiles = `-- name: ListFiles :many
|
||||
SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, parent_file_id, is_folder FROM files
|
||||
WHERE parent_file_id IS NULL
|
||||
ORDER BY created_at DESC
|
||||
ORDER BY is_folder DESC, created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListFiles(ctx context.Context) ([]File, error) {
|
||||
@@ -281,6 +281,22 @@ func (q *Queries) ListFolders(ctx context.Context) ([]File, error) {
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const moveFiles = `-- name: MoveFiles :exec
|
||||
UPDATE files
|
||||
SET parent_file_id = $1, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ANY($2::text[])
|
||||
`
|
||||
|
||||
type MoveFilesParams struct {
|
||||
ParentFileID sql.NullString `json:"parent_file_id"`
|
||||
Column2 []string `json:"column_2"`
|
||||
}
|
||||
|
||||
func (q *Queries) MoveFiles(ctx context.Context, arg MoveFilesParams) error {
|
||||
_, err := q.db.ExecContext(ctx, moveFiles, arg.ParentFileID, pq.Array(arg.Column2))
|
||||
return err
|
||||
}
|
||||
|
||||
const updateFile = `-- name: UpdateFile :exec
|
||||
UPDATE files
|
||||
SET name = $1, mime_type = $2, ocr_text = $3, updated_at = CURRENT_TIMESTAMP
|
||||
|
||||
@@ -5,7 +5,7 @@ WHERE id = $1 LIMIT 1;
|
||||
-- name: ListFiles :many
|
||||
SELECT * FROM files
|
||||
WHERE parent_file_id IS NULL
|
||||
ORDER BY created_at DESC;
|
||||
ORDER BY is_folder DESC, created_at DESC;
|
||||
|
||||
-- name: ListFolders :many
|
||||
SELECT * FROM files
|
||||
@@ -32,6 +32,11 @@ SELECT * FROM files
|
||||
WHERE parent_file_id = $1
|
||||
ORDER BY is_folder DESC, created_at DESC;
|
||||
|
||||
-- name: MoveFiles :exec
|
||||
UPDATE files
|
||||
SET parent_file_id = $1, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ANY($2::text[]);
|
||||
|
||||
-- name: UpdateFile :exec
|
||||
UPDATE files
|
||||
SET name = $1, mime_type = $2, ocr_text = $3, updated_at = CURRENT_TIMESTAMP
|
||||
|
||||
@@ -197,3 +197,48 @@ func (h *FileHandler) GetTags(c *gin.Context) {
|
||||
}
|
||||
api.Success(c, tags)
|
||||
}
|
||||
|
||||
func (h *FileHandler) MoveFiles(c *gin.Context) {
|
||||
var body struct {
|
||||
FileIDs []string `json:"file_ids" binding:"required"`
|
||||
ParentFileID *string `json:"parent_file_id"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_BODY", "Body must contain 'file_ids' array")
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.files.MoveFiles(body.FileIDs, body.ParentFileID); err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "DB_ERROR", "Failed to move files")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, gin.H{"moved": len(body.FileIDs)})
|
||||
}
|
||||
|
||||
func (h *FileHandler) ListFolders(c *gin.Context) {
|
||||
folders, err := h.files.ListFolders()
|
||||
if err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "DB_ERROR", "Failed to list folders")
|
||||
return
|
||||
}
|
||||
api.Success(c, folders)
|
||||
}
|
||||
|
||||
func (h *FileHandler) CreateFolder(c *gin.Context) {
|
||||
var body struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
api.Error(c, http.StatusBadRequest, "INVALID_BODY", "Body must contain 'name'")
|
||||
return
|
||||
}
|
||||
|
||||
folder, err := h.files.CreateFolder(body.Name)
|
||||
if err != nil {
|
||||
api.Error(c, http.StatusInternalServerError, "DB_ERROR", "Failed to create folder")
|
||||
return
|
||||
}
|
||||
|
||||
api.Success(c, folder)
|
||||
}
|
||||
|
||||
@@ -9,9 +9,12 @@ func SetupRoutes(r *gin.Engine, h *Handler) {
|
||||
|
||||
api.GET("/files", h.File.List)
|
||||
api.POST("/files/upload", h.File.Upload)
|
||||
api.POST("/files/move", h.File.MoveFiles)
|
||||
api.POST("/files/folders", h.File.CreateFolder)
|
||||
api.GET("/files/folders", h.File.ListFolders)
|
||||
api.GET("/files/download/:id", h.File.Download)
|
||||
api.GET("/files/:id", h.File.Get)
|
||||
api.DELETE("/files/:id", h.File.Delete)
|
||||
api.GET("/files/:id", h.File.Get)
|
||||
|
||||
api.POST("/files/:id/tags", h.File.AddTags)
|
||||
api.GET("/files/:id/tags", h.File.GetTags)
|
||||
|
||||
@@ -162,6 +162,57 @@ func (s *FileService) GetTagsByFileID(fileID string) ([]model.Tag, error) {
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func (s *FileService) MoveFiles(fileIDs []string, parentFileID *string) error {
|
||||
var parentID sql.NullString
|
||||
if parentFileID != nil {
|
||||
parentID = sql.NullString{String: *parentFileID, Valid: true}
|
||||
}
|
||||
return s.queries.MoveFiles(context.Background(), db.MoveFilesParams{
|
||||
ParentFileID: parentID,
|
||||
Column2: fileIDs,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *FileService) CreateFolder(name string) (*model.File, error) {
|
||||
f, err := s.queries.CreateFolder(context.Background(), db.CreateFolderParams{
|
||||
ID: uuid.New().String(),
|
||||
Name: name,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create folder: %w", err)
|
||||
}
|
||||
m := dbToModel(f, nil)
|
||||
return &m, nil
|
||||
}
|
||||
|
||||
func (s *FileService) ListFolders() ([]model.File, error) {
|
||||
dbFiles, err := s.queries.ListFolders(context.Background())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list folders: %w", err)
|
||||
}
|
||||
folders := make([]model.File, len(dbFiles))
|
||||
for i, f := range dbFiles {
|
||||
folders[i] = dbToModel(f, nil)
|
||||
}
|
||||
return folders, nil
|
||||
}
|
||||
|
||||
func (s *FileService) ListFilesByParentID(parentID string) ([]model.File, error) {
|
||||
dbFiles, err := s.queries.ListFilesByParentID(context.Background(), sql.NullString{String: parentID, Valid: true})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list files by parent: %w", err)
|
||||
}
|
||||
files := make([]model.File, len(dbFiles))
|
||||
for i, f := range dbFiles {
|
||||
tags, err := s.queries.GetTagsByFileID(context.Background(), sql.NullString{String: f.ID, Valid: true})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get tags for file %s: %w", f.ID, err)
|
||||
}
|
||||
files[i] = dbToModel(f, tags)
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func dbToModel(f db.File, dbTags []db.Tag) model.File {
|
||||
tags := make([]model.Tag, len(dbTags))
|
||||
for i, t := range dbTags {
|
||||
|
||||
Reference in New Issue
Block a user