endpoints to add tags

This commit is contained in:
m
2026-07-13 00:36:08 +02:00
parent 7dc53ea99f
commit c3bb0dd6ab
6 changed files with 165 additions and 16 deletions
+29 -2
View File
@@ -137,9 +137,36 @@ func (h *FileHandler) Delete(c *gin.Context) {
}
func (h *FileHandler) AddTags(c *gin.Context) {
api.Error(c, http.StatusNotImplemented, "NOT_IMPLEMENTED", "Tags not yet implemented")
id := c.Param("id")
var body struct {
Tags []string `json:"tags" binding:"required"`
}
if err := c.ShouldBindJSON(&body); err != nil {
api.Error(c, http.StatusBadRequest, "INVALID_BODY", "Body must contain a 'tags' array")
return
}
if err := h.files.AddTags(id, body.Tags); err != nil {
api.Error(c, http.StatusInternalServerError, "DB_ERROR", "Failed to add tags")
return
}
tags, err := h.files.GetTagsByFileID(id)
if err != nil {
api.Error(c, http.StatusInternalServerError, "DB_ERROR", "Failed to fetch tags")
return
}
api.Success(c, tags)
}
func (h *FileHandler) GetTags(c *gin.Context) {
api.Success(c, []interface{}{})
id := c.Param("id")
tags, err := h.files.GetTagsByFileID(id)
if err != nil {
api.Error(c, http.StatusInternalServerError, "DB_ERROR", "Failed to fetch tags")
return
}
api.Success(c, tags)
}
+7
View File
@@ -1,5 +1,11 @@
package model
type Tag struct {
ID string `json:"id"`
Name string `json:"name"`
TagType string `json:"tagType"`
}
type File struct {
ID string `json:"id"`
Name string `json:"name"`
@@ -8,6 +14,7 @@ type File struct {
StorageKey string `json:"-"`
Checksum string `json:"-"`
OcrText string `json:"ocrText,omitempty"`
Tags []Tag `json:"tags"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
-5
View File
@@ -1,6 +1 @@
package model
type Tag struct {
ID string `json:"id"`
Name string `json:"name"`
}
+57 -3
View File
@@ -2,6 +2,7 @@ package service
import (
"context"
"database/sql"
"encoding/hex"
"fmt"
"mime/multipart"
@@ -74,7 +75,11 @@ func (s *FileService) List() ([]model.File, error) {
files := make([]model.File, len(dbFiles))
for i, f := range dbFiles {
files[i] = dbToModel(f)
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
}
@@ -84,7 +89,11 @@ func (s *FileService) Get(id string) (*model.File, error) {
if err != nil {
return nil, fmt.Errorf("get file: %w", err)
}
m := dbToModel(f)
tags, err := s.queries.GetTagsByFileID(context.Background(), sql.NullString{String: f.ID, Valid: true})
if err != nil {
return nil, fmt.Errorf("get tags: %w", err)
}
m := dbToModel(f, tags)
return &m, nil
}
@@ -113,7 +122,51 @@ func (s *FileService) UpdateOCRText(id, text string) error {
})
}
func dbToModel(f db.File) model.File {
func (s *FileService) AddTags(fileID string, tagNames []string) error {
for _, name := range tagNames {
tag, err := s.queries.GetTagByName(context.Background(), name)
if err == sql.ErrNoRows {
tag, err = s.queries.CreateTag(context.Background(), db.CreateTagParams{
ID: uuid.New().String(),
TagName: name,
TagType: "none",
})
if err != nil {
return fmt.Errorf("create tag %q: %w", name, err)
}
} else if err != nil {
return fmt.Errorf("get tag %q: %w", name, err)
}
err = s.queries.AddTagToFile(context.Background(), db.AddTagToFileParams{
ID: uuid.New().String(),
TagID: sql.NullString{String: tag.ID, Valid: true},
FileID: sql.NullString{String: fileID, Valid: true},
})
if err != nil {
return fmt.Errorf("link tag %q to file: %w", name, err)
}
}
return nil
}
func (s *FileService) GetTagsByFileID(fileID string) ([]model.Tag, error) {
dbTags, err := s.queries.GetTagsByFileID(context.Background(), sql.NullString{String: fileID, Valid: true})
if err != nil {
return nil, fmt.Errorf("get tags: %w", err)
}
tags := make([]model.Tag, len(dbTags))
for i, t := range dbTags {
tags[i] = model.Tag{ID: t.ID, Name: t.TagName, TagType: t.TagType}
}
return tags, nil
}
func dbToModel(f db.File, dbTags []db.Tag) model.File {
tags := make([]model.Tag, len(dbTags))
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,
@@ -122,6 +175,7 @@ func dbToModel(f db.File) model.File {
StorageKey: f.StorageKey,
Checksum: f.Checksum,
OcrText: f.OcrText,
Tags: tags,
CreatedAt: f.CreatedAt.String(),
UpdatedAt: f.UpdatedAt.String(),
}