mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-08-17 10:56:24 -07:00
Add thread attributes manage page
This commit is contained in:
parent
39fdb320c9
commit
0f0c9362eb
7 changed files with 161 additions and 23 deletions
|
@ -100,11 +100,10 @@ func GetBoardDirFromPostID(postID int) (string, error) {
|
|||
return boardURI, err
|
||||
}
|
||||
|
||||
// GetBoardFromID returns the board corresponding to a given id
|
||||
func GetBoardFromID(id int) (*Board, error) {
|
||||
const query = selectBoardsBaseSQL + "WHERE DBPREFIXboards.id = ?"
|
||||
func getBoardBase(where string, whereParameters []interface{}) (*Board, error) {
|
||||
query := selectBoardsBaseSQL + where
|
||||
board := new(Board)
|
||||
err := QueryRowSQL(query, interfaceSlice(id), interfaceSlice(
|
||||
err := QueryRowSQL(query, whereParameters, interfaceSlice(
|
||||
&board.ID, &board.SectionID, &board.URI, &board.Dir, &board.NavbarPosition, &board.Title, &board.Subtitle,
|
||||
&board.Description, &board.MaxFilesize, &board.MaxThreads, &board.DefaultStyle, &board.Locked,
|
||||
&board.CreatedAt, &board.AnonymousName, &board.ForceAnonymous, &board.AutosageAfter, &board.NoImagesAfter,
|
||||
|
@ -114,6 +113,23 @@ func GetBoardFromID(id int) (*Board, error) {
|
|||
return board, err
|
||||
}
|
||||
|
||||
// GetBoardFromID returns the board corresponding to a given id
|
||||
func GetBoardFromID(id int) (*Board, error) {
|
||||
return getBoardBase("WHERE DBPREFIXboards.id = ?", interfaceSlice(id))
|
||||
}
|
||||
|
||||
// GetBoardFromDir returns the board corresponding to a given dir
|
||||
func GetBoardFromDir(dir string) (*Board, error) {
|
||||
return getBoardBase("WHERE DBPREFIXboards.dir = ?", interfaceSlice(dir))
|
||||
}
|
||||
|
||||
// GetIDFromDir returns the id of the board with the given dir value
|
||||
func GetBoardIDFromDir(dir string) (id int, err error) {
|
||||
const query = `SELECT id FROM DBPREFIXboards WHERE dir = ?`
|
||||
err = QueryRowSQL(query, interfaceSlice(dir), interfaceSlice(&id))
|
||||
return id, err
|
||||
}
|
||||
|
||||
// GetBoardURIs gets a list of all existing board URIs
|
||||
func GetBoardURIs() (URIS []string, err error) {
|
||||
const sql = `SELECT uri FROM DBPREFIXboards`
|
||||
|
|
|
@ -86,6 +86,25 @@ func GetTopPostInThread(postID int) (int, error) {
|
|||
return id, err
|
||||
}
|
||||
|
||||
func GetTopPostIDsInThreadIDs(threads ...interface{}) ([]int, error) {
|
||||
params := createArrayPlaceholder(threads)
|
||||
query := `SELECT id FROM DBPREFIXposts WHERE thread_id in ` + params
|
||||
rows, err := QuerySQL(query, threads...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var ids []int
|
||||
for rows.Next() {
|
||||
var id int
|
||||
if err = rows.Scan(&id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func GetThreadTopPost(threadID int) (*Post, error) {
|
||||
const query = selectPostsBaseSQL + "WHERE thread_id = ? AND is_top_post = TRUE LIMIT 1"
|
||||
post := new(Post)
|
||||
|
|
|
@ -81,10 +81,11 @@ func GetThreadsWithBoardID(boardID int, onlyNotDeleted bool) ([]Thread, error) {
|
|||
var thread Thread
|
||||
if err = rows.Scan(
|
||||
&thread.ID, &thread.BoardID, &thread.Locked, &thread.Stickied, &thread.Anchored,
|
||||
&thread.Cyclical, &thread.LastBump,
|
||||
&thread.Cyclical, &thread.LastBump, &thread.DeletedAt, &thread.IsDeleted,
|
||||
); err != nil {
|
||||
return threads, err
|
||||
}
|
||||
threads = append(threads, thread)
|
||||
}
|
||||
return threads, nil
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ var (
|
|||
ManageAppeals *template.Template
|
||||
ManageBans *template.Template
|
||||
ManageBoards *template.Template
|
||||
ManageThreadAttrs *template.Template
|
||||
ManageSections *template.Template
|
||||
ManageConfig *template.Template
|
||||
ManageDashboard *template.Template
|
||||
|
@ -154,6 +155,12 @@ func templateLoading(t string, buildAll bool) error {
|
|||
return templateError("manage_boards.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "managethreadattrs" {
|
||||
ManageThreadAttrs, err = LoadTemplate("manage_threadattrs.html")
|
||||
if err != nil {
|
||||
return templateError("manage_threadattrs.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "managesections" {
|
||||
ManageSections, err = LoadTemplate("manage_sections.html")
|
||||
if err != nil {
|
||||
|
|
|
@ -741,6 +741,78 @@ var actions = []Action{
|
|||
outputStr += staffBuffer.String()
|
||||
return outputStr, nil
|
||||
}},
|
||||
{
|
||||
ID: "threadattrs",
|
||||
Title: "View/Update Thread Attributes",
|
||||
Permissions: ModPerms,
|
||||
JSONoutput: OptionalJSON,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv, errEv *zerolog.Event) (output interface{}, err error) {
|
||||
boardDir := request.FormValue("board")
|
||||
attrBuffer := bytes.NewBufferString("")
|
||||
if boardDir == "" {
|
||||
if wantsJSON {
|
||||
return nil, errors.New(`missing required field "board"`)
|
||||
}
|
||||
if err = serverutil.MinifyTemplate(gctemplates.ManageThreadAttrs, map[string]interface{}{
|
||||
"action": "threadattrs",
|
||||
"boards": gcsql.AllBoards,
|
||||
}, attrBuffer, "text/html"); err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return "", err
|
||||
}
|
||||
return attrBuffer.String(), nil
|
||||
}
|
||||
errEv.Str("boardDir", boardDir)
|
||||
boardID, err := gcsql.GetBoardIDFromDir(boardDir)
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return "", err
|
||||
}
|
||||
|
||||
var updateID int
|
||||
for name, val := range request.Form {
|
||||
if len(val) > 0 && val[0] == "Update attributes" {
|
||||
if _, err = fmt.Sscanf(name, "update-%d", &updateID); err != nil {
|
||||
return "", fmt.Errorf("invalid input name %q: %s", name, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
threads, err := gcsql.GetThreadsWithBoardID(boardID, true)
|
||||
var threadIDs []interface{}
|
||||
for _, thread := range threads {
|
||||
threadIDs = append(threadIDs, thread.ID)
|
||||
}
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Int("boardID", boardID).Send()
|
||||
return "", err
|
||||
}
|
||||
if wantsJSON {
|
||||
return threads, nil
|
||||
}
|
||||
board := gcsql.Board{
|
||||
ID: boardID,
|
||||
Dir: boardDir,
|
||||
}
|
||||
|
||||
opIDs, err := gcsql.GetTopPostIDsInThreadIDs(threadIDs...)
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return "", err
|
||||
}
|
||||
if err = serverutil.MinifyTemplate(gctemplates.ManageThreadAttrs, map[string]interface{}{
|
||||
"action": "threadattrs",
|
||||
"boards": gcsql.AllBoards,
|
||||
"board": board,
|
||||
"threads": threads,
|
||||
"opIDs": opIDs,
|
||||
}, attrBuffer, "text/html"); err != nil {
|
||||
errEv.Err(err).Caller().Send()
|
||||
return "", err
|
||||
}
|
||||
return attrBuffer.String(), nil
|
||||
}},
|
||||
{
|
||||
ID: "login",
|
||||
Title: "Login",
|
||||
|
@ -1192,22 +1264,6 @@ var actions = []Action{
|
|||
}
|
||||
return postInfo, nil
|
||||
}},
|
||||
// {
|
||||
// may end up deleting this
|
||||
// ID: "tempposts",
|
||||
// Title: "Temporary posts lists",
|
||||
// Permissions: AdminPerms,
|
||||
// Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
|
||||
// outputStr := ""
|
||||
// if len(gcsql.TempPosts) == 0 {
|
||||
// outputStr += "No temporary posts"
|
||||
// return
|
||||
// }
|
||||
// for p, post := range gcsql.TempPosts {
|
||||
// outputStr += fmt.Sprintf("Post[%d]: %#v<br />", p, post)
|
||||
// }
|
||||
// return outputStr, nil
|
||||
// }},
|
||||
{
|
||||
ID: "wordfilters",
|
||||
Title: "Wordfilters",
|
||||
|
|
|
@ -86,7 +86,7 @@ func CallManageFunction(writer http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
|
||||
if staff.Rank < action.Permissions {
|
||||
writer.WriteHeader(403)
|
||||
writer.WriteHeader(http.StatusForbidden)
|
||||
errEv.
|
||||
Int("rank", staff.Rank).
|
||||
Int("requiredRank", action.Permissions).
|
||||
|
@ -107,7 +107,7 @@ func CallManageFunction(writer http.ResponseWriter, request *http.Request) {
|
|||
output, err = action.Callback(writer, request, staff, wantsJSON, infoEv, errEv)
|
||||
}
|
||||
if err != nil {
|
||||
// writer.WriteHeader(500)
|
||||
writer.WriteHeader(http.StatusInternalServerError)
|
||||
serveError(writer, "actionerror", actionID, err.Error(), wantsJSON || (action.JSONoutput == AlwaysJSON))
|
||||
return
|
||||
}
|
||||
|
|
39
templates/manage_threadattrs.html
Normal file
39
templates/manage_threadattrs.html
Normal file
|
@ -0,0 +1,39 @@
|
|||
<form method="GET" action="{{webPath "manage" $.action}}" class="staff-form">
|
||||
{{with $.boards -}}
|
||||
<select name="board">
|
||||
{{range $_, $board := $.boards}}
|
||||
<option value="{{$board.Dir}}" {{with $.board}}{{if eq $.board.Dir $board.Dir}}selected="selected"{{end}}{{end}}>/{{$board.Dir}}/ - {{$board.Title}}</option>
|
||||
{{else}}
|
||||
<i>No boards</i>
|
||||
{{end}}
|
||||
</select>
|
||||
<input type="submit" name="show-threads" value="Show threads" /><br />
|
||||
{{else}}
|
||||
<i>No boards</i>
|
||||
{{end}}
|
||||
{{with $.board}}
|
||||
Threads on /{{.Dir}}/ (board ID is {{.ID}})<br/>
|
||||
{{if (lt (len $.threads) 1)}}
|
||||
<i>No threads on </i>
|
||||
{{else -}}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Thread ID</th><th>OP</th><th>Locked</th><th>Stickied</th><th>Anchored</th><th>Cyclical</th>
|
||||
</tr>
|
||||
{{- range $t, $thread := $.threads}}
|
||||
<tr>
|
||||
{{- with $opIDstr := (print (index $.opIDs $t)) -}}
|
||||
<td>{{$thread.ID}}</td>
|
||||
<td><a href="{{webPath $.board.Dir "res" $opIDstr}}.html">>>/{{$.board.Dir}}/{{$opIDstr}}</a></td>
|
||||
<td><input type="checkbox" name="locked" {{if $thread.Locked}}checked="checked"{{end}} />{{$thread.Locked}}</td>
|
||||
<td><input type="checkbox" name="stickied" {{if $thread.Stickied}}checked="checked"{{end}} />{{$thread.Stickied}}</td>
|
||||
<td><input type="checkbox" name="anchored" {{if $thread.Anchored}}checked="checked"{{end}} />{{$thread.Anchored}}</td>
|
||||
<td><input type="checkbox" name="cyclical" {{if $thread.Cyclical}}checked="checked"{{end}} />{{$thread.Cyclical}}</td>
|
||||
<td><input type="submit" name="update-{{$thread.ID}}" value="Update attributes"></td>
|
||||
{{- end}}
|
||||
</tr>
|
||||
{{end -}}
|
||||
</table>
|
||||
{{- end}}
|
||||
{{end}}
|
||||
</form>
|
Loading…
Add table
Add a link
Reference in a new issue