mirror of
https://github.com/ForFarmTeam/ForFarm.git
synced 2025-12-18 13:34:08 +01:00
feat: add image_url attribute and handle method
This commit is contained in:
parent
8af97c0150
commit
5eec21a2b1
@ -81,13 +81,14 @@ type GetKnowledgeArticleByIDOutput struct {
|
||||
|
||||
type CreateOrUpdateKnowledgeArticleInput struct {
|
||||
Body struct {
|
||||
UUID string `json:"uuid,omitempty"` // Optional for create, required for update
|
||||
UUID string `json:"uuid,omitempty"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Author string `json:"author"`
|
||||
PublishDate time.Time `json:"publish_date"`
|
||||
ReadTime string `json:"read_time"`
|
||||
Categories []string `json:"categories"`
|
||||
ImageURL string `json:"image_url"`
|
||||
} `json:"body"`
|
||||
}
|
||||
|
||||
@ -130,7 +131,7 @@ func (a *api) getAllKnowledgeArticlesHandler(ctx context.Context, input *struct{
|
||||
}
|
||||
|
||||
func (a *api) getKnowledgeArticleByIDHandler(ctx context.Context, input *struct {
|
||||
UUID string `path:"uuid" example:"550e8400-e29b-41d4-a716-446655440000"`
|
||||
UUID string `path:"uuid"`
|
||||
}) (*GetKnowledgeArticleByIDOutput, error) {
|
||||
resp := &GetKnowledgeArticleByIDOutput{}
|
||||
|
||||
@ -138,8 +139,7 @@ func (a *api) getKnowledgeArticleByIDHandler(ctx context.Context, input *struct
|
||||
return nil, huma.Error400BadRequest("UUID parameter is required")
|
||||
}
|
||||
|
||||
_, err := uuid.FromString(input.UUID)
|
||||
if err != nil {
|
||||
if _, err := uuid.FromString(input.UUID); err != nil {
|
||||
return nil, huma.Error400BadRequest("invalid UUID format")
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ func (a *api) getKnowledgeArticleByIDHandler(ctx context.Context, input *struct
|
||||
}
|
||||
|
||||
func (a *api) getKnowledgeArticlesByCategoryHandler(ctx context.Context, input *struct {
|
||||
Category string `path:"category" example:"Sustainability"`
|
||||
Category string `path:"category"`
|
||||
}) (*GetKnowledgeArticlesOutput, error) {
|
||||
resp := &GetKnowledgeArticlesOutput{}
|
||||
|
||||
@ -190,8 +190,7 @@ func (a *api) createOrUpdateKnowledgeArticleHandler(ctx context.Context, input *
|
||||
}
|
||||
|
||||
if input.Body.UUID != "" {
|
||||
_, err := uuid.FromString(input.Body.UUID)
|
||||
if err != nil {
|
||||
if _, err := uuid.FromString(input.Body.UUID); err != nil {
|
||||
return nil, huma.Error400BadRequest("invalid UUID format")
|
||||
}
|
||||
}
|
||||
@ -204,10 +203,10 @@ func (a *api) createOrUpdateKnowledgeArticleHandler(ctx context.Context, input *
|
||||
PublishDate: input.Body.PublishDate,
|
||||
ReadTime: input.Body.ReadTime,
|
||||
Categories: input.Body.Categories,
|
||||
ImageURL: input.Body.ImageURL,
|
||||
}
|
||||
|
||||
err := a.knowledgeHubRepo.CreateOrUpdateArticle(ctx, article)
|
||||
if err != nil {
|
||||
if err := a.knowledgeHubRepo.CreateOrUpdateArticle(ctx, article); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -216,7 +215,7 @@ func (a *api) createOrUpdateKnowledgeArticleHandler(ctx context.Context, input *
|
||||
}
|
||||
|
||||
func (a *api) getArticleTableOfContentsHandler(ctx context.Context, input *struct {
|
||||
UUID string `path:"uuid" example:"550e8400-e29b-41d4-a716-446655440000"`
|
||||
UUID string `path:"uuid"`
|
||||
}) (*GetTableOfContentsOutput, error) {
|
||||
resp := &GetTableOfContentsOutput{}
|
||||
|
||||
@ -224,8 +223,7 @@ func (a *api) getArticleTableOfContentsHandler(ctx context.Context, input *struc
|
||||
return nil, huma.Error400BadRequest("UUID parameter is required")
|
||||
}
|
||||
|
||||
_, err := uuid.FromString(input.UUID)
|
||||
if err != nil {
|
||||
if _, err := uuid.FromString(input.UUID); err != nil {
|
||||
return nil, huma.Error400BadRequest("invalid UUID format")
|
||||
}
|
||||
|
||||
@ -242,7 +240,7 @@ func (a *api) getArticleTableOfContentsHandler(ctx context.Context, input *struc
|
||||
}
|
||||
|
||||
func (a *api) getArticleRelatedArticlesHandler(ctx context.Context, input *struct {
|
||||
UUID string `path:"uuid" example:"550e8400-e29b-41d4-a716-446655440000"`
|
||||
UUID string `path:"uuid"`
|
||||
}) (*GetRelatedArticlesOutput, error) {
|
||||
resp := &GetRelatedArticlesOutput{}
|
||||
|
||||
@ -250,8 +248,7 @@ func (a *api) getArticleRelatedArticlesHandler(ctx context.Context, input *struc
|
||||
return nil, huma.Error400BadRequest("UUID parameter is required")
|
||||
}
|
||||
|
||||
_, err := uuid.FromString(input.UUID)
|
||||
if err != nil {
|
||||
if _, err := uuid.FromString(input.UUID); err != nil {
|
||||
return nil, huma.Error400BadRequest("invalid UUID format")
|
||||
}
|
||||
|
||||
@ -286,5 +283,5 @@ func (a *api) createRelatedArticleHandler(
|
||||
return nil, huma.Error500InternalServerError("failed to create related article")
|
||||
}
|
||||
|
||||
return nil, nil // HTTP 204 No Content
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@ package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
validation "github.com/go-ozzo/ozzo-validation/v4"
|
||||
@ -15,6 +17,7 @@ type KnowledgeArticle struct {
|
||||
PublishDate time.Time
|
||||
ReadTime string
|
||||
Categories []string
|
||||
ImageURL string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
@ -25,6 +28,16 @@ func (k *KnowledgeArticle) Validate() error {
|
||||
validation.Field(&k.Content, validation.Required),
|
||||
validation.Field(&k.Author, validation.Required),
|
||||
validation.Field(&k.PublishDate, validation.Required),
|
||||
validation.Field(&k.ImageURL,
|
||||
validation.By(func(value interface{}) error {
|
||||
if url, ok := value.(string); ok && url != "" {
|
||||
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
|
||||
return fmt.Errorf("must be a valid URL starting with http:// or https://")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ func (p *postgresKnowledgeHubRepository) fetchArticles(ctx context.Context, quer
|
||||
&a.PublishDate,
|
||||
&a.ReadTime,
|
||||
&a.Categories,
|
||||
&a.ImageURL,
|
||||
&a.CreatedAt,
|
||||
&a.UpdatedAt,
|
||||
); err != nil {
|
||||
@ -46,7 +47,7 @@ func (p *postgresKnowledgeHubRepository) fetchArticles(ctx context.Context, quer
|
||||
|
||||
func (p *postgresKnowledgeHubRepository) GetArticleByID(ctx context.Context, uuid string) (domain.KnowledgeArticle, error) {
|
||||
query := `
|
||||
SELECT uuid, title, content, author, publish_date, read_time, categories, created_at, updated_at
|
||||
SELECT uuid, title, content, author, publish_date, read_time, categories, image_url, created_at, updated_at
|
||||
FROM knowledge_articles
|
||||
WHERE uuid = $1`
|
||||
|
||||
@ -62,7 +63,7 @@ func (p *postgresKnowledgeHubRepository) GetArticleByID(ctx context.Context, uui
|
||||
|
||||
func (p *postgresKnowledgeHubRepository) GetArticlesByCategory(ctx context.Context, category string) ([]domain.KnowledgeArticle, error) {
|
||||
query := `
|
||||
SELECT uuid, title, content, author, publish_date, read_time, categories, created_at, updated_at
|
||||
SELECT uuid, title, content, author, publish_date, read_time, categories, image_url, created_at, updated_at
|
||||
FROM knowledge_articles
|
||||
WHERE $1 = ANY(categories)`
|
||||
|
||||
@ -71,20 +72,24 @@ func (p *postgresKnowledgeHubRepository) GetArticlesByCategory(ctx context.Conte
|
||||
|
||||
func (p *postgresKnowledgeHubRepository) GetAllArticles(ctx context.Context) ([]domain.KnowledgeArticle, error) {
|
||||
query := `
|
||||
SELECT uuid, title, content, author, publish_date, read_time, categories, created_at, updated_at
|
||||
SELECT uuid, title, content, author, publish_date, read_time, categories, image_url, created_at, updated_at
|
||||
FROM knowledge_articles`
|
||||
|
||||
return p.fetchArticles(ctx, query)
|
||||
}
|
||||
|
||||
func (p *postgresKnowledgeHubRepository) CreateOrUpdateArticle(ctx context.Context, article *domain.KnowledgeArticle) error {
|
||||
func (p *postgresKnowledgeHubRepository) CreateOrUpdateArticle(
|
||||
ctx context.Context,
|
||||
article *domain.KnowledgeArticle,
|
||||
) error {
|
||||
if strings.TrimSpace(article.UUID) == "" {
|
||||
article.UUID = uuid.New().String()
|
||||
}
|
||||
|
||||
query := `
|
||||
INSERT INTO knowledge_articles (uuid, title, content, author, publish_date, read_time, categories, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())
|
||||
INSERT INTO knowledge_articles
|
||||
(uuid, title, content, author, publish_date, read_time, categories, image_url, created_at, updated_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW(), NOW())
|
||||
ON CONFLICT (uuid) DO UPDATE
|
||||
SET title = EXCLUDED.title,
|
||||
content = EXCLUDED.content,
|
||||
@ -92,6 +97,7 @@ func (p *postgresKnowledgeHubRepository) CreateOrUpdateArticle(ctx context.Conte
|
||||
publish_date = EXCLUDED.publish_date,
|
||||
read_time = EXCLUDED.read_time,
|
||||
categories = EXCLUDED.categories,
|
||||
image_url = EXCLUDED.image_url,
|
||||
updated_at = NOW()
|
||||
RETURNING uuid, created_at, updated_at`
|
||||
|
||||
@ -105,6 +111,7 @@ func (p *postgresKnowledgeHubRepository) CreateOrUpdateArticle(ctx context.Conte
|
||||
article.PublishDate,
|
||||
article.ReadTime,
|
||||
article.Categories,
|
||||
article.ImageURL,
|
||||
).Scan(&article.UUID, &article.CreatedAt, &article.UpdatedAt)
|
||||
}
|
||||
|
||||
@ -188,8 +195,8 @@ func (p *postgresKnowledgeHubRepository) CreateRelatedArticle(
|
||||
articleID string,
|
||||
related *domain.RelatedArticle,
|
||||
) error {
|
||||
related.UUID = uuid.New().String() // Generate UUID
|
||||
related.ArticleID = articleID // Link to main article
|
||||
related.UUID = uuid.New().String()
|
||||
related.ArticleID = articleID
|
||||
|
||||
query := `
|
||||
INSERT INTO related_articles
|
||||
|
||||
7
backend/migrations/00005_add_image_url_to_articles.sql
Normal file
7
backend/migrations/00005_add_image_url_to_articles.sql
Normal file
@ -0,0 +1,7 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE knowledge_articles
|
||||
ADD COLUMN image_url TEXT;
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE knowledge_articles
|
||||
DROP COLUMN image_url;
|
||||
Loading…
Reference in New Issue
Block a user