2026-02-20 23:22:10 +00:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
2026-02-21 23:09:34 +00:00
|
|
|
"strconv"
|
2026-02-20 23:22:10 +00:00
|
|
|
|
|
|
|
|
"github.com/gofiber/fiber/v3"
|
|
|
|
|
"lmika.dev/lmika/weiro/models"
|
2026-03-22 03:33:31 +00:00
|
|
|
"lmika.dev/lmika/weiro/providers/db"
|
2026-03-18 10:45:28 +00:00
|
|
|
"lmika.dev/lmika/weiro/services/categories"
|
2026-02-20 23:22:10 +00:00
|
|
|
"lmika.dev/lmika/weiro/services/posts"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type PostsHandler struct {
|
2026-03-18 10:45:28 +00:00
|
|
|
PostService *posts.Service
|
|
|
|
|
CategoryService *categories.Service
|
2026-02-20 23:22:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ph PostsHandler) Index(c fiber.Ctx) error {
|
2026-02-23 10:18:34 +00:00
|
|
|
var req struct {
|
|
|
|
|
Filter string `query:"filter"`
|
2026-03-22 03:33:31 +00:00
|
|
|
Page int `query:"page"`
|
2026-02-23 10:18:34 +00:00
|
|
|
}
|
|
|
|
|
if err := c.Bind().Query(&req); err != nil {
|
|
|
|
|
return fiber.ErrBadRequest
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-22 03:33:31 +00:00
|
|
|
const perPage = 25
|
|
|
|
|
if req.Page < 1 {
|
|
|
|
|
req.Page = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result, err := ph.PostService.ListPosts(c.Context(), req.Filter == "deleted", db.PagingParams{
|
|
|
|
|
Offset: int64((req.Page - 1) * perPage),
|
|
|
|
|
Limit: perPage,
|
|
|
|
|
})
|
2026-02-21 23:09:34 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-22 03:33:31 +00:00
|
|
|
totalPages := int(result.TotalCount+int64(perPage)-1) / perPage
|
|
|
|
|
if totalPages < 1 {
|
|
|
|
|
totalPages = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pageInfo := models.PageInfo{
|
|
|
|
|
CurrentPage: req.Page,
|
|
|
|
|
TotalPages: totalPages,
|
|
|
|
|
PostsPerPage: perPage,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-23 10:18:34 +00:00
|
|
|
return accepts(c, json(func() any {
|
2026-03-22 03:33:31 +00:00
|
|
|
return result.Posts
|
2026-02-23 10:18:34 +00:00
|
|
|
}), html(func(c fiber.Ctx) error {
|
|
|
|
|
return c.Render("posts/index", fiber.Map{
|
2026-03-22 03:33:31 +00:00
|
|
|
"req": req,
|
|
|
|
|
"posts": result.Posts,
|
|
|
|
|
"pageInfo": pageInfo,
|
2026-02-23 10:18:34 +00:00
|
|
|
})
|
|
|
|
|
}))
|
2026-02-20 23:22:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ph PostsHandler) New(c fiber.Ctx) error {
|
2026-02-21 23:09:34 +00:00
|
|
|
p := models.Post{
|
2026-02-24 11:21:26 +00:00
|
|
|
GUID: models.NewNanoID(),
|
|
|
|
|
State: models.StateDraft,
|
2026-02-21 23:09:34 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-18 10:45:28 +00:00
|
|
|
cats, err := ph.CategoryService.ListCategories(c.Context())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-21 23:09:34 +00:00
|
|
|
return c.Render("posts/edit", fiber.Map{
|
2026-03-18 10:45:28 +00:00
|
|
|
"post": p,
|
|
|
|
|
"categories": cats,
|
|
|
|
|
"selectedCategories": map[int64]bool{},
|
2026-03-21 01:01:24 +00:00
|
|
|
"bodyClass": "post-edit-page",
|
2026-02-21 23:09:34 +00:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ph PostsHandler) Edit(c fiber.Ctx) error {
|
|
|
|
|
postIDStr := c.Params("postID")
|
|
|
|
|
if postIDStr == "" {
|
|
|
|
|
return fiber.ErrBadRequest
|
|
|
|
|
}
|
|
|
|
|
postID, err := strconv.ParseInt(postIDStr, 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fiber.ErrBadRequest
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
post, err := ph.PostService.GetPost(c.Context(), postID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-18 10:45:28 +00:00
|
|
|
cats, err := ph.CategoryService.ListCategories(c.Context())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
postCats, err := ph.PostService.GetPostCategories(c.Context(), postID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
selectedCategories := make(map[int64]bool)
|
|
|
|
|
for _, pc := range postCats {
|
|
|
|
|
selectedCategories[pc.ID] = true
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-23 10:18:34 +00:00
|
|
|
return accepts(c, json(func() any {
|
|
|
|
|
return post
|
|
|
|
|
}), html(func(c fiber.Ctx) error {
|
|
|
|
|
return c.Render("posts/edit", fiber.Map{
|
2026-03-18 10:45:28 +00:00
|
|
|
"post": post,
|
|
|
|
|
"categories": cats,
|
|
|
|
|
"selectedCategories": selectedCategories,
|
2026-03-21 01:01:24 +00:00
|
|
|
"bodyClass": "post-edit-page",
|
2026-02-23 10:18:34 +00:00
|
|
|
})
|
|
|
|
|
}))
|
2026-02-20 23:22:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ph PostsHandler) Update(c fiber.Ctx) error {
|
|
|
|
|
var req posts.CreatePostParams
|
|
|
|
|
if err := c.Bind().Body(&req); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-24 11:21:26 +00:00
|
|
|
post, err := ph.PostService.UpdatePost(c.Context(), req)
|
2026-02-20 23:22:10 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-23 10:18:34 +00:00
|
|
|
return accepts(c, json(func() any {
|
|
|
|
|
// TODO: should be created if brand new
|
|
|
|
|
return post
|
|
|
|
|
}), html(func(c fiber.Ctx) error {
|
|
|
|
|
return c.Redirect().To(fmt.Sprintf("/sites/%v/posts", post.SiteID))
|
|
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ph PostsHandler) Patch(c fiber.Ctx) error {
|
|
|
|
|
postIDStr := c.Params("postID")
|
|
|
|
|
if postIDStr == "" {
|
|
|
|
|
return fiber.ErrBadRequest
|
|
|
|
|
}
|
|
|
|
|
postID, err := strconv.ParseInt(postIDStr, 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fiber.ErrBadRequest
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
Action string `json:"action"`
|
|
|
|
|
}
|
|
|
|
|
if err := c.Bind().Body(&req); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch req.Action {
|
|
|
|
|
case "restore":
|
|
|
|
|
if err := ph.PostService.RestorePost(c.Context(), postID); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
return fiber.ErrBadRequest
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return accepts(c, json(func() any {
|
|
|
|
|
return struct{}{}
|
|
|
|
|
}), html(func(c fiber.Ctx) error {
|
2026-03-18 11:19:26 +00:00
|
|
|
return c.Redirect().To(fmt.Sprintf("/sites/%v/posts", models.MustGetSite(c.Context()).ID))
|
2026-02-23 10:18:34 +00:00
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ph PostsHandler) Delete(c fiber.Ctx) error {
|
|
|
|
|
postIDStr := c.Params("postID")
|
|
|
|
|
if postIDStr == "" {
|
|
|
|
|
return fiber.ErrBadRequest
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
postID, err := strconv.ParseInt(postIDStr, 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fiber.ErrBadRequest
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var req struct {
|
|
|
|
|
Hard bool `query:"hard"`
|
|
|
|
|
}
|
|
|
|
|
if err := c.Bind().Query(&req); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := ph.PostService.DeletePost(c.Context(), postID, req.Hard); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return accepts(c, json(func() any {
|
|
|
|
|
return fiber.Map{}
|
|
|
|
|
}), html(func(c fiber.Ctx) error {
|
2026-03-07 22:37:49 +00:00
|
|
|
return c.Redirect().To("/")
|
|
|
|
|
}))
|
|
|
|
|
}
|