summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gmi/tpl.go2
-rw-r--r--src/http/assets.go20
-rw-r--r--src/http/drafts.go40
-rw-r--r--src/http/posts.go167
-rw-r--r--src/http/tpl.go2
-rw-r--r--src/http/tpl/draft-posts-manage.html26
-rw-r--r--src/http/tpl/post-assets-manage.html6
-rw-r--r--src/http/tpl/post-edit.html34
-rw-r--r--src/http/tpl/posts-manage.html14
-rw-r--r--src/http/tpl/posts.html15
-rw-r--r--src/render/methods.go51
11 files changed, 121 insertions, 256 deletions
diff --git a/src/gmi/tpl.go b/src/gmi/tpl.go
index 8ffa6bc..f6c1754 100644
--- a/src/gmi/tpl.go
+++ b/src/gmi/tpl.go
@@ -177,6 +177,8 @@ func (a *api) tplHandler() (gemini.Handler, error) {
a.params.PublicURL,
a.params.HTTPGeminiGatewayURL,
a.params.PostStore,
+ nil, // asset.Store, not supported by gemini endpoint
+ nil, // post.DraftStore, not supported by gemini endpoint
preprocessFuncs,
))
diff --git a/src/http/assets.go b/src/http/assets.go
index 5a47152..8c5ac7e 100644
--- a/src/http/assets.go
+++ b/src/http/assets.go
@@ -14,27 +14,9 @@ import (
)
func (a *api) managePostAssetsHandler() http.Handler {
-
tpl := a.mustParseBasedTpl("post-assets-manage.html")
-
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
-
- ids, err := a.params.PostAssetStore.List()
-
- if err != nil {
- apiutil.InternalServerError(
- rw, r, fmt.Errorf("getting list of asset ids: %w", err),
- )
- return
- }
-
- tplPayload := struct {
- IDs []string
- }{
- IDs: ids,
- }
-
- a.executeTemplate(rw, r, tpl, tplPayload)
+ a.executeTemplate(rw, r, tpl, nil)
})
}
diff --git a/src/http/drafts.go b/src/http/drafts.go
index b0550ce..8f17eec 100644
--- a/src/http/drafts.go
+++ b/src/http/drafts.go
@@ -5,50 +5,12 @@ import (
"net/http"
"dev.mediocregopher.com/mediocre-blog.git/src/http/apiutil"
- "dev.mediocregopher.com/mediocre-blog.git/src/post"
)
func (a *api) manageDraftPostsHandler() http.Handler {
-
tpl := a.mustParseBasedTpl("draft-posts-manage.html")
- const pageCount = 20
-
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
-
- page, err := apiutil.StrToInt(r.FormValue("p"), 0)
- if err != nil {
- apiutil.BadRequest(
- rw, r, fmt.Errorf("invalid page number: %w", err),
- )
- return
- }
-
- posts, hasMore, err := a.params.PostDraftStore.Get(page, pageCount)
- if err != nil {
- apiutil.InternalServerError(
- rw, r, fmt.Errorf("fetching page %d of posts: %w", page, err),
- )
- return
- }
-
- tplPayload := struct {
- Posts []post.Post
- PrevPage, NextPage int
- }{
- Posts: posts,
- PrevPage: -1,
- NextPage: -1,
- }
-
- if page > 0 {
- tplPayload.PrevPage = page - 1
- }
-
- if hasMore {
- tplPayload.NextPage = page + 1
- }
-
- a.executeTemplate(rw, r, tpl, tplPayload)
+ a.executeTemplate(rw, r, tpl, nil)
})
}
diff --git a/src/http/posts.go b/src/http/posts.go
index 939b811..14224f2 100644
--- a/src/http/posts.go
+++ b/src/http/posts.go
@@ -5,7 +5,6 @@ import (
"context"
"errors"
"fmt"
- "html/template"
"net/http"
"path/filepath"
"strings"
@@ -58,12 +57,6 @@ func (a *api) postPreprocessFuncImage(args ...string) (string, error) {
return buf.String(), nil
}
-type postTplPayload struct {
- post.StoredPost
- SeriesPrevious, SeriesNext *post.StoredPost
- Body template.HTML
-}
-
func (a *api) postPreprocessFuncs() post.PreprocessFunctions {
return post.PreprocessFunctions{
BlogURL: func(path string) string {
@@ -90,76 +83,17 @@ func (a *api) postPreprocessFuncs() post.PreprocessFunctions {
}
func (a *api) getPostsHandler() http.Handler {
-
- tpl := a.mustParseBasedTpl("posts.html")
- getPostHandler := a.getPostHandler()
- const pageCount = 20
+ var (
+ tpl = a.mustParseBasedTpl("posts.html")
+ getPostHandler = a.getPostHandler()
+ )
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
-
- id := filepath.Base(r.URL.Path)
-
- if id != "/" {
+ if id := filepath.Base(r.URL.Path); id != "/" {
getPostHandler.ServeHTTP(rw, r)
return
}
-
- page, err := apiutil.StrToInt(r.FormValue("p"), 0)
- if err != nil {
- apiutil.BadRequest(
- rw, r, fmt.Errorf("invalid page number: %w", err),
- )
- return
- }
-
- tag := r.FormValue("tag")
-
- var (
- posts []post.StoredPost
- hasMore bool
- )
-
- if tag == "" {
- posts, hasMore, err = a.params.PostStore.Get(page, pageCount)
- } else {
- posts, err = a.params.PostStore.GetByTag(tag)
- }
-
- if err != nil {
- apiutil.InternalServerError(
- rw, r, fmt.Errorf("fetching page %d of posts: %w", page, err),
- )
- return
- }
-
- tags, err := a.params.PostStore.GetTags()
- if err != nil {
- apiutil.InternalServerError(
- rw, r, fmt.Errorf("fething tags: %w", err),
- )
- return
- }
-
- tplPayload := struct {
- Posts []post.StoredPost
- PrevPage, NextPage int
- Tags []string
- }{
- Posts: posts,
- PrevPage: -1,
- NextPage: -1,
- Tags: tags,
- }
-
- if page > 0 {
- tplPayload.PrevPage = page - 1
- }
-
- if hasMore {
- tplPayload.NextPage = page + 1
- }
-
- a.executeTemplate(rw, r, tpl, tplPayload)
+ a.executeTemplate(rw, r, tpl, nil)
})
}
@@ -173,105 +107,22 @@ func (a *api) getPostHandler() http.Handler {
}
func (a *api) managePostsHandler() http.Handler {
-
tpl := a.mustParseBasedTpl("posts-manage.html")
- const pageCount = 20
-
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
-
- page, err := apiutil.StrToInt(r.FormValue("p"), 0)
- if err != nil {
- apiutil.BadRequest(
- rw, r, fmt.Errorf("invalid page number: %w", err),
- )
- return
- }
-
- posts, hasMore, err := a.params.PostStore.Get(page, pageCount)
- if err != nil {
- apiutil.InternalServerError(
- rw, r, fmt.Errorf("fetching page %d of posts: %w", page, err),
- )
- return
- }
-
- tplPayload := struct {
- Posts []post.StoredPost
- PrevPage, NextPage int
- }{
- Posts: posts,
- PrevPage: -1,
- NextPage: -1,
- }
-
- if page > 0 {
- tplPayload.PrevPage = page - 1
- }
-
- if hasMore {
- tplPayload.NextPage = page + 1
- }
-
- a.executeTemplate(rw, r, tpl, tplPayload)
+ a.executeTemplate(rw, r, tpl, nil)
})
}
func (a *api) editPostHandler(isDraft bool) http.Handler {
-
tpl := a.mustParseBasedTpl("post-edit.html")
-
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
-
- id := filepath.Base(r.URL.Path)
-
- if id == "/" && !isDraft {
- http.Error(rw, "Post id required", 400)
- return
- }
-
- var (
- storedPost post.StoredPost
- err error
- )
-
- if id != "/" {
-
- if isDraft {
- storedPost.Post, err = a.params.PostDraftStore.GetByID(id)
- } else {
- storedPost, err = a.params.PostStore.GetByID(id)
- }
-
- if errors.Is(err, post.ErrPostNotFound) {
- http.Error(rw, "Post not found", 404)
- return
- } else if err != nil {
- apiutil.InternalServerError(
- rw, r, fmt.Errorf("fetching post with id %q: %w", id, err),
- )
- return
- }
- }
-
- tags, err := a.params.PostStore.GetTags()
- if err != nil {
- apiutil.InternalServerError(rw, r, fmt.Errorf("fetching tags: %w", err))
- return
- }
-
- tplPayload := struct {
- Post post.StoredPost
- Tags []string
+ a.executeTemplate(rw, r, tpl, struct {
IsDraft bool
Formats []post.Format
}{
- Post: storedPost,
- Tags: tags,
IsDraft: isDraft,
Formats: post.Formats,
- }
-
- a.executeTemplate(rw, r, tpl, tplPayload)
+ })
})
}
diff --git a/src/http/tpl.go b/src/http/tpl.go
index c623f2e..afd4c8e 100644
--- a/src/http/tpl.go
+++ b/src/http/tpl.go
@@ -151,6 +151,8 @@ func (a *api) newTPLData(r *http.Request, payload interface{}) tplData {
a.params.PublicURL,
a.params.GeminiGatewayURL,
a.params.PostStore,
+ a.params.PostAssetStore,
+ a.params.PostDraftStore,
a.postPreprocessFuncs(),
),
Payload: payload,
diff --git a/src/http/tpl/draft-posts-manage.html b/src/http/tpl/draft-posts-manage.html
index 5454f24..b1b4362 100644
--- a/src/http/tpl/draft-posts-manage.html
+++ b/src/http/tpl/draft-posts-manage.html
@@ -1,5 +1,15 @@
{{ define "body" }}
+ {{ $page := .GetQueryIntValue "p" 0 -}}
+ {{ $getPostsRes := .GetDraftPosts $page 20 -}}
+
+ <script>
+ function confirmDelete(event) {
+ if (!confirm("Are you sure you want to delete this draft?"))
+ event.preventDefault();
+ }
+ </script>
+
<p>
<a href="{{ BlogURL "admin" }}">Back to Admin</a>
</p>
@@ -10,15 +20,15 @@
<a href="{{ BlogURL "drafts" }}?method=edit">New Draft</a>
</p>
- {{ if ge .Payload.PrevPage 0 }}
+ {{ if gt $page 0 }}
<p>
- <a href="?method=manage&p={{ .Payload.PrevPage}}">&lt; &lt; Previous Page</a>
+ <a href="?method=manage&p={{ .Add $page -1 }}">&lt; &lt; Previous Page</a>
</p>
{{ end }}
<table>
- {{ range .Payload.Posts }}
+ {{ range $getPostsRes.Posts }}
<tr>
<td>{{ .Title }}</td>
<td>
@@ -31,7 +41,11 @@
action="{{ DraftURL .ID }}?method=delete"
method="POST"
>
- <input type="submit" value="Delete" />
+ <input
+ type="submit"
+ value="Delete"
+ onclick="confirmDelete(event)"
+ />
</form>
</td>
</tr>
@@ -39,9 +53,9 @@
</table>
- {{ if ge .Payload.NextPage 0 }}
+ {{ if $getPostsRes.HasMore }}
<p>
- <a href="?method=manage&p={{ .Payload.NextPage}}">Next Page &gt; &gt;</a>
+ <a href="?method=manage&p={{ .Add $page 1 }}">Next Page &gt; &gt;</a>
</p>
{{ end }}
diff --git a/src/http/tpl/post-assets-manage.html b/src/http/tpl/post-assets-manage.html
index f21717a..a0b0da0 100644
--- a/src/http/tpl/post-assets-manage.html
+++ b/src/http/tpl/post-assets-manage.html
@@ -1,5 +1,7 @@
{{ define "body" }}
+{{ $assetIDs := .GetPostAssetIDs }}
+
<p>
<a href="{{ BlogURL "admin" }}">Back to Admin</a>
</p>
@@ -27,13 +29,13 @@
</div>
</form>
-{{ if gt (len .Payload.IDs) 0 }}
+{{ if $assetIDs }}
<h2>Existing Assets</h2>
<table>
- {{ range .Payload.IDs }}
+ {{ range $assetIDs }}
<tr>
<td><a href="{{ AssetURL . }}">{{ . }}</a></td>
<td>
diff --git a/src/http/tpl/post-edit.html b/src/http/tpl/post-edit.html
index c66b60a..28dcd0e 100644
--- a/src/http/tpl/post-edit.html
+++ b/src/http/tpl/post-edit.html
@@ -1,5 +1,9 @@
{{ define "body" }}
+{{ $tags := .GetTags }}
+
+{{ $post := (or (and .Payload.IsDraft .GetThisDraftPost) .GetThisPost) }}
+
<p>
{{ if .Payload.IsDraft }}
<a href="{{ BlogURL "drafts?method=manage" }}">
@@ -21,19 +25,19 @@
Unique ID
</td>
<td>
- {{ if eq .Payload.Post.ID "" }}
+ {{ if eq $post.ID "" }}
<input
name="id"
type="text"
required
placeholder="e.g. how-to-fly-a-kite"
- value="{{ .Payload.Post.ID }}" />
+ value="{{ $post.ID }}" />
{{ else if .Payload.IsDraft }}
- {{ .Payload.Post.ID }}
- <input name="id" type="hidden" value="{{ .Payload.Post.ID }}" />
+ {{ $post.ID }}
+ <input name="id" type="hidden" value="{{ $post.ID }}" />
{{ else }}
- <a href="{{ PostURL .Payload.Post.ID }}">{{ .Payload.Post.ID }}</a>
- <input name="id" type="hidden" value="{{ .Payload.Post.ID }}" />
+ <a href="{{ PostURL $post.ID }}">{{ $post.ID }}</a>
+ <input name="id" type="hidden" value="{{ $post.ID }}" />
{{ end }}
</td>
</tr>
@@ -45,15 +49,15 @@
name="tags"
type="text"
required
- value="{{- range $i, $tag := .Payload.Post.Tags -}}
+ value="{{- range $i, $tag := $post.Tags -}}
{{- if ne $i 0 }} {{ end }}{{ $tag -}}
{{- end -}}
"/>
- {{ if gt (len .Payload.Tags) 0 }}
+ {{ if $tags }}
<em>
Existing tags:
- {{ range $i, $tag := .Payload.Tags }}
+ {{ range $i, $tag := $tags }}
{{ if ne $i 0 }} {{ end }}{{ $tag }}
{{ end }}
</em>
@@ -67,7 +71,7 @@
<input
name="series"
type="text"
- value="{{ .Payload.Post.Series }}" />
+ value="{{ $post.Series }}" />
</td>
</tr>
@@ -78,7 +82,7 @@
name="title"
type="text"
required
- value="{{ .Payload.Post.Title }}" />
+ value="{{ $post.Title }}" />
</td>
</tr>
@@ -88,7 +92,7 @@
<input
name="description"
type="text"
- value="{{ .Payload.Post.Description }}" />
+ value="{{ $post.Description }}" />
</td>
</tr>
@@ -98,7 +102,7 @@
<select name="format" required>
<option value=""></option>
- {{ $format := .Payload.Post.Format }}
+ {{ $format := $post.Format }}
{{ range .Payload.Formats -}}
<option
{{- if eq . $format }}
@@ -122,7 +126,7 @@
placeholder="Post body"
style="width:100%;height: 75vh;"
>
- {{- .Payload.Post.Body -}}
+ {{- $post.Body -}}
</textarea>
</p>
@@ -131,7 +135,7 @@
<input
type="submit"
value="Preview"
- formaction="{{ BlogURL "posts/" }}{{ .Payload.Post.ID }}?method=preview"
+ formaction="{{ BlogURL "posts/" }}{{ $post.ID }}?method=preview"
formtarget="_blank"
/>
diff --git a/src/http/tpl/posts-manage.html b/src/http/tpl/posts-manage.html
index 96b30ca..f9adbc1 100644
--- a/src/http/tpl/posts-manage.html
+++ b/src/http/tpl/posts-manage.html
@@ -1,4 +1,8 @@
{{ define "body" }}
+
+ {{ $page := .GetQueryIntValue "p" 0 -}}
+ {{ $getPostsRes := .GetPosts $page 20 -}}
+
<script>
function confirmDelete(event) {
if (!confirm("Are you sure you want to delete this post?"))
@@ -12,9 +16,9 @@
<h1>Posts</h1>
- {{ if ge .Payload.PrevPage 0 }}
+ {{ if gt $page 0 }}
<p>
- <a href="?method=manage&p={{ .Payload.PrevPage}}">&lt; &lt; Previous Page</a>
+ <a href="?method=manage&p={{ .Add $page -1 }}">&lt; &lt; Previous Page</a>
</p>
{{ end }}
@@ -26,7 +30,7 @@
<col span="1" style="width: auto;">
</colgroup>
- {{ range .Payload.Posts }}
+ {{ range $getPostsRes.Posts }}
<tr>
<td>{{ .PublishedAt.Local.Format "2006-01-02 15:04:05 MST" }}</td>
<td><a href="{{ PostURL .ID }}">{{ .Title }}</a></td>
@@ -52,9 +56,9 @@
</table>
- {{ if ge .Payload.NextPage 0 }}
+ {{ if $getPostsRes.HasMore }}
<p>
- <a href="?method=manage&p={{ .Payload.NextPage}}">Next Page &gt; &gt;</a>
+ <a href="?method=manage&p={{ .Add $page 1 }}">Next Page &gt; &gt;</a>
</p>
{{ end }}
diff --git a/src/http/tpl/posts.html b/src/http/tpl/posts.html
index 0701459..2fa336d 100644
--- a/src/http/tpl/posts.html
+++ b/src/http/tpl/posts.html
@@ -1,8 +1,11 @@
{{ define "body" }}
- {{ if ge .Payload.PrevPage 0 }}
+ {{ $page := .GetQueryIntValue "p" 0 -}}
+ {{ $getPostsRes := .GetPosts $page 20 -}}
+
+ {{ if gt $page 0 }}
<p>
- <a href="?p={{ .Payload.PrevPage}}">&lt; &lt; Previous Page</a>
+ <a href="?p={{ .Add $page -1 }}">&lt; &lt; Previous Page</a>
</p>
{{ else }}
<p>
@@ -12,10 +15,10 @@
{{ end }}
<ul>
- {{ range .Payload.Posts }}
+ {{ range $getPostsRes.Posts }}
<li>
<strong><a href="{{ PostURL .ID }}">
- {{ DateTimeFormat .PublishedAt }} / {{ .Title }}
+ {{ .PublishedAt.Format "2006-01-02" }} - {{ .Title }}
</a></strong>
{{ if .Description }}
<br/><em>{{ .Description }}</em>
@@ -24,9 +27,9 @@
{{ end }}
</ul>
- {{ if ge .Payload.NextPage 0 }}
+ {{ if $getPostsRes.HasMore }}
<p>
- <a href="?p={{ .Payload.NextPage}}">Next Page &gt; &gt;</a>
+ <a href="?p={{ .Add $page 1 }}">Next Page &gt; &gt;</a>
</p>
{{ end }}
diff --git a/src/render/methods.go b/src/render/methods.go
index 6dd9332..5b2c0b1 100644
--- a/src/render/methods.go
+++ b/src/render/methods.go
@@ -13,6 +13,7 @@ import (
"dev.mediocregopher.com/mediocre-blog.git/src/gmi/gemtext"
"dev.mediocregopher.com/mediocre-blog.git/src/post"
+ "dev.mediocregopher.com/mediocre-blog.git/src/post/asset"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
@@ -37,6 +38,12 @@ type GetPostsRes struct {
HasMore bool
}
+// GetDraftPostsRes are the fields returned from the GetDraftPosts method.
+type GetDraftPostsRes struct {
+ Posts []post.Post
+ HasMore bool
+}
+
// GetPostSeriesNextPreviousRes are the fields returned from the
// GetPostSeriesNextPreviousRes method.
type GetPostSeriesNextPreviousRes struct {
@@ -51,9 +58,12 @@ type Methods struct {
publicURL *url.URL
geminiGatewayURL *url.URL
postStore post.Store
+ postAssetStore asset.Store
+ postDraftStore post.DraftStore
preprocessFuncs post.PreprocessFunctions
- thisPost *post.StoredPost // cache
+ thisPost *post.StoredPost // cache
+ thisDraftPost *post.Post // cache
}
// NewMethods initializes a Methods using its required dependencies.
@@ -63,6 +73,8 @@ func NewMethods(
publicURL *url.URL,
geminiGatewayURL *url.URL,
postStore post.Store,
+ postAssetStore asset.Store,
+ postDraftStore post.DraftStore,
preprocessFuncs post.PreprocessFunctions,
) *Methods {
return &Methods{
@@ -71,16 +83,32 @@ func NewMethods(
publicURL,
geminiGatewayURL,
postStore,
+ postAssetStore,
+ postDraftStore,
preprocessFuncs,
nil, // thisPost
+ nil, // thisDraftPost
}
}
+func (m *Methods) GetTags() ([]string, error) {
+ return m.postStore.GetTags()
+}
+
+func (m *Methods) GetPostAssetIDs() ([]string, error) {
+ return m.postAssetStore.List()
+}
+
func (m *Methods) GetPosts(page, count int) (GetPostsRes, error) {
posts, hasMore, err := m.postStore.Get(page, count)
return GetPostsRes{posts, hasMore}, err
}
+func (m *Methods) GetDraftPosts(page, count int) (GetDraftPostsRes, error) {
+ posts, hasMore, err := m.postDraftStore.Get(page, count)
+ return GetDraftPostsRes{posts, hasMore}, err
+}
+
func (m *Methods) GetThisPost() (p post.StoredPost, err error) {
if m.thisPost != nil {
return *m.thisPost, nil
@@ -100,12 +128,23 @@ func (m *Methods) GetThisPost() (p post.StoredPost, err error) {
return m.postStore.GetByID(id)
}
-func (m *Methods) GetPostByID(id string) (post.StoredPost, error) {
- p, err := m.postStore.GetByID(id)
- if err != nil {
- return post.StoredPost{}, fmt.Errorf("fetching post %q: %w", id, err)
+func (m *Methods) GetThisDraftPost() (p post.Post, err error) {
+ if m.thisPost != nil {
+ return *m.thisDraftPost, nil
}
- return p, nil
+
+ defer func() {
+ m.thisDraftPost = &p
+ }()
+
+ id := path.Base(m.url.Path)
+ if id == "/" {
+ // An empty draft is fine, in the context of editing
+ return
+ }
+
+ id = strings.TrimSuffix(id, path.Ext(id))
+ return m.postDraftStore.GetByID(id)
}
func (m *Methods) GetPostSeriesNextPrevious(