add handler, html templates, Makefile and migrations
This commit is contained in:
commit
a06e8db2ff
22 changed files with 1001 additions and 0 deletions
69
web/comment_handler.go
Normal file
69
web/comment_handler.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.snrd.de/Spaenny/goddit"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CommentHandler struct {
|
||||
store goddit.Store
|
||||
}
|
||||
|
||||
func (h *CommentHandler) Store() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
content := r.FormValue("content")
|
||||
idStr := chi.URLParam(r, "postID")
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.store.CreateComment(&goddit.Comment{
|
||||
ID: uuid.New(),
|
||||
PostID: id,
|
||||
Content: content,
|
||||
}); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, r.Referer(), http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *CommentHandler) Vote() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := chi.URLParam(r, "id")
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
c, err := h.store.Comment(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
dir := r.URL.Query().Get("dir")
|
||||
if dir == "up" {
|
||||
c.Votes++
|
||||
} else if dir == "down" {
|
||||
c.Votes--
|
||||
}
|
||||
|
||||
if err := h.store.UpdateComment(&c); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, r.Referer(), http.StatusFound)
|
||||
}
|
||||
}
|
63
web/handler.go
Normal file
63
web/handler.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"git.snrd.de/Spaenny/goddit"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
)
|
||||
|
||||
func NewHandler(store goddit.Store) *Handler {
|
||||
h := &Handler{
|
||||
Mux: chi.NewMux(),
|
||||
store: store,
|
||||
}
|
||||
|
||||
threads := ThreadHandler{store: store}
|
||||
posts := PostHandler{store: store}
|
||||
comments := CommentHandler{store: store}
|
||||
|
||||
h.Use(middleware.Logger)
|
||||
|
||||
h.Get("/", h.Home())
|
||||
h.Route("/threads", func(r chi.Router) {
|
||||
r.Get("/", threads.List())
|
||||
r.Get("/new", threads.Create())
|
||||
r.Post("/", threads.Store())
|
||||
r.Get("/{id}", threads.Show())
|
||||
r.Post("/{id}/delete", threads.Delete())
|
||||
r.Get("/{id}/new", posts.Create())
|
||||
r.Post("/{id}", posts.Store())
|
||||
r.Get("/{threadID}/{postID}", posts.Show())
|
||||
r.Get("/{threadID}/{postID}/vote", posts.Vote())
|
||||
r.Post("/{threadID}/{postID}", comments.Store())
|
||||
})
|
||||
h.Get("/comments/{id}/vote", comments.Vote())
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
*chi.Mux
|
||||
|
||||
store goddit.Store
|
||||
}
|
||||
|
||||
func (h *Handler) Home() http.HandlerFunc {
|
||||
type data struct {
|
||||
Posts []goddit.Post
|
||||
}
|
||||
|
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/home.html"))
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
pp, err := h.store.Posts()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
tmpl.Execute(w, data{Posts: pp})
|
||||
}
|
||||
}
|
150
web/post_handler.go
Normal file
150
web/post_handler.go
Normal file
|
@ -0,0 +1,150 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"git.snrd.de/Spaenny/goddit"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type PostHandler struct {
|
||||
store goddit.Store
|
||||
}
|
||||
|
||||
func (h *PostHandler) Create() http.HandlerFunc {
|
||||
type data struct {
|
||||
Thread goddit.Thread
|
||||
}
|
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/post_create.html"))
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := chi.URLParam(r, "id")
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
t, err := h.store.Thread(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
tmpl.Execute(w, data{Thread: t})
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PostHandler) Show() http.HandlerFunc {
|
||||
type data struct {
|
||||
Thread goddit.Thread
|
||||
Post goddit.Post
|
||||
Comments []goddit.Comment
|
||||
}
|
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/post.html"))
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
postIDStr := chi.URLParam(r, "postID")
|
||||
threadIDStr := chi.URLParam(r, "threadID")
|
||||
|
||||
postID, err := uuid.Parse(postIDStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
threadID, err := uuid.Parse(threadIDStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
p, err := h.store.Post(postID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
cc, err := h.store.CommentsByPost(p.ID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
t, err := h.store.Thread(threadID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
tmpl.Execute(w, data{Thread: t, Post: p, Comments: cc})
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PostHandler) Store() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
title := r.FormValue("title")
|
||||
content := r.FormValue("content")
|
||||
|
||||
idStr := chi.URLParam(r, "id")
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
t, err := h.store.Thread(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
p := &goddit.Post{
|
||||
ID: uuid.New(),
|
||||
ThreadID: t.ID,
|
||||
Title: title,
|
||||
Content: content,
|
||||
}
|
||||
|
||||
if err := h.store.CreatePost(p); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/threads/"+t.ID.String()+"/"+p.ID.String(), http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PostHandler) Vote() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := chi.URLParam(r, "postID")
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
p, err := h.store.Post(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
dir := r.URL.Query().Get("dir")
|
||||
if dir == "up" {
|
||||
p.Votes++
|
||||
} else if dir == "down" {
|
||||
p.Votes--
|
||||
}
|
||||
|
||||
if err := h.store.UpdatePost(&p); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, r.Referer(), http.StatusFound)
|
||||
}
|
||||
}
|
103
web/thread_handler.go
Normal file
103
web/thread_handler.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"git.snrd.de/Spaenny/goddit"
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ThreadHandler struct {
|
||||
store goddit.Store
|
||||
}
|
||||
|
||||
func (h *ThreadHandler) List() http.HandlerFunc {
|
||||
type data struct {
|
||||
Threads []goddit.Thread
|
||||
}
|
||||
|
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/threads.html"))
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
tt, err := h.store.Threads()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
tmpl.Execute(w, data{Threads: tt})
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ThreadHandler) Create() http.HandlerFunc {
|
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/thread_create.html"))
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
tmpl.Execute(w, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ThreadHandler) Show() http.HandlerFunc {
|
||||
type data struct {
|
||||
Thread goddit.Thread
|
||||
Posts []goddit.Post
|
||||
}
|
||||
|
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/thread.html"))
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := chi.URLParam(r, "id")
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
t, err := h.store.Thread(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
pp, err := h.store.PostsByThread(t.ID)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
tmpl.Execute(w, data{Thread: t, Posts: pp})
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ThreadHandler) Store() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
title := r.FormValue("title")
|
||||
description := r.FormValue("description")
|
||||
|
||||
if err := h.store.CreateThread(&goddit.Thread{
|
||||
ID: uuid.New(),
|
||||
Title: title,
|
||||
Description: description,
|
||||
}); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/threads", http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ThreadHandler) Delete() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := chi.URLParam(r, "id")
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.store.DeleteThread(id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/threads", http.StatusFound)
|
||||
}
|
||||
}
|
Reference in a new issue