fix(tags): filter out existing tags and upsert note tag link

This commit is contained in:
Kristian Borgwarth 2026-04-05 14:11:54 +02:00
parent f600752d87
commit 56194470fb
5 changed files with 72 additions and 18 deletions

View file

@ -3,7 +3,6 @@ package handlers
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"log/slog"
"github.com/KristianJBorgwarth/dendrite.daemon/core/frontmatter" "github.com/KristianJBorgwarth/dendrite.daemon/core/frontmatter"
"github.com/KristianJBorgwarth/dendrite.daemon/core/models" "github.com/KristianJBorgwarth/dendrite.daemon/core/models"
@ -18,7 +17,7 @@ type createNoteCommand struct {
Path string `json:"path"` Path string `json:"path"`
} }
type CreateNoteHandler struct{ type CreateNoteHandler struct {
uow *repositories.UnitOfWork uow *repositories.UnitOfWork
} }
@ -40,15 +39,11 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an
return nil, err return nil, err
} }
slog.Debug("rendered template", "data", string(data))
tags, err := frontmatter.ParseTags(data) tags, err := frontmatter.ParseTags(data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
slog.Debug("parsed tags", "tags", tags)
tx, err := h.uow.Begin() tx, err := h.uow.Begin()
if err != nil { if err != nil {
return nil, err return nil, err
@ -59,17 +54,31 @@ func (h *CreateNoteHandler) Handle(ctx context.Context, raw json.RawMessage) (an
tagRepo := repositories.NewTagRepository(tx) tagRepo := repositories.NewTagRepository(tx)
noteRepo := repositories.NewNoteRepository(tx) noteRepo := repositories.NewNoteRepository(tx)
tagModels, err := models.CreateTags(tags) dbTags, err := tagRepo.GetByNames(ctx, tags)
if err != nil { if err != nil {
return nil, err return nil, err
} }
slog.Debug("Creating tags", "tags", tags) newTags := utils.Filter(tags, func(name string) bool {
for _, t := range dbTags {
if t.Name() == name {
return false
}
}
return true
})
tagModels, err := models.CreateTags(newTags)
if err != nil {
return nil, err
}
if err = tagRepo.Upsert(ctx, tagModels); err != nil { if err = tagRepo.Upsert(ctx, tagModels); err != nil {
return nil, err return nil, err
} }
tagModels = append(tagModels, dbTags...)
note := models.CreateNote(cmd.Path, cmd.Title, slug) note := models.CreateNote(cmd.Path, cmd.Title, slug)
if err = noteRepo.Upsert(ctx, note); err != nil { if err = noteRepo.Upsert(ctx, note); err != nil {

View file

@ -7,13 +7,9 @@ type Tag struct {
name string name string
} }
func NewTag(name string) *Tag { func NewTag(id, name string) *Tag {
id, err := uuid.NewV7()
if err != nil {
panic(err)
}
return &Tag{ return &Tag{
id: id.String(), id: id,
name: name, name: name,
} }
} }
@ -21,7 +17,11 @@ func NewTag(name string) *Tag {
func CreateTags(tags []string) ([]*Tag, error) { func CreateTags(tags []string) ([]*Tag, error) {
tagModels := make([]*Tag, len(tags)) tagModels := make([]*Tag, len(tags))
for i, tag := range tags { for i, tag := range tags {
tagModels[i] = NewTag(tag) id, err := uuid.NewV7()
if err != nil {
panic(err)
}
tagModels[i] = NewTag(id.String(), tag)
} }
return tagModels, nil return tagModels, nil

View file

@ -8,3 +8,13 @@ func Select[T any, U any](input []T, mapper func(T) U) []U {
} }
return output return output
} }
func Filter[T any](input []T, predicate func(T) bool) []T {
output := make([]T, 0)
for _, item := range input {
if predicate(item) {
output = append(output, item)
}
}
return output
}

BIN
dendrite

Binary file not shown.

View file

@ -11,6 +11,7 @@ import (
type ITagRepository interface { type ITagRepository interface {
Upsert(ctx context.Context, tags []*models.Tag) error Upsert(ctx context.Context, tags []*models.Tag) error
UpsertNoteTags(ctx context.Context, noteID string, tagIDs []string) error UpsertNoteTags(ctx context.Context, noteID string, tagIDs []string) error
GetByNames(ctx context.Context, names []string) ([]*models.Tag, error)
} }
type tagRepository struct { type tagRepository struct {
@ -62,3 +63,37 @@ func (r *tagRepository) UpsertNoteTags(ctx context.Context ,noteID string, tagID
return nil return nil
} }
func (r *tagRepository) GetByNames(ctx context.Context, names []string) ([]*models.Tag, error) {
if len(names) == 0 {
return []*models.Tag{}, nil
}
placeholders := make([]string, 0, len(names))
args := make([]any, 0, len(names))
for _, name := range names {
placeholders = append(placeholders, "?")
args = append(args, name)
}
query := "SELECT id, name FROM tags WHERE name IN (" + strings.Join(placeholders, ",") + ")"
rows, err := r.Transaction.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var tags []*models.Tag
for rows.Next() {
var id string
var name string
if err := rows.Scan(&id, &name); err != nil {
return nil, err
}
tags = append(tags, models.NewTag(id, name))
}
return tags, nil
}