catpuccing moka
This commit is contained in:
parent
381ed6270e
commit
ead8819e39
8 changed files with 154 additions and 64 deletions
|
|
@ -63,12 +63,15 @@ func (r *GORMSessionRepository) FindValid(ctx context.Context, t string) (domain
|
|||
type GORMContentRepository struct{ db *gorm.DB }
|
||||
|
||||
func NewContentRepository(db *gorm.DB) IContentRepository { return &GORMContentRepository{db} }
|
||||
func (r *GORMContentRepository) List(ctx context.Context, limit, offset int, category string, badges []string) ([]domain.Content, error) {
|
||||
func (r *GORMContentRepository) List(ctx context.Context, limit, offset int, category, status string, badges []string) ([]domain.Content, error) {
|
||||
var rows []persistence.ContentModel
|
||||
query := r.db.WithContext(ctx).Model(&persistence.ContentModel{}).Preload("Category").Preload("Badges")
|
||||
if category != "" {
|
||||
query = query.Where("category_id IN (SELECT id FROM categories WHERE slug = ?)", category)
|
||||
}
|
||||
if status != "" {
|
||||
query = query.Where("status = ?", status)
|
||||
}
|
||||
for _, badge := range badges {
|
||||
query = query.Where("EXISTS (SELECT 1 FROM content_badges cb JOIN badges b ON b.id = cb.badge_id WHERE cb.content_id = content.id AND b.name = ?)", badge)
|
||||
}
|
||||
|
|
@ -113,6 +116,17 @@ func (r *GORMContentRepository) Update(ctx context.Context, d domain.Content, h
|
|||
if err := tx.Model(&persistence.ContentModel{}).Where("id = ?", d.ID).Updates(map[string]any{"slug": d.Slug, "title": d.Title, "summary": d.Summary, "body": d.Body, "status": d.Status, "published": d.Published, "updated_at": d.UpdatedAt, "updated_by": d.UpdatedBy}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("DELETE FROM content_badges WHERE content_id = ?", d.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for _, badge := range d.Badges {
|
||||
if err := tx.Exec("INSERT INTO badges (name) VALUES (?) ON CONFLICT (name) DO NOTHING", badge).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec("INSERT INTO content_badges (content_id, badge_id) SELECT ?, id FROM badges WHERE name = ? ON CONFLICT DO NOTHING", d.ID, badge).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return tx.Create(&persistence.ContentHistoryModel{ContentID: h.ContentID, Operation: h.Operation, ActorID: h.ActorID, ActorAdminID: h.ActorAdminID, CreatedAt: h.CreatedAt, Snapshot: h.Snapshot}).Error
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ type ISessionRepository interface {
|
|||
FindValid(context.Context, string) (domain.Session, error)
|
||||
}
|
||||
type IContentRepository interface {
|
||||
List(context.Context, int, int, string, []string) ([]domain.Content, error)
|
||||
List(context.Context, int, int, string, string, []string) ([]domain.Content, error)
|
||||
ListCategories(context.Context) ([]domain.Category, error)
|
||||
ListBadges(context.Context) ([]domain.Badge, error)
|
||||
FindBySlug(context.Context, string) (domain.Content, error)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
type IContentService interface {
|
||||
List(context.Context, int, int, string, []string) ([]domain.Content, error)
|
||||
List(context.Context, int, int, string, string, []string) ([]domain.Content, error)
|
||||
ListCategories(context.Context) ([]domain.Category, error)
|
||||
ListBadges(context.Context) ([]domain.Badge, error)
|
||||
Get(context.Context, string) (domain.Content, error)
|
||||
|
|
@ -26,7 +26,7 @@ type ContentService struct {
|
|||
func NewContentService(r repository.IContentRepository, a *AuthService) *ContentService {
|
||||
return &ContentService{repo: r, auth: a}
|
||||
}
|
||||
func (s *ContentService) List(ctx context.Context, limit, offset int, category string, badges []string) ([]domain.Content, error) {
|
||||
func (s *ContentService) List(ctx context.Context, limit, offset int, category, status string, badges []string) ([]domain.Content, error) {
|
||||
if limit < 1 {
|
||||
limit = 20
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ func (s *ContentService) List(ctx context.Context, limit, offset int, category s
|
|||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
return s.repo.List(ctx, limit, offset, category, badges)
|
||||
return s.repo.List(ctx, limit, offset, category, status, badges)
|
||||
}
|
||||
func (s *ContentService) ListCategories(ctx context.Context) ([]domain.Category, error) {
|
||||
return s.repo.ListCategories(ctx)
|
||||
|
|
@ -65,9 +65,11 @@ func (s *ContentService) Update(ctx context.Context, c domain.Content, session d
|
|||
c.CreatedAt = old.CreatedAt
|
||||
c.CreatedBy = old.CreatedBy
|
||||
c.UpdatedAt = time.Now()
|
||||
c.Badges = normalizeBadges(c.Badges)
|
||||
if session.UserID != nil {
|
||||
c.UpdatedBy = *session.UserID
|
||||
}
|
||||
|
||||
snapshot, _ := json.Marshal(c)
|
||||
h := domain.ContentHistory{ContentID: c.ID, Operation: "updated", CreatedAt: c.UpdatedAt, Snapshot: string(snapshot), ActorID: session.UserID, ActorAdminID: session.AdminID}
|
||||
if err = s.repo.Update(ctx, c, h); err != nil {
|
||||
|
|
@ -76,6 +78,23 @@ func (s *ContentService) Update(ctx context.Context, c domain.Content, session d
|
|||
return c, nil
|
||||
}
|
||||
|
||||
func normalizeBadges(values []string) []string {
|
||||
result := make([]string, 0, len(values))
|
||||
seen := make(map[string]struct{}, len(values))
|
||||
for _, value := range values {
|
||||
value = strings.ToLower(strings.TrimSpace(value))
|
||||
if value == "" || len(value) > 100 {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[value]; ok {
|
||||
continue
|
||||
}
|
||||
seen[value] = struct{}{}
|
||||
result = append(result, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var slugRE = regexp.MustCompile(`^[a-z0-9]+(?:-[a-z0-9]+)*$`)
|
||||
|
||||
func validSlug(s string) bool { return len(s) <= 200 && slugRE.MatchString(s) }
|
||||
|
|
|
|||
|
|
@ -183,7 +183,11 @@ func (h *Handler) contentList(w http.ResponseWriter, r *http.Request) {
|
|||
filtered = append(filtered, badge)
|
||||
}
|
||||
}
|
||||
items, e := h.content.List(r.Context(), limit, offset, strings.TrimSpace(strings.ToLower(r.URL.Query().Get("category"))), filtered)
|
||||
items, e := h.content.List(r.Context(), limit, offset,
|
||||
strings.TrimSpace(strings.ToLower(r.URL.Query().Get("category"))),
|
||||
strings.TrimSpace(strings.ToLower(r.URL.Query().Get("status"))),
|
||||
filtered,
|
||||
)
|
||||
if e != nil {
|
||||
jsonWrite(w, 500, map[string]string{"error": e.Error()})
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue