Thread Moderator Buttons: Pin and Lock
* The bottoms of threads have moderator buttons now, to easily Pin or Unpin the thread (for Owners + Admins) or to Lock/Unlock the thread (all moderators).
This commit is contained in:
parent
90d0d10ee5
commit
85fd6ac5a2
|
@ -170,6 +170,11 @@ func AddEdit() http.HandlerFunc {
|
|||
forum.Private,
|
||||
))
|
||||
|
||||
// If this is a Community forum, subscribe the owner to it immediately.
|
||||
if forum.Category == "" {
|
||||
models.CreateForumMembership(currentUser, forum)
|
||||
}
|
||||
|
||||
return
|
||||
} else {
|
||||
session.FlashError(w, r, "Error creating the forum: %s", err)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"code.nonshy.com/nonshy/website/pkg/config"
|
||||
"code.nonshy.com/nonshy/website/pkg/log"
|
||||
"code.nonshy.com/nonshy/website/pkg/models"
|
||||
"code.nonshy.com/nonshy/website/pkg/session"
|
||||
|
@ -138,3 +139,91 @@ func ManageModerators() http.HandlerFunc {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ModerateThread endpoint - perform a mod action like pinning or locking a thread.
|
||||
func ModerateThread() http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Query params.
|
||||
var (
|
||||
threadID, err = strconv.Atoi(r.PathValue("id"))
|
||||
intent = r.PostFormValue("intent")
|
||||
nextURL = fmt.Sprintf("/forum/thread/%d", threadID)
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
session.FlashError(w, r, "Invalid thread ID.")
|
||||
templates.Redirect(w, nextURL)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the current user.
|
||||
currentUser, err := session.CurrentUser(r)
|
||||
if err != nil {
|
||||
session.FlashError(w, r, "Couldn't get current user: %s", err)
|
||||
templates.Redirect(w, "/")
|
||||
return
|
||||
}
|
||||
|
||||
// Get this thread.
|
||||
thread, err := models.GetThread(uint64(threadID))
|
||||
if err != nil {
|
||||
templates.NotFoundPage(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Get its forum.
|
||||
forum, err := models.GetForum(thread.ForumID)
|
||||
if err != nil {
|
||||
templates.NotFoundPage(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// User must at least be able to moderate.
|
||||
if !forum.CanBeModeratedBy(currentUser) {
|
||||
templates.ForbiddenPage(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Does the user have Ownership level access (including privileged admins)
|
||||
var isOwner = forum.OwnerID == currentUser.ID || currentUser.HasAdminScope(config.ScopeForumAdmin)
|
||||
|
||||
/****
|
||||
* Moderator level permissions.
|
||||
***/
|
||||
switch intent {
|
||||
case "lock":
|
||||
thread.NoReply = true
|
||||
session.Flash(w, r, "This thread has been locked and will not be accepting any new replies.")
|
||||
case "unlock":
|
||||
thread.NoReply = false
|
||||
session.Flash(w, r, "This thread has been unlocked and can accept new replies again.")
|
||||
default:
|
||||
if !isOwner {
|
||||
// End of the road.
|
||||
templates.ForbiddenPage(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/****
|
||||
* Owner + Admin level permissions.
|
||||
***/
|
||||
switch intent {
|
||||
case "pin":
|
||||
thread.Pinned = true
|
||||
session.Flash(w, r, "This thread is now pinned to the top of the forum.")
|
||||
case "unpin":
|
||||
thread.Pinned = false
|
||||
session.Flash(w, r, "This thread will no longer be pinned to the top of the forum.")
|
||||
default:
|
||||
session.FlashError(w, r, "Unknown moderator action.")
|
||||
}
|
||||
|
||||
// Save changes to the thread.
|
||||
if err := thread.Save(); err != nil {
|
||||
session.FlashError(w, r, "Error saving thread: %s", err)
|
||||
}
|
||||
|
||||
templates.Redirect(w, nextURL)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ func New() http.Handler {
|
|||
mux.Handle("GET /forum", middleware.CertRequired(forum.Landing()))
|
||||
mux.Handle("/forum/post", middleware.CertRequired(forum.NewPost()))
|
||||
mux.Handle("GET /forum/thread/{id}", middleware.CertRequired(forum.Thread()))
|
||||
mux.Handle("POST /forum/thread/{id}/moderate", middleware.CertRequired(forum.ModerateThread()))
|
||||
mux.Handle("GET /forum/explore", middleware.CertRequired(forum.Explore()))
|
||||
mux.Handle("GET /forum/newest", middleware.CertRequired(forum.Newest()))
|
||||
mux.Handle("GET /forum/search", middleware.CertRequired(forum.Search()))
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
{{else}}
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/nonshy-prefers-dark.css?build={{.BuildHash}}">
|
||||
{{end}}
|
||||
<link rel="stylesheet" href="/static/fontawesome-free-6.1.2-web/css/all.css">
|
||||
<link rel="stylesheet" href="/static/fontawesome-free-6.6.0-web/css/all.css">
|
||||
<link rel="stylesheet" href="/static/css/theme.css?build={{.BuildHash}}">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<title>{{template "title" .}} - {{ .Title }}</title>
|
||||
|
|
|
@ -368,6 +368,54 @@
|
|||
{{SimplePager .Pager}}
|
||||
</div>
|
||||
|
||||
<!-- Moderator controls -->
|
||||
{{if .CanModerate}}
|
||||
<div class="block p-2">
|
||||
<form method="POST" action="/forum/thread/{{.Thread.ID}}/moderate">
|
||||
{{InputCSRF}}
|
||||
|
||||
<div class="field has-addons">
|
||||
<p class="control">
|
||||
<button type="button" class="button is-small has-text-info"
|
||||
onclick="alert('Note: These are your moderator controls for this forum thread.')">
|
||||
<span class="icon is-small">
|
||||
<i class="fa fa-user-tie"></i>
|
||||
</span>
|
||||
</button>
|
||||
</p>
|
||||
|
||||
<!-- Pin/Unpin -->
|
||||
{{if or (eq .Forum.OwnerID .CurrentUser.ID) (.CurrentUser.HasAdminScope "admin.forum.manage")}}
|
||||
<p class="control">
|
||||
<button type="submit" class="button is-small has-text-success"
|
||||
name="intent"
|
||||
value="{{if .Thread.Pinned}}un{{end}}pin"
|
||||
onclick="return confirm('Are you sure you want to {{if .Thread.Pinned}}un{{end}}pin this thread to the top of the forum?')">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-thumbtack{{if .Thread.Pinned}}-slash{{end}}"></i>
|
||||
</span>
|
||||
<span>{{if .Thread.Pinned}}Unp{{else}}P{{end}}in thread</span>
|
||||
</button>
|
||||
</p>
|
||||
{{end}}
|
||||
|
||||
<!-- Lock/Unlock -->
|
||||
<p class="control">
|
||||
<button type="submit" class="button is-small has-text-warning"
|
||||
name="intent"
|
||||
value="{{if .Thread.NoReply}}un{{end}}lock"
|
||||
onclick="return confirm('Do you want to {{if .Thread.NoReply}}UN{{end}}LOCK this thread?\n\nA locked thread will not accept any new replies.')">
|
||||
<span class="icon is-small">
|
||||
<i class="fa fa-ban"></i>
|
||||
</span>
|
||||
<span>{{if .Thread.NoReply}}Unl{{else}}L{{end}}ock replies</span>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .Thread.NoReply}}
|
||||
<div class="block notification is-warning is-light">
|
||||
<i class="fa fa-ban pr-2"></i>
|
||||
|
|
Loading…
Reference in New Issue
Block a user