2025-11-07 01:04:10 +00:00
|
|
|
package blog
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"arimelody-web/admin/core"
|
|
|
|
|
"arimelody-web/admin/templates"
|
|
|
|
|
"arimelody-web/controller"
|
|
|
|
|
"arimelody-web/model"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/http"
|
|
|
|
|
"os"
|
|
|
|
|
"slices"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func Handler(app *model.AppState) http.Handler {
|
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
|
|
2025-11-08 14:13:42 +00:00
|
|
|
mux.Handle("/blogs/{id}", serveBlogPost(app))
|
|
|
|
|
mux.Handle("/blogs/", serveBlogIndex(app))
|
2025-11-07 01:04:10 +00:00
|
|
|
|
|
|
|
|
mux.ServeHTTP(w, r)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type (
|
2025-11-08 12:54:31 +00:00
|
|
|
blogPostCollection struct {
|
2025-11-07 01:04:10 +00:00
|
|
|
Year int
|
2025-11-08 12:54:31 +00:00
|
|
|
Posts []*model.BlogPost
|
2025-11-07 01:04:10 +00:00
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2025-11-08 12:54:31 +00:00
|
|
|
func (c *blogPostCollection) Clone() blogPostCollection {
|
|
|
|
|
return blogPostCollection{
|
|
|
|
|
Year: c.Year,
|
|
|
|
|
Posts: slices.Clone(c.Posts),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-07 02:35:51 +00:00
|
|
|
func serveBlogIndex(app *model.AppState) http.Handler {
|
2025-11-07 01:04:10 +00:00
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2025-11-07 02:35:51 +00:00
|
|
|
session := r.Context().Value("session").(*model.Session)
|
2025-11-07 01:04:10 +00:00
|
|
|
|
|
|
|
|
posts, err := controller.GetBlogPosts(app.DB, false, -1, 0)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog posts: %v\n", err)
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-08 12:54:31 +00:00
|
|
|
collections := []*blogPostCollection{}
|
|
|
|
|
collection := blogPostCollection{
|
|
|
|
|
Posts: []*model.BlogPost{},
|
|
|
|
|
Year: -1,
|
|
|
|
|
}
|
2025-11-07 01:04:10 +00:00
|
|
|
for i, post := range posts {
|
2025-11-08 12:54:31 +00:00
|
|
|
if i == 0 {
|
|
|
|
|
collection.Year = post.PublishDate.Year()
|
2025-11-07 01:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
2025-11-08 12:54:31 +00:00
|
|
|
if post.PublishDate.Year() != collection.Year {
|
|
|
|
|
clone := collection.Clone()
|
|
|
|
|
collections = append(collections, &clone)
|
|
|
|
|
collection = blogPostCollection{
|
|
|
|
|
Year: post.PublishDate.Year(),
|
|
|
|
|
Posts: []*model.BlogPost{},
|
|
|
|
|
}
|
2025-11-07 01:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
2025-11-08 12:54:31 +00:00
|
|
|
collection.Posts = append(collection.Posts, post)
|
2025-11-07 01:04:10 +00:00
|
|
|
|
2025-11-08 12:54:31 +00:00
|
|
|
if i == len(posts) - 1 {
|
|
|
|
|
collections = append(collections, &collection)
|
2025-11-07 01:04:10 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type blogsData struct {
|
|
|
|
|
core.AdminPageData
|
|
|
|
|
TotalPosts int
|
2025-11-08 12:54:31 +00:00
|
|
|
Collections []*blogPostCollection
|
2025-11-07 01:04:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = templates.BlogsTemplate.Execute(w, blogsData{
|
|
|
|
|
AdminPageData: core.AdminPageData{
|
|
|
|
|
Session: session,
|
|
|
|
|
},
|
|
|
|
|
TotalPosts: len(posts),
|
|
|
|
|
Collections: collections,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "WARN: Error rendering admin blog index: %v\n", err)
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2025-11-07 02:35:51 +00:00
|
|
|
|
|
|
|
|
func serveBlogPost(app *model.AppState) http.Handler {
|
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
session := r.Context().Value("session").(*model.Session)
|
|
|
|
|
|
|
|
|
|
blogID := r.PathValue("id")
|
|
|
|
|
|
|
|
|
|
post, err := controller.GetBlogPost(app.DB, blogID)
|
|
|
|
|
if err != nil {
|
2025-11-08 12:54:31 +00:00
|
|
|
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog %s: %v\n", blogID, err)
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if post == nil {
|
2025-11-07 02:35:51 +00:00
|
|
|
http.NotFound(w, r)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type blogPostData struct {
|
|
|
|
|
core.AdminPageData
|
|
|
|
|
Post *model.BlogPost
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = templates.EditBlogTemplate.Execute(w, blogPostData{
|
|
|
|
|
AdminPageData: core.AdminPageData{
|
|
|
|
|
Session: session,
|
|
|
|
|
},
|
|
|
|
|
Post: post,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "WARN: Error rendering admin edit page for blog %s: %v\n", blogID, err)
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|