Update. Add svelte admin frontend
This commit is contained in:
100
internal/api/news.go
Normal file
100
internal/api/news.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"git.clustercockpit.org/moebiusband/go-http-skeleton/internal/repository"
|
||||
)
|
||||
|
||||
func createNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
req := repository.CreateNewsEntryParams{}
|
||||
if err := decode(r.Body, &req); err != nil {
|
||||
handleError(fmt.Errorf("parsing request body failed: %w", err), http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
repo := repository.GetRepository()
|
||||
err := repo.CreateNewsEntry(r.Context(), req)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func readNewsItems(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
items, err := repo.ListNews(r.Context())
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
slog.Debug("/api/news returned", "newscount", len(items))
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
bw := bufio.NewWriter(rw)
|
||||
defer bw.Flush()
|
||||
|
||||
if err := json.NewEncoder(bw).Encode(items); err != nil {
|
||||
handleError(err, http.StatusInternalServerError, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func readNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
item, err := repo.GetNewsEntry(r.Context(), id)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
bw := bufio.NewWriter(rw)
|
||||
defer bw.Flush()
|
||||
|
||||
if err := json.NewEncoder(bw).Encode(item); err != nil {
|
||||
handleError(err, http.StatusInternalServerError, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func updateNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
req := repository.UpdateNewsEntryParams{}
|
||||
if err := decode(r.Body, &req); err != nil {
|
||||
handleError(fmt.Errorf("parsing request body failed: %w", err), http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
repo := repository.GetRepository()
|
||||
err := repo.UpdateNewsEntry(r.Context(), req)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func deleteNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
err = repo.DeleteNewsEntry(r.Context(), id)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
@@ -1,15 +1,10 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"git.clustercockpit.org/moebiusband/go-http-skeleton/internal/repository"
|
||||
)
|
||||
|
||||
type ErrorResponse struct {
|
||||
@@ -24,6 +19,12 @@ func MountApiEndpoints(r *http.ServeMux) {
|
||||
r.HandleFunc("GET /api/news/{id}", readNewsItem)
|
||||
r.HandleFunc("PATCH /api/news/", updateNewsItem)
|
||||
r.HandleFunc("DELETE /api/news/{id}", deleteNewsItem)
|
||||
|
||||
r.HandleFunc("POST /api/retailers/", createRetailerItem)
|
||||
r.HandleFunc("GET /api/retailers/", readRetailerItems)
|
||||
r.HandleFunc("GET /api/retailers/{id}", readRetailerItem)
|
||||
r.HandleFunc("PATCH /api/retailers/", updateRetailerItem)
|
||||
r.HandleFunc("DELETE /api/retailers/{id}", deleteRetailerItem)
|
||||
}
|
||||
|
||||
func handleError(err error, statusCode int, rw http.ResponseWriter) {
|
||||
@@ -41,91 +42,3 @@ func decode(r io.Reader, val any) error {
|
||||
dec.DisallowUnknownFields()
|
||||
return dec.Decode(val)
|
||||
}
|
||||
|
||||
func createNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
req := repository.CreateNewsEntryParams{}
|
||||
if err := decode(r.Body, &req); err != nil {
|
||||
handleError(fmt.Errorf("parsing request body failed: %w", err), http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
repo := repository.GetRepository()
|
||||
err := repo.CreateNewsEntry(r.Context(), req)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func readNewsItems(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
items, err := repo.ListNews(r.Context())
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
slog.Debug("/api/news returned", "newscount", len(items))
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
bw := bufio.NewWriter(rw)
|
||||
defer bw.Flush()
|
||||
|
||||
if err := json.NewEncoder(bw).Encode(items); err != nil {
|
||||
handleError(err, http.StatusInternalServerError, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func readNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
item, err := repo.GetNewsEntry(r.Context(), id)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
bw := bufio.NewWriter(rw)
|
||||
defer bw.Flush()
|
||||
|
||||
if err := json.NewEncoder(bw).Encode(item); err != nil {
|
||||
handleError(err, http.StatusInternalServerError, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func updateNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
req := repository.UpdateNewsEntryParams{}
|
||||
if err := decode(r.Body, &req); err != nil {
|
||||
handleError(fmt.Errorf("parsing request body failed: %w", err), http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
repo := repository.GetRepository()
|
||||
err := repo.UpdateNewsEntry(r.Context(), req)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func deleteNewsItem(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
err = repo.DeleteNewsEntry(r.Context(), id)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
100
internal/api/retailer.go
Normal file
100
internal/api/retailer.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"git.clustercockpit.org/moebiusband/go-http-skeleton/internal/repository"
|
||||
)
|
||||
|
||||
func createRetailerItem(rw http.ResponseWriter, r *http.Request) {
|
||||
req := repository.CreateNewsEntryParams{}
|
||||
if err := decode(r.Body, &req); err != nil {
|
||||
handleError(fmt.Errorf("parsing request body failed: %w", err), http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
repo := repository.GetRepository()
|
||||
err := repo.CreateNewsEntry(r.Context(), req)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func readRetailerItems(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
items, err := repo.ListRetailers(r.Context())
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
slog.Debug("/api/retailers returned", "count", len(items))
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
bw := bufio.NewWriter(rw)
|
||||
defer bw.Flush()
|
||||
|
||||
if err := json.NewEncoder(bw).Encode(items); err != nil {
|
||||
handleError(err, http.StatusInternalServerError, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func readRetailerItem(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
item, err := repo.GetNewsEntry(r.Context(), id)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
rw.Header().Add("Content-Type", "application/json")
|
||||
bw := bufio.NewWriter(rw)
|
||||
defer bw.Flush()
|
||||
|
||||
if err := json.NewEncoder(bw).Encode(item); err != nil {
|
||||
handleError(err, http.StatusInternalServerError, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func updateRetailerItem(rw http.ResponseWriter, r *http.Request) {
|
||||
req := repository.UpdateNewsEntryParams{}
|
||||
if err := decode(r.Body, &req); err != nil {
|
||||
handleError(fmt.Errorf("parsing request body failed: %w", err), http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
repo := repository.GetRepository()
|
||||
err := repo.UpdateNewsEntry(r.Context(), req)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func deleteRetailerItem(rw http.ResponseWriter, r *http.Request) {
|
||||
repo := repository.GetRepository()
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
|
||||
err = repo.DeleteNewsEntry(r.Context(), id)
|
||||
if err != nil {
|
||||
handleError(err, http.StatusBadRequest, rw)
|
||||
return
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@@ -13,11 +14,12 @@ func AdminHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
tpl := template.Must(template.ParseFS(web.Templates, "templates/admin.html", "templates/base.html"))
|
||||
viteFragment, err := vite.HTMLFragment(vite.Config{
|
||||
FS: web.StaticAssets,
|
||||
FS: web.DistFS(),
|
||||
IsDev: false,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, "Error instantiating vite fragment", http.StatusInternalServerError)
|
||||
msg := fmt.Errorf("error instantiating vite fragment: %v", err)
|
||||
http.Error(w, msg.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user