Editor page!
This commit is contained in:
@@ -1,29 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/CalebQ42/darkstorm-server/internal/backend"
|
||||
"github.com/CalebQ42/darkstorm-server/internal/blog"
|
||||
)
|
||||
|
||||
//go:embed embed
|
||||
var editorFS embed.FS
|
||||
// //go:embed embed
|
||||
// var editorFS embed.FS
|
||||
|
||||
const loginPage = `
|
||||
const (
|
||||
loginPage = `
|
||||
<form id="loginForm" hx-post="/login" hx-target="#formResult">
|
||||
<label for="username">Username:</label>
|
||||
<input name="username" id="usernameInput" onkeydown="return event.key != 'Enter';"></input>
|
||||
<input name="username" id="usernameInput" onkeydown="return event.key != 'Enter';" type="text"></input>
|
||||
<label for="password">Password:</label>
|
||||
<input name="password" type="password" id="passwordInput"></input>
|
||||
<div id="formResult"></div>
|
||||
<button id="loginButton" type="submit">Login</button>
|
||||
</form>
|
||||
<button class="formButton" type="submit">Login</button>
|
||||
</form>`
|
||||
editorPage = `
|
||||
<p>
|
||||
<label for="blog" style="margin-right:10px">Blog:</label>
|
||||
<select id="blogSelect"
|
||||
name='blog'
|
||||
hx-get='/editor/edit'
|
||||
hx-target='#editor'>
|
||||
<option value=""></option>
|
||||
<option value='new'>New Blog</option>
|
||||
{{ range $blog := . }}
|
||||
<option value='{{$blog.ID}}'>{{$blog.Title}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</p>
|
||||
<div id="editor" hx-on::after-swap="blogEditorResize()"><p>Select a blog!</p></div>
|
||||
`
|
||||
editorForm = `
|
||||
<form id="editorForm" hx-post="/editor/post">
|
||||
<input name="id" type="hidden" value="{{.ID}}"></input>
|
||||
<p>
|
||||
<label for="static" style="margin-right:10px">Static Page:</label><input type="checkbox" name="static"{{if .StaticPage}} checked {{end}}/>
|
||||
<span class="vertical-seperator"></span>
|
||||
<label for="draft" style="margin-right:10px">Draft:</label><input type="checkbox" name="draft"{{if .Draft}} checked {{end}}/>
|
||||
</p>
|
||||
<label for="title">Title</label>
|
||||
<input id="titleInput" name="title" value="{{.Title}}" type="text"/>
|
||||
<textarea id="blogEditor" name="blog" oninput="blogEditorResize()">{{.RawBlog}}</textarea>
|
||||
<p style="margin-right:0px;">
|
||||
<button class="formButton" type="submit" style="margin-right:0px;">{{if eq .ID ""}}Create{{else}}Update{{end}}</button>
|
||||
<button class="formButton" type="submit" style="margin-right:0px;"
|
||||
hx-get="/editor/edit"
|
||||
hx-include="#blogSelect"
|
||||
hx-target="#editor"
|
||||
hx-confirm="Undo all your changes??">
|
||||
Cancel
|
||||
</button>
|
||||
<p>
|
||||
</form>`
|
||||
)
|
||||
|
||||
func loginPageRequest(w http.ResponseWriter, r *http.Request) {
|
||||
sendContent(w, r, loginPage, "", "")
|
||||
@@ -62,36 +102,80 @@ func trueLoginRequest(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func editorRequest(w http.ResponseWriter, r *http.Request) {
|
||||
if !verifyEditorCookie(r) {
|
||||
editorRedirect(w, r, "/login")
|
||||
return
|
||||
}
|
||||
tmpl, err := template.New("page").Parse(editorPage)
|
||||
if err != nil {
|
||||
log.Println("error parsing editor template:", err)
|
||||
sendContent(w, r, "ERROR", "", "")
|
||||
return
|
||||
}
|
||||
blogs, _ := blogApp.LatestBlogs(r.Context(), 0)
|
||||
buf := new(bytes.Buffer)
|
||||
err = tmpl.Execute(buf, blogs)
|
||||
if err != nil {
|
||||
log.Println("error executing editor page template:", err)
|
||||
sendContent(w, r, "ERROR", "", "")
|
||||
return
|
||||
}
|
||||
sendContent(w, r, buf.String(), "", "")
|
||||
}
|
||||
|
||||
func editorEdit(w http.ResponseWriter, r *http.Request) {
|
||||
if !verifyEditorCookie(r) {
|
||||
editorRedirect(w, r, "/login")
|
||||
return
|
||||
}
|
||||
tmpl, err := template.New("editor").Parse(editorForm)
|
||||
if err != nil {
|
||||
log.Println("error parsing editor template:", err)
|
||||
sendContent(w, r, "ERROR", "", "")
|
||||
return
|
||||
}
|
||||
var bl *blog.Blog
|
||||
blogID := r.URL.Query().Get("blog")
|
||||
if blogID == "" {
|
||||
sendContent(w, r, "<p>Select a blog!</p>", "", "")
|
||||
return
|
||||
}
|
||||
if blogID == "new" {
|
||||
bl = &blog.Blog{}
|
||||
} else {
|
||||
bl, err = blogApp.Blog(r.Context(), r.URL.Query().Get("blog"))
|
||||
if err != nil {
|
||||
log.Println("error getting blog for editor:", err)
|
||||
sendContent(w, r, "ERROR", "", "")
|
||||
return
|
||||
}
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
err = tmpl.Execute(buf, bl)
|
||||
if err != nil {
|
||||
log.Println("error executing editor template:", err)
|
||||
sendContent(w, r, "ERROR", "", "")
|
||||
return
|
||||
}
|
||||
sendContent(w, r, buf.String(), "", "")
|
||||
}
|
||||
|
||||
func verifyEditorCookie(r *http.Request) bool {
|
||||
authCookie, err := r.Cookie("blogAuthToken")
|
||||
if err != nil {
|
||||
if err != http.ErrNoCookie {
|
||||
log.Println("error getting auth cookie:", err)
|
||||
}
|
||||
editorRedirect(w, r, "/login")
|
||||
return
|
||||
return false
|
||||
}
|
||||
usr, err := back.VerifyUser(r.Context(), authCookie.Value)
|
||||
_, err = back.VerifyUser(r.Context(), authCookie.Value)
|
||||
if err != nil {
|
||||
if err != backend.ErrTokenUnauthorized {
|
||||
log.Println("error authorizing JWT token:", err)
|
||||
}
|
||||
editorRedirect(w, r, "/login")
|
||||
return
|
||||
return false
|
||||
}
|
||||
page, err := editorFS.Open("embed/editor.html")
|
||||
defer page.Close()
|
||||
if err != nil {
|
||||
log.Println("error getting editor.html:", err)
|
||||
sendContent(w, r, "error getting page", "", "")
|
||||
return
|
||||
}
|
||||
_, err = io.ReadAll(page)
|
||||
if err != nil {
|
||||
log.Println("error reading editor.html:", err)
|
||||
sendContent(w, r, "error getting page", "", "")
|
||||
return
|
||||
}
|
||||
sendContent(w, r, "<p>Hello there, "+usr.Username+"</p>", "", "")
|
||||
return true
|
||||
}
|
||||
|
||||
func editorRedirect(w http.ResponseWriter, r *http.Request, path string) {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<form id="editorForm" hx-post="https://api.darkstorm.tech/">
|
||||
<p><input type="checkbox" id="draft"></input><label for="draft">Draft</label></p>
|
||||
<label for="title">Title</label>
|
||||
<input name="title" value="{{.Title}}"></input>
|
||||
<textarea name="blog"></textarea>
|
||||
<button></button>
|
||||
</form>
|
||||
@@ -28,7 +28,8 @@ type Blog struct {
|
||||
Author string `json:"author" bson:"author"`
|
||||
Favicon string `json:"favicon" bson:"favicon"`
|
||||
Title string `json:"title" bson:"title"`
|
||||
Blog string `json:"blog" bson:"blog"`
|
||||
RawBlog string `json:"blog" bson:"blog"`
|
||||
HTMLBlog string `json:"-" bson:"-"`
|
||||
StaticPage bool `json:"staticPage" bson:"staticPage"`
|
||||
Draft bool `json:"draft" bson:"draft"`
|
||||
CreateTime int64 `json:"createTime" bson:"createTime"`
|
||||
@@ -37,7 +38,7 @@ type Blog struct {
|
||||
|
||||
func (b *Blog) HTMX(blogApp *BlogApp, ctx context.Context) string {
|
||||
if b.StaticPage {
|
||||
return b.Blog
|
||||
return b.RawBlog
|
||||
}
|
||||
out := fmt.Sprintf(blogTitle, b.ID, b.ID, b.Title)
|
||||
auth, err := blogApp.GetAuthor(ctx, b)
|
||||
@@ -52,7 +53,7 @@ func (b *Blog) HTMX(blogApp *BlogApp, ctx context.Context) string {
|
||||
} else {
|
||||
out += fmt.Sprintf(blogCreate, cTime)
|
||||
}
|
||||
out += fmt.Sprintf(blogMain, b.Blog)
|
||||
out += fmt.Sprintf(blogMain, b.HTMLBlog)
|
||||
if err == nil {
|
||||
out += "<h2 class='blog-author-info'>About the author:</h2>" + auth.HTML()
|
||||
}
|
||||
@@ -61,7 +62,7 @@ func (b *Blog) HTMX(blogApp *BlogApp, ctx context.Context) string {
|
||||
|
||||
func (b *BlogApp) ConvertBlog(blog *Blog) {
|
||||
if !blog.StaticPage {
|
||||
blog.Blog = b.conv.HTMLConvert(blog.Blog)
|
||||
blog.HTMLBlog = b.conv.HTMLConvert(blog.RawBlog)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -147,13 +147,16 @@ func setupWebsite(mux *http.ServeMux) {
|
||||
url, _ := url.Parse("https://localhost:30000")
|
||||
mux.Handle("rpg.darkstorm.tech/", httputil.NewSingleHostReverseProxy(url))
|
||||
}
|
||||
mux.HandleFunc("/", mainHandle)
|
||||
mux.HandleFunc("GET /files/{w...}", filesRequest)
|
||||
mux.HandleFunc("GET /portfolio", portfolioRequest)
|
||||
mux.HandleFunc("GET /list", blogListHandle)
|
||||
|
||||
// Editor stuff
|
||||
mux.HandleFunc("GET /login", loginPageRequest)
|
||||
mux.HandleFunc("GET /editor/", editorRequest)
|
||||
mux.HandleFunc("GET /editor/edit", editorEdit)
|
||||
mux.HandleFunc("POST /login", trueLoginRequest)
|
||||
mux.HandleFunc("/", mainHandle)
|
||||
}
|
||||
|
||||
func mainHandle(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user