implemented draft publishing and removed New Posts link/capability

main
Brian Picciano 2 years ago
parent 33a81f73e1
commit f365b09757
  1. 4
      srv/src/http/api.go
  2. 20
      srv/src/http/drafts.go
  3. 67
      srv/src/http/posts.go
  4. 20
      srv/src/http/tpl/edit-post.html
  5. 6
      srv/src/http/tpl/posts.html

@ -202,7 +202,7 @@ func (a *api) blogHandler() http.Handler {
mux.Handle("/posts/", http.StripPrefix("/posts", mux.Handle("/posts/", http.StripPrefix("/posts",
apiutil.MethodMux(map[string]http.Handler{ apiutil.MethodMux(map[string]http.Handler{
"GET": a.renderPostHandler(), "GET": a.renderPostHandler(),
"POST": a.postPostHandler(false), "POST": a.postPostHandler(),
"DELETE": a.deletePostHandler(false), "DELETE": a.deletePostHandler(false),
"PREVIEW": a.previewPostHandler(), "PREVIEW": a.previewPostHandler(),
}), }),
@ -223,7 +223,7 @@ func (a *api) blogHandler() http.Handler {
apiutil.MethodMux(map[string]http.Handler{ apiutil.MethodMux(map[string]http.Handler{
"GET": a.renderDraftPostHandler(), "GET": a.renderDraftPostHandler(),
"POST": a.postPostHandler(true), "POST": a.postDraftPostHandler(),
"DELETE": a.deletePostHandler(true), "DELETE": a.deletePostHandler(true),
"PREVIEW": a.previewPostHandler(), "PREVIEW": a.previewPostHandler(),
}), }),

@ -108,3 +108,23 @@ func (a *api) renderDraftPostsIndexHandler() http.Handler {
executeTemplate(rw, r, tpl, tplPayload) executeTemplate(rw, r, tpl, tplPayload)
}) })
} }
func (a *api) postDraftPostHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
p, err := postFromPostReq(r)
if err != nil {
apiutil.BadRequest(rw, r, err)
return
}
if err := a.params.PostDraftStore.Set(p); err != nil {
apiutil.InternalServerError(
rw, r, fmt.Errorf("storing post with id %q: %w", p.ID, err),
)
return
}
a.executeRedirectTpl(rw, r, a.draftURL(p.ID, false)+"?edit")
})
}

@ -2,6 +2,7 @@ package http
import ( import (
"bytes" "bytes"
"context"
"errors" "errors"
"fmt" "fmt"
"html/template" "html/template"
@ -16,6 +17,7 @@ import (
"github.com/gomarkdown/markdown/parser" "github.com/gomarkdown/markdown/parser"
"github.com/mediocregopher/blog.mediocregopher.com/srv/http/apiutil" "github.com/mediocregopher/blog.mediocregopher.com/srv/http/apiutil"
"github.com/mediocregopher/blog.mediocregopher.com/srv/post" "github.com/mediocregopher/blog.mediocregopher.com/srv/post"
"github.com/mediocregopher/mediocre-go-lib/v2/mctx"
) )
func (a *api) parsePostBody(post post.Post) (*txttpl.Template, error) { func (a *api) parsePostBody(post post.Post) (*txttpl.Template, error) {
@ -248,6 +250,10 @@ func (a *api) renderEditPostHandler(isDraft bool) http.Handler {
) )
return return
} }
} else if !isDraft {
http.Error(rw, "Post ID required in URL", 400)
return
} }
tags, err := a.params.PostStore.GetTags() tags, err := a.params.PostStore.GetTags()
@ -296,49 +302,54 @@ func postFromPostReq(r *http.Request) (post.Post, error) {
return p, nil return p, nil
} }
func (a *api) postPostHandler(isDraft bool) http.Handler { func (a *api) storeAndPublishPost(ctx context.Context, p post.Post) error {
first, err := a.params.PostStore.Set(p, time.Now())
if err != nil {
return fmt.Errorf("storing post with id %q: %w", p.ID, err)
}
if !first {
return nil
}
a.params.Logger.Info(ctx, "publishing blog post to mailing list")
urlStr := a.postURL(p.ID, true)
if err := a.params.MailingList.Publish(p.Title, urlStr); err != nil {
return fmt.Errorf("publishing post to mailing list: %w", err)
}
if err := a.params.PostDraftStore.Delete(p.ID); err != nil {
return fmt.Errorf("deleting draft: %w", err)
}
return nil
}
func (a *api) postPostHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
p, err := postFromPostReq(r) p, err := postFromPostReq(r)
if err != nil { if err != nil {
apiutil.BadRequest(rw, r, err) apiutil.BadRequest(rw, r, err)
return return
} }
var first bool ctx = mctx.Annotate(ctx, "postID", p.ID)
if isDraft { if err := a.storeAndPublishPost(ctx, p); err != nil {
err = a.params.PostDraftStore.Set(p)
} else {
first, err = a.params.PostStore.Set(p, time.Now())
}
if err != nil {
apiutil.InternalServerError( apiutil.InternalServerError(
rw, r, fmt.Errorf("storing post with id %q: %w", p.ID, err), rw, r, fmt.Errorf("storing/publishing post with id %q: %w", p.ID, err),
) )
return return
} }
if !isDraft && first { a.executeRedirectTpl(rw, r, a.postURL(p.ID, false))
a.params.Logger.Info(r.Context(), "publishing blog post to mailing list")
urlStr := a.postURL(p.ID, true)
if err := a.params.MailingList.Publish(p.Title, urlStr); err != nil {
apiutil.InternalServerError(
rw, r, fmt.Errorf("publishing post with id %q: %w", p.ID, err),
)
return
}
}
if isDraft {
a.executeRedirectTpl(rw, r, a.draftURL(p.ID, false)+"?edit")
} else {
a.executeRedirectTpl(rw, r, a.postURL(p.ID, false)+"?edit")
}
}) })
} }

@ -90,6 +90,7 @@
</p> </p>
<p> <p>
<input <input
type="submit" type="submit"
value="Preview" value="Preview"
@ -99,8 +100,23 @@
{{ if .Payload.IsDraft }} {{ if .Payload.IsDraft }}
<input type="submit" value="Save" formaction="{{ BlogURL "drafts/" }}" /> <input type="submit" value="Save" formaction="{{ BlogURL "drafts/" }}" />
{{ else if eq .Payload.Post.ID "" }}
<input type="submit" value="Publish" formaction="{{ BlogURL "posts/" }}" />
<script>
function confirmPublish(event) {
if (!confirm("Are you sure you're ready to publish?"))
event.preventDefault();
}
</script>
<input
type="submit"
value="Publish"
formaction="{{ BlogURL "posts/" }}"
onclick="confirmPublish(event)"
/>
{{ else }} {{ else }}
<input type="submit" value="Update" formaction="{{ BlogURL "posts/" }}" /> <input type="submit" value="Update" formaction="{{ BlogURL "posts/" }}" />
{{ end }} {{ end }}

@ -2,12 +2,6 @@
<h1>Posts</h1> <h1>Posts</h1>
<p>
<a href="{{ BlogURL "posts/" }}?edit">
New Post
</a>
</p>
{{ if ge .Payload.PrevPage 0 }} {{ if ge .Payload.PrevPage 0 }}
<p> <p>
<a href="?p={{ .Payload.PrevPage}}">&lt; &lt; Previous Page</a> <a href="?p={{ .Payload.PrevPage}}">&lt; &lt; Previous Page</a>

Loading…
Cancel
Save