summaryrefslogtreecommitdiff
path: root/srv/src
diff options
context:
space:
mode:
Diffstat (limited to 'srv/src')
-rw-r--r--srv/src/api/api.go4
-rw-r--r--srv/src/api/assets.go29
-rw-r--r--srv/src/api/posts.go37
-rw-r--r--srv/src/api/tpl.go8
-rw-r--r--srv/src/api/tpl/assets.html2
-rw-r--r--srv/src/api/tpl/index.html2
-rw-r--r--srv/src/api/tpl/post.html8
-rw-r--r--srv/src/api/tpl/posts.html61
-rw-r--r--srv/src/post/post.go6
9 files changed, 134 insertions, 23 deletions
diff --git a/srv/src/api/api.go b/srv/src/api/api.go
index ab2bca5..a6fc779 100644
--- a/srv/src/api/api.go
+++ b/srv/src/api/api.go
@@ -212,7 +212,9 @@ func (a *api) handler() http.Handler {
{
v2Mux := http.NewServeMux()
v2Mux.Handle("/follow.html", a.renderDumbTplHandler("follow.html"))
- v2Mux.Handle("/posts/", a.renderPostHandler())
+ v2Mux.Handle("/posts/", http.StripPrefix("/posts",
+ a.renderPostHandler(),
+ ))
v2Mux.Handle("/assets/", http.StripPrefix("/assets",
apiutil.MethodMux(map[string]http.Handler{
"GET": a.getPostAssetHandler(),
diff --git a/srv/src/api/assets.go b/srv/src/api/assets.go
index 7065ff6..c1cd75e 100644
--- a/srv/src/api/assets.go
+++ b/srv/src/api/assets.go
@@ -50,16 +50,41 @@ func resizeImage(out io.Writer, in io.Reader, maxWidth float64) error {
}
}
+func (a *api) renderPostAssetsIndexHandler() http.Handler {
+
+ tpl := a.mustParseBasedTpl("assets.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,
+ }
+
+ executeTemplate(rw, r, tpl, tplPayload)
+ })
+}
+
func (a *api) getPostAssetHandler() http.Handler {
- renderHandler := a.renderPostAssetsIndexHandler()
+ renderIndexHandler := a.renderPostAssetsIndexHandler()
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
id := filepath.Base(r.URL.Path)
if id == "/" {
- renderHandler.ServeHTTP(rw, r)
+ renderIndexHandler.ServeHTTP(rw, r)
return
}
diff --git a/srv/src/api/posts.go b/srv/src/api/posts.go
index 87806c7..68754a3 100644
--- a/srv/src/api/posts.go
+++ b/srv/src/api/posts.go
@@ -18,11 +18,17 @@ import (
func (a *api) renderPostHandler() http.Handler {
tpl := a.mustParseBasedTpl("post.html")
+ renderIndexHandler := a.renderPostsIndexHandler()
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
id := strings.TrimSuffix(filepath.Base(r.URL.Path), ".html")
+ if id == "/" {
+ renderIndexHandler.ServeHTTP(rw, r)
+ return
+ }
+
storedPost, err := a.params.PostStore.GetByID(id)
if errors.Is(err, post.ErrPostNotFound) {
@@ -88,25 +94,44 @@ func (a *api) renderPostHandler() http.Handler {
})
}
-func (a *api) renderPostAssetsIndexHandler() http.Handler {
+func (a *api) renderPostsIndexHandler() http.Handler {
- tpl := a.mustParseBasedTpl("assets.html")
+ tpl := a.mustParseBasedTpl("posts.html")
+ const pageCount = 20
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- ids, err := a.params.PostAssetStore.List()
+ 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.WithOrderDesc().Get(page, pageCount)
if err != nil {
apiutil.InternalServerError(
- rw, r, fmt.Errorf("getting list of asset ids: %w", err),
+ rw, r, fmt.Errorf("fetching page %d of posts: %w", page, err),
)
return
}
tplPayload := struct {
- IDs []string
+ Posts []post.StoredPost
+ PrevPage, NextPage int
}{
- IDs: ids,
+ Posts: posts,
+ PrevPage: -1,
+ NextPage: -1,
+ }
+
+ if page > 0 {
+ tplPayload.PrevPage = page - 1
+ }
+
+ if hasMore {
+ tplPayload.NextPage = page + 1
}
executeTemplate(rw, r, tpl, tplPayload)
diff --git a/srv/src/api/tpl.go b/srv/src/api/tpl.go
index 8d85de9..5e33bea 100644
--- a/srv/src/api/tpl.go
+++ b/srv/src/api/tpl.go
@@ -42,8 +42,12 @@ func (a *api) mustParseTpl(name string) *template.Template {
tpl := template.New("").Funcs(template.FuncMap{
"BlogURL": blogURL,
- "AssetURL": func(path string) string {
- path = filepath.Join("assets", path)
+ "AssetURL": func(id string) string {
+ path := filepath.Join("assets", id)
+ return blogURL(path)
+ },
+ "PostURL": func(id string) string {
+ path := filepath.Join("posts", id)
return blogURL(path)
},
})
diff --git a/srv/src/api/tpl/assets.html b/srv/src/api/tpl/assets.html
index b8d51a2..aa5e422 100644
--- a/srv/src/api/tpl/assets.html
+++ b/srv/src/api/tpl/assets.html
@@ -33,7 +33,7 @@
<td><a href="{{ AssetURL . }}" target="_blank">{{ . }}</a></td>
<td>
<form
- action="{{ BlogURL "assets/" }}{{ . }}?method=delete"
+ action="{{ AssetURL . }}?method=delete"
method="POST"
style="margin-bottom: 0;"
>
diff --git a/srv/src/api/tpl/index.html b/srv/src/api/tpl/index.html
index b634169..946a3e4 100644
--- a/srv/src/api/tpl/index.html
+++ b/srv/src/api/tpl/index.html
@@ -5,7 +5,7 @@
{{ range .Payload.Posts }}
<li>
<h2>
- <a href="posts/{{ .HTTPPath }}">{{ .Title }}</a>
+ <a href="{{ PostURL .ID }}">{{ .Title }}</a>
</h2>
<span>{{ .PublishedAt.Format "2006-01-02" }}</span>
{{ if not .LastUpdatedAt.IsZero }}
diff --git a/srv/src/api/tpl/post.html b/srv/src/api/tpl/post.html
index c5c3c96..fadab3c 100644
--- a/srv/src/api/tpl/post.html
+++ b/srv/src/api/tpl/post.html
@@ -19,10 +19,10 @@
<p class="light"><em>
This post is part of a series:<br/>
{{ if .Payload.SeriesPrevious }}
- Previously: <a href="{{ .Payload.SeriesPrevious.HTTPPath }}">{{ .Payload.SeriesPrevious.Title }}</a></br>
+ Previously: <a href="{{ PostURL .Payload.SeriesPrevious.ID }}">{{ .Payload.SeriesPrevious.Title }}</a></br>
{{ end }}
{{ if .Payload.SeriesNext }}
- Next: <a href="{{ .Payload.SeriesNext.HTTPPath }}">{{ .Payload.SeriesNext.Title }}</a></br>
+ Next: <a href="{{ PostURL .Payload.SeriesNext.ID }}">{{ .Payload.SeriesNext.Title }}</a></br>
{{ end }}
</em></p>
{{ end }}
@@ -35,10 +35,10 @@
<p class="light"><em>
If you liked this post, consider checking out other posts in the series:<br/>
{{ if .Payload.SeriesPrevious }}
- Previously: <a href="{{ .Payload.SeriesPrevious.HTTPPath }}">{{ .Payload.SeriesPrevious.Title }}</a></br>
+ Previously: <a href="{{ PostURL .Payload.SeriesPrevious.ID }}">{{ .Payload.SeriesPrevious.Title }}</a></br>
{{ end }}
{{ if .Payload.SeriesNext }}
- Next: <a href="{{ .Payload.SeriesNext.HTTPPath }}">{{ .Payload.SeriesNext.Title }}</a></br>
+ Next: <a href="{{ PostURL .Payload.SeriesNext.ID }}">{{ .Payload.SeriesNext.Title }}</a></br>
{{ end }}
</em></p>
{{ end }}
diff --git a/srv/src/api/tpl/posts.html b/srv/src/api/tpl/posts.html
new file mode 100644
index 0000000..e701f59
--- /dev/null
+++ b/srv/src/api/tpl/posts.html
@@ -0,0 +1,61 @@
+{{ define "posts-nextprev" }}
+
+ {{ if or (ge .Payload.PrevPage 0) (ge .Payload.NextPage 0) }}
+ <div id="page-turner">
+
+ {{ if ge .Payload.PrevPage 0 }}
+ <a style="float: left;" href="?p={{ .Payload.PrevPage}}">Newer</a>
+ {{ end }}
+
+ {{ if ge .Payload.NextPage 0 }}
+ <a style="float:right;" href="?p={{ .Payload.NextPage}}">Older</a>
+ {{ end }}
+
+ </div>
+ {{ end }}
+
+{{ end }}
+
+{{ define "body" }}
+
+ {{ $csrfFormInput := .CSRFFormInput }}
+
+
+ <p style="text-align: center;">
+ <a href="{{ BlogURL "posts/" }}?method=new">
+ <button>New Post</button>
+ </a>
+ </p>
+
+ {{ template "posts-nextprev" . }}
+
+ <table style="margin-top: 2rem;">
+
+ {{ range .Payload.Posts }}
+ <tr>
+ <td>{{ .PublishedAt }}</td>
+ <td><a href="{{ PostURL .ID }}" target="_blank">{{ .Title }}</a></td>
+ <td>
+ <a href="{{ PostURL .ID }}?method=edit">
+ <button>Edit</button>
+ </a>
+ </td>
+ <td>
+ <form
+ action="{{ PostURL .ID }}?method=delete"
+ method="POST"
+ >
+ {{ $csrfFormInput }}
+ <input type="submit" value="Delete" />
+ </form>
+ </td>
+ </tr>
+ {{ end }}
+
+ </table>
+
+ {{ template "posts-nextprev" . }}
+
+{{ end }}
+
+{{ template "base.html" . }}
diff --git a/srv/src/post/post.go b/srv/src/post/post.go
index 3eab9bc..766a543 100644
--- a/srv/src/post/post.go
+++ b/srv/src/post/post.go
@@ -36,12 +36,6 @@ type Post struct {
Body string
}
-// HTTPPath returns the relative URL path of the StoredPost, when querying it
-// over HTTP.
-func (p Post) HTTPPath() string {
- return fmt.Sprintf("%s.html", p.ID)
-}
-
// StoredPost is a Post which has been stored in a Store, and has been given
// some extra fields as a result.
type StoredPost struct {