mirror of https://github.com/jlelse/GoBlog
Add editor to create, update or delete posts
This commit is contained in:
parent
366514699d
commit
eeb68dbba9
|
@ -0,0 +1,85 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
const editorPath = "/editor"
|
||||||
|
|
||||||
|
func serveEditor(w http.ResponseWriter, r *http.Request) {
|
||||||
|
render(w, templateEditor, &renderData{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func serveEditorPost(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if action := r.FormValue("editoraction"); action != "" {
|
||||||
|
if action == "loadupdate" {
|
||||||
|
parsedURL, err := url.Parse(r.FormValue("url"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
post, err := getPost(parsedURL.Path)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mf := post.toMfItem()
|
||||||
|
render(w, templateEditor, &renderData{
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"UpdatePostURL": parsedURL.String(),
|
||||||
|
"UpdatePostContent": mf.Properties.Content[0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
} else if action == "updatepost" {
|
||||||
|
urlValue := r.FormValue("url")
|
||||||
|
content := r.FormValue("content")
|
||||||
|
mf := map[string]interface{}{
|
||||||
|
"action": actionUpdate,
|
||||||
|
"url": urlValue,
|
||||||
|
"replace": map[string][]string{
|
||||||
|
"content": {
|
||||||
|
content,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
jsonBytes, err := json.Marshal(mf)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest(http.MethodPost, "", bytes.NewReader(jsonBytes))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.Header.Set(contentType, contentTypeJSON)
|
||||||
|
editorMicropubPost(w, req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http.Error(w, "unknown editoraction", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
editorMicropubPost(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func editorMicropubPost(w http.ResponseWriter, r *http.Request) {
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
addAllScopes(http.HandlerFunc(serveMicropubPost)).ServeHTTP(recorder, r)
|
||||||
|
result := recorder.Result()
|
||||||
|
if location := result.Header.Get("Location"); location != "" {
|
||||||
|
http.Redirect(w, r, result.Header.Get("Location"), http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result.StatusCode >= 200 && result.StatusCode <= 400 {
|
||||||
|
http.Redirect(w, r, editorPath, http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(result.StatusCode)
|
||||||
|
body, _ := ioutil.ReadAll(result.Body)
|
||||||
|
w.Write(body)
|
||||||
|
}
|
7
http.go
7
http.go
|
@ -106,6 +106,13 @@ func buildHandler() (http.Handler, error) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Editor
|
||||||
|
r.Route("/editor", func(mpRouter chi.Router) {
|
||||||
|
mpRouter.Use(authMiddleware)
|
||||||
|
mpRouter.Get("/", serveEditor)
|
||||||
|
mpRouter.Post("/", serveEditorPost)
|
||||||
|
})
|
||||||
|
|
||||||
// IndieAuth
|
// IndieAuth
|
||||||
r.Route("/indieauth", func(indieauthRouter chi.Router) {
|
r.Route("/indieauth", func(indieauthRouter chi.Router) {
|
||||||
indieauthRouter.Use(middleware.NoCache)
|
indieauthRouter.Use(middleware.NoCache)
|
||||||
|
|
|
@ -21,3 +21,10 @@ func checkIndieAuth(next http.Handler) http.Handler {
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addAllScopes(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
next.ServeHTTP(rw, r.WithContext(context.WithValue(r.Context(), "scope", "create update delete media")))
|
||||||
|
return
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -90,6 +90,8 @@ func (p *post) toMfItem() *microformatItem {
|
||||||
params["path"] = []string{p.Path}
|
params["path"] = []string{p.Path}
|
||||||
params["section"] = []string{p.Section}
|
params["section"] = []string{p.Section}
|
||||||
params["blog"] = []string{p.Blog}
|
params["blog"] = []string{p.Blog}
|
||||||
|
params["published"] = []string{p.Published}
|
||||||
|
params["updated"] = []string{p.Updated}
|
||||||
pb, _ := yaml.Marshal(p.Parameters)
|
pb, _ := yaml.Marshal(p.Parameters)
|
||||||
content := fmt.Sprintf("---\n%s---\n%s", string(pb), p.Content)
|
content := fmt.Sprintf("---\n%s---\n%s", string(pb), p.Content)
|
||||||
return µformatItem{
|
return µformatItem{
|
||||||
|
@ -185,8 +187,7 @@ func serveMicropubPost(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Add("Location", p.fullURL())
|
http.Redirect(w, r, p.fullURL(), http.StatusAccepted)
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +425,7 @@ func micropubDelete(w http.ResponseWriter, r *http.Request, u *url.URL) {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusNoContent)
|
http.Redirect(w, r, u.String(), http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,4 +558,5 @@ func micropubUpdate(w http.ResponseWriter, r *http.Request, u *url.URL, mf *micr
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
http.Redirect(w, r, p.fullURL(), http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,13 @@ func (p *post) checkPost() error {
|
||||||
if p.Blog == "" {
|
if p.Blog == "" {
|
||||||
p.Blog = appConfig.DefaultBlog
|
p.Blog = appConfig.DefaultBlog
|
||||||
}
|
}
|
||||||
|
if _, ok := appConfig.Blogs[p.Blog]; !ok {
|
||||||
|
return errors.New("blog doesn't exist")
|
||||||
|
}
|
||||||
|
// Check if section exists
|
||||||
|
if _, ok := appConfig.Blogs[p.Blog].Sections[p.Section]; p.Section != "" && !ok {
|
||||||
|
return errors.New("section doesn't exist")
|
||||||
|
}
|
||||||
// Check path
|
// Check path
|
||||||
p.Path = strings.TrimSuffix(p.Path, "/")
|
p.Path = strings.TrimSuffix(p.Path, "/")
|
||||||
if p.Path == "" {
|
if p.Path == "" {
|
||||||
|
|
|
@ -30,6 +30,7 @@ const templateTaxonomy = "taxonomy"
|
||||||
const templateSearch = "search"
|
const templateSearch = "search"
|
||||||
const templateSummary = "summary"
|
const templateSummary = "summary"
|
||||||
const templatePhotosSummary = "photosummary"
|
const templatePhotosSummary = "photosummary"
|
||||||
|
const templateEditor = "editor"
|
||||||
|
|
||||||
var templates map[string]*template.Template
|
var templates map[string]*template.Template
|
||||||
var templateFunctions template.FuncMap
|
var templateFunctions template.FuncMap
|
||||||
|
@ -229,6 +230,9 @@ func render(w http.ResponseWriter, template string, data *renderData) {
|
||||||
}
|
}
|
||||||
data.Blog = appConfig.Blogs[data.blogString]
|
data.Blog = appConfig.Blogs[data.blogString]
|
||||||
}
|
}
|
||||||
|
if data.Data == nil {
|
||||||
|
data.Data = map[string]interface{}{}
|
||||||
|
}
|
||||||
// We need to use a buffer here to enable minification
|
// We need to use a buffer here to enable minification
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
err := templates[template].ExecuteTemplate(&buffer, template, data)
|
err := templates[template].ExecuteTemplate(&buffer, template, data)
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
{{ define "title" }}
|
||||||
|
<title>{{ string .Blog.Lang "editor" }} - {{ .Blog.Title }}</title>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "main" }}
|
||||||
|
<main>
|
||||||
|
<h1>{{ string .Blog.Lang "editor" }}</h1>
|
||||||
|
<h2>{{ string .Blog.Lang "create" }}</h2>
|
||||||
|
<form class="fw-form p" method="post">
|
||||||
|
<input type="hidden" name="h" value="entry">
|
||||||
|
<textarea class="fw" name="content"></textarea>
|
||||||
|
<input class="fw" type="submit" value="{{ string .Blog.Lang "create" }}">
|
||||||
|
</form>
|
||||||
|
<h2>{{ string .Blog.Lang "update" }}</h2>
|
||||||
|
<form class="fw-form p" method="post">
|
||||||
|
{{ if .Data.UpdatePostURL }}
|
||||||
|
<input type="hidden" name="editoraction" value="updatepost">
|
||||||
|
<input type="hidden" name="url" value="{{ .Data.UpdatePostURL }}">
|
||||||
|
<textarea class="fw" name="content">{{ .Data.UpdatePostContent }}</textarea>
|
||||||
|
{{ else }}
|
||||||
|
<input type="hidden" name="editoraction" value="loadupdate">
|
||||||
|
<input class="fw" type="text" style="margin-bottom: 5px" name="url" placeholder="URL">
|
||||||
|
{{ end }}
|
||||||
|
<input class="fw" type="submit" value="{{ string .Blog.Lang "update" }}">
|
||||||
|
</form>
|
||||||
|
<h2>{{ string .Blog.Lang "delete" }}</h2>
|
||||||
|
<form class="fw-form p" method="post">
|
||||||
|
<input type="hidden" name="action" value="delete">
|
||||||
|
<input class="fw" type="text" style="margin-bottom: 5px" name="url" placeholder="URL">
|
||||||
|
<input class="fw" type="submit" value="{{ string .Blog.Lang "delete" }}">
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "editor" }}
|
||||||
|
{{ template "base" . }}
|
||||||
|
{{ end }}
|
|
@ -22,4 +22,7 @@ anoncomment: "You can also create an anonymous comment."
|
||||||
interactions: "Interactions"
|
interactions: "Interactions"
|
||||||
send: "Send"
|
send: "Send"
|
||||||
interactionslabel: "Have you published a response to this? Paste the URL here."
|
interactionslabel: "Have you published a response to this? Paste the URL here."
|
||||||
search: "Search"
|
search: "Search"
|
||||||
|
editor: "Editor"
|
||||||
|
create: "Create"
|
||||||
|
update: "Update"
|
Loading…
Reference in New Issue