From 3c66fcabfc9bdac07bab8b2eee9c79cfd160f92f Mon Sep 17 00:00:00 2001 From: m Date: Mon, 13 Jul 2026 16:35:01 +0200 Subject: [PATCH] files responses --- backend/internal/db/files.sql.go | 56 +++++++++++++++++-- .../db/migrations/005_folders.down.sql | 3 + .../internal/db/migrations/005_folders.up.sql | 3 + backend/internal/db/models.go | 21 +++---- backend/internal/db/queries/files.sql | 5 ++ backend/internal/db/tags.sql.go | 3 +- backend/internal/handler/files.go | 39 ++++++------- backend/internal/model/file.go | 27 ++++----- backend/internal/service/file.go | 22 ++++---- 9 files changed, 121 insertions(+), 58 deletions(-) create mode 100644 backend/internal/db/migrations/005_folders.down.sql create mode 100644 backend/internal/db/migrations/005_folders.up.sql diff --git a/backend/internal/db/files.sql.go b/backend/internal/db/files.sql.go index e84965a..6714d89 100644 --- a/backend/internal/db/files.sql.go +++ b/backend/internal/db/files.sql.go @@ -14,7 +14,7 @@ import ( const createFile = `-- name: CreateFile :one INSERT INTO files (id, name, mime_type, size, storage_key, checksum, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) -RETURNING id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder +RETURNING id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder, parent_file_id ` type CreateFileParams struct { @@ -47,6 +47,7 @@ func (q *Queries) CreateFile(ctx context.Context, arg CreateFileParams) (File, e &i.CreatedAt, &i.UpdatedAt, &i.IsFolder, + &i.ParentFileID, ) return i, err } @@ -54,7 +55,7 @@ func (q *Queries) CreateFile(ctx context.Context, arg CreateFileParams) (File, e const createFolder = `-- name: CreateFolder :one INSERT INTO files (id, name, created_at, updated_at) VALUES ($1, $2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) -RETURNING id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder +RETURNING id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder, parent_file_id ` type CreateFolderParams struct { @@ -76,6 +77,7 @@ func (q *Queries) CreateFolder(ctx context.Context, arg CreateFolderParams) (Fil &i.CreatedAt, &i.UpdatedAt, &i.IsFolder, + &i.ParentFileID, ) return i, err } @@ -91,7 +93,7 @@ func (q *Queries) DeleteFile(ctx context.Context, id string) error { } const getFile = `-- name: GetFile :one -SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder FROM files +SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder, parent_file_id FROM files WHERE id = $1 LIMIT 1 ` @@ -109,12 +111,13 @@ func (q *Queries) GetFile(ctx context.Context, id string) (File, error) { &i.CreatedAt, &i.UpdatedAt, &i.IsFolder, + &i.ParentFileID, ) return i, err } const listFiles = `-- name: ListFiles :many -SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder FROM files +SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder, parent_file_id FROM files ORDER BY created_at DESC ` @@ -138,6 +141,7 @@ func (q *Queries) ListFiles(ctx context.Context) ([]File, error) { &i.CreatedAt, &i.UpdatedAt, &i.IsFolder, + &i.ParentFileID, ); err != nil { return nil, err } @@ -153,7 +157,7 @@ func (q *Queries) ListFiles(ctx context.Context) ([]File, error) { } const listFilesByID = `-- name: ListFilesByID :many -SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder FROM files +SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder, parent_file_id FROM files WHERE id = ANY($1::text[]) ORDER BY created_at DESC ` @@ -178,6 +182,48 @@ func (q *Queries) ListFilesByID(ctx context.Context, dollar_1 []string) ([]File, &i.CreatedAt, &i.UpdatedAt, &i.IsFolder, + &i.ParentFileID, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listFolders = `-- name: ListFolders :many +SELECT id, name, mime_type, size, storage_key, checksum, ocr_text, created_at, updated_at, is_folder, parent_file_id FROM files +WHERE is_folder = true +ORDER BY created_at DESC +` + +func (q *Queries) ListFolders(ctx context.Context) ([]File, error) { + rows, err := q.db.QueryContext(ctx, listFolders) + if err != nil { + return nil, err + } + defer rows.Close() + var items []File + for rows.Next() { + var i File + if err := rows.Scan( + &i.ID, + &i.Name, + &i.MimeType, + &i.Size, + &i.StorageKey, + &i.Checksum, + &i.OcrText, + &i.CreatedAt, + &i.UpdatedAt, + &i.IsFolder, + &i.ParentFileID, ); err != nil { return nil, err } diff --git a/backend/internal/db/migrations/005_folders.down.sql b/backend/internal/db/migrations/005_folders.down.sql new file mode 100644 index 0000000..a36242d --- /dev/null +++ b/backend/internal/db/migrations/005_folders.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE files DROP CONSTRAINT IF EXISTS fk_parent_file_id + +ALTER TABLE files DROP COLUMN IF EXISTS parent_file_id; \ No newline at end of file diff --git a/backend/internal/db/migrations/005_folders.up.sql b/backend/internal/db/migrations/005_folders.up.sql new file mode 100644 index 0000000..bba7447 --- /dev/null +++ b/backend/internal/db/migrations/005_folders.up.sql @@ -0,0 +1,3 @@ +ALTER TABLE files ADD COLUMN parent_file_id TEXT; + +ALTER TABLE files ADD CONSTRAINT fk_parent_file_id FOREIGN KEY(parent_file_id) REFERENCES files(id) \ No newline at end of file diff --git a/backend/internal/db/models.go b/backend/internal/db/models.go index dc15ec5..ec218b0 100644 --- a/backend/internal/db/models.go +++ b/backend/internal/db/models.go @@ -10,16 +10,17 @@ import ( ) type File struct { - ID string `json:"id"` - Name string `json:"name"` - MimeType string `json:"mime_type"` - Size int64 `json:"size"` - StorageKey string `json:"storage_key"` - Checksum string `json:"checksum"` - OcrText string `json:"ocr_text"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - IsFolder bool `json:"is_folder"` + ID string `json:"id"` + Name string `json:"name"` + MimeType string `json:"mime_type"` + Size int64 `json:"size"` + StorageKey string `json:"storage_key"` + Checksum string `json:"checksum"` + OcrText string `json:"ocr_text"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + IsFolder bool `json:"is_folder"` + ParentFileID sql.NullString `json:"parent_file_id"` } type FileTag struct { diff --git a/backend/internal/db/queries/files.sql b/backend/internal/db/queries/files.sql index 338823e..0fdc4c1 100644 --- a/backend/internal/db/queries/files.sql +++ b/backend/internal/db/queries/files.sql @@ -6,6 +6,11 @@ WHERE id = $1 LIMIT 1; SELECT * FROM files ORDER BY created_at DESC; +-- name: ListFolders :many +SELECT * FROM files +WHERE is_folder = true +ORDER BY created_at DESC; + -- name: ListFilesByID :many SELECT * FROM files WHERE id = ANY($1::text[]) diff --git a/backend/internal/db/tags.sql.go b/backend/internal/db/tags.sql.go index fd7a4d8..dda5a33 100644 --- a/backend/internal/db/tags.sql.go +++ b/backend/internal/db/tags.sql.go @@ -64,7 +64,7 @@ func (q *Queries) DeleteTag(ctx context.Context, id string) error { } const getFilesByTagID = `-- name: GetFilesByTagID :many -SELECT f.id, f.name, f.mime_type, f.size, f.storage_key, f.checksum, f.ocr_text, f.created_at, f.updated_at, f.is_folder FROM files f +SELECT f.id, f.name, f.mime_type, f.size, f.storage_key, f.checksum, f.ocr_text, f.created_at, f.updated_at, f.is_folder, f.parent_file_id FROM files f JOIN file_tags ft ON f.id = ft.file_id WHERE ft.tag_id = $1 ORDER BY f.created_at DESC @@ -90,6 +90,7 @@ func (q *Queries) GetFilesByTagID(ctx context.Context, tagID sql.NullString) ([] &i.CreatedAt, &i.UpdatedAt, &i.IsFolder, + &i.ParentFileID, ); err != nil { return nil, err } diff --git a/backend/internal/handler/files.go b/backend/internal/handler/files.go index 0097fdb..bef7a01 100644 --- a/backend/internal/handler/files.go +++ b/backend/internal/handler/files.go @@ -64,15 +64,16 @@ func (h *FileHandler) List(c *gin.Context) { } type fileResponse struct { - ID string `json:"id"` - URL string `json:"url"` - Name string `json:"name"` - Size int64 `json:"size"` - Tags []tagResponse `json:"tags"` - CreatedAt string `json:"createdAt"` - MimeType string `json:"mimeType"` - OcrText string `json:"ocrText,omitempty"` - UpdatedAt string `json:"updatedAt"` + ID string `json:"id"` + URL string `json:"url"` + Name string `json:"name"` + Size int64 `json:"size"` + Tags []tagResponse `json:"tags"` + CreatedAt string `json:"createdAt"` + MimeType string `json:"mimeType"` + OcrText string `json:"ocrText,omitempty"` + ParentFileID string `json:"parentFileID,omitempty"` + UpdatedAt string `json:"updatedAt"` } resp := make([]fileResponse, len(files)) @@ -89,17 +90,17 @@ func (h *FileHandler) List(c *gin.Context) { }) } - resp[i] = fileResponse{ - ID: f.ID, - URL: h.urls.GenerateDownloadURL(f.ID), - Name: f.Name, - Size: f.Size, - Tags: tags, - CreatedAt: f.CreatedAt, - OcrText: f.OcrText, - UpdatedAt: f.UpdatedAt, - MimeType: f.MimeType, + ID: f.ID, + URL: h.urls.GenerateDownloadURL(f.ID), + Name: f.Name, + Size: f.Size, + Tags: tags, + CreatedAt: f.CreatedAt, + ParentFileID: f.ParentFileID, + OcrText: f.OcrText, + UpdatedAt: f.UpdatedAt, + MimeType: f.MimeType, } } diff --git a/backend/internal/model/file.go b/backend/internal/model/file.go index dccbbb1..e5c4362 100644 --- a/backend/internal/model/file.go +++ b/backend/internal/model/file.go @@ -1,22 +1,23 @@ package model type Tag struct { - ID string `json:"id"` - Name string `json:"name"` - TagType string `json:"tagType"` + ID string `json:"id"` + Name string `json:"name"` + TagType string `json:"tagType"` } type File struct { - ID string `json:"id"` - Name string `json:"name"` - MimeType string `json:"mimeType"` - Size int64 `json:"size"` - StorageKey string `json:"-"` - Checksum string `json:"-"` - OcrText string `json:"ocrText,omitempty"` - Tags []Tag `json:"tags"` - CreatedAt string `json:"createdAt"` - UpdatedAt string `json:"updatedAt"` + ID string `json:"id"` + Name string `json:"name"` + MimeType string `json:"mimeType"` + Size int64 `json:"size"` + StorageKey string `json:"-"` + Checksum string `json:"-"` + OcrText string `json:"ocrText,omitempty"` + Tags []Tag `json:"tags"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` + ParentFileID string `json:"parentFileID,omitempty"` } type UploadResult struct { diff --git a/backend/internal/service/file.go b/backend/internal/service/file.go index 0c05fac..ec45ceb 100644 --- a/backend/internal/service/file.go +++ b/backend/internal/service/file.go @@ -167,17 +167,19 @@ func dbToModel(f db.File, dbTags []db.Tag) model.File { for i, t := range dbTags { tags[i] = model.Tag{ID: t.ID, Name: t.TagName, TagType: t.TagType} } + return model.File{ - ID: f.ID, - Name: f.Name, - MimeType: f.MimeType, - Size: f.Size, - StorageKey: f.StorageKey, - Checksum: f.Checksum, - OcrText: f.OcrText, - Tags: tags, - CreatedAt: f.CreatedAt.String(), - UpdatedAt: f.UpdatedAt.String(), + ID: f.ID, + Name: f.Name, + MimeType: f.MimeType, + Size: f.Size, + StorageKey: f.StorageKey, + Checksum: f.Checksum, + OcrText: f.OcrText, + ParentFileID: f.ParentFileID.String, + Tags: tags, + CreatedAt: f.CreatedAt.String(), + UpdatedAt: f.UpdatedAt.String(), } }