M TODO => TODO +0 -1
@@ 7,7 7,6 @@ links on home and thread list should go to the post
Login/Reigster:
finish up oauth integration
admin/mod ability to delete / edit posts
-Edit save should return to post
proper page titles
ts hover to show full TS + Timestamp into a template snippet
Notifications (Including integration with PWA / browser API)
M thread.go => thread.go +2 -2
@@ 51,12 51,12 @@ func getThreads(forumID, page int) ([]Thread, error) {
return threads, nil
}
-func threadPin(threadid int, pinned bool) error {
+func setThreadPin(threadid int, pinned bool) error {
_, err := stmtThreadPin.Exec(pinned, threadid)
return err
}
-func threadLock(threadid int, locked bool) error {
+func setThreadLock(threadid int, locked bool) error {
_, err := stmtThreadLock.Exec(locked, threadid)
return err
}
M views/forum.html => views/forum.html +17 -1
@@ 13,8 13,20 @@
<td>
{{ if .Locked }} {{ template "lock.svg" }} {{ end }}
{{ if .Pinned }} {{ template "pin.svg" }} {{ end }}
- <a class="title-link" href="/f/general/{{.ID}}">{{.Title}}</a><br>
+ <div class="flex-between">
+ <div>
+ <a class="title-link" href="/f/{{$.ForumSlug}}/{{.ID}}">{{.Title}}</a><br>
by <a href="/user/{{.Author.ID}}">{{.Author.Username}}</a> <span class="text-alt">{{ timeago .Created }}</span>
+ </div>
+ {{ if $.User.Role.ModLevel }}
+ <div>
+ <form method="POST" action="/f/{{$.ForumSlug}}/{{.ID}}/lock"><button class="link-button" id="submit">Lock</button></form>
+ {{ if not .Pinned }}
+ <form method="POST" action="/f/{{$.ForumSlug}}/{{.ID}}/pin"><button class="link-button" id="submit">Pin</button></form>
+ {{ end }}
+ </div>
+ </div>
+ {{ end }}
</td>
<td style="text-align:center;">{{.Replies}}</td>
<td>
@@ 28,7 40,11 @@
</tr>
{{ end }}
</table>
+{{ $pages := pageArr .ItemCount }}
+{{ $length := len $pages }}
+{{ if ne $length 1 }}
<div class="body-footer">
{{ template "pagelist.html" . }}
</div>
+{{ end }}
{{ template "footer.html" . }}
M views/style.css => views/style.css +5 -0
@@ 112,6 112,11 @@ body {
border-bottom: 1px solid var(--border);
}
+.flex-between {
+ justify-content: space-between;
+ display: flex;
+ flex-direction: row;
+}
.body-header {
display: flex;
justify-content: space-between;
M web.go => web.go +36 -0
@@ 93,6 93,7 @@ func forumPage(w http.ResponseWriter, r *http.Request) {
return
}
tmpl["ForumID"] = fid
+ tmpl["ForumSlug"] = r.PathValue("forum")
tmpl["Threads"] = threads
// pagination
tmpl["Page"] = page
@@ 530,6 531,36 @@ func doCreateForum(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/control", http.StatusSeeOther)
}
+func doLockThread(w http.ResponseWriter, r *http.Request) {
+ threadID, err := strconv.Atoi(r.PathValue("tid"))
+ if err != nil {
+ serverError(w, r, err)
+ return
+ }
+ err = setThreadLock(threadID, true)
+ if err != nil {
+ serverError(w, r, err)
+ return
+ }
+ // TODO paginate redirect
+ http.Redirect(w, r, "/f/"+r.PathValue("forum"), http.StatusSeeOther)
+}
+
+func doPinThread(w http.ResponseWriter, r *http.Request) {
+ threadID, err := strconv.Atoi(r.PathValue("tid"))
+ if err != nil {
+ serverError(w, r, err)
+ return
+ }
+ err = setThreadPin(threadID, true)
+ if err != nil {
+ serverError(w, r, err)
+ return
+ }
+ // TODO paginate redirect
+ http.Redirect(w, r, "/f/"+r.PathValue("forum"), http.StatusSeeOther)
+}
+
// placeholder
func dummy(w http.ResponseWriter, r *http.Request) {
}
@@ 604,6 635,11 @@ func serve() {
r.HandleFunc("POST /user/{userid}/change-password", dummy)
})
+ r.Group(func(r chi.Router) {
+ r.Use(Mod)
+ r.HandleFunc("POST /f/{forum}/{tid}/pin", doPinThread)
+ r.HandleFunc("POST /f/{forum}/{tid}/lock", doLockThread)
+ })
// admin functions
// TODO admin auth
r.Group(func(r chi.Router) {