mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-09-06 11:46:24 -07:00
Remove unused manage_config.html template and function, add manage_announcements.html
This commit is contained in:
parent
5fd9601cc1
commit
d5e614b664
10 changed files with 226 additions and 245 deletions
|
@ -1,21 +0,0 @@
|
|||
package gcsql
|
||||
|
||||
func GetAllAccouncements() ([]Announcement, error) {
|
||||
const query = `SELECT id, staff_id, subject, message, timestamp FROM DBPREFIXannouncements ORDER BY TIMESTAMP DESC`
|
||||
rows, err := QuerySQL(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var announcements []Announcement
|
||||
for rows.Next() {
|
||||
var announcement Announcement
|
||||
if err = rows.Scan(
|
||||
&announcement.ID, &announcement.StaffID, &announcement.Subject, &announcement.Message, &announcement.Timestamp,
|
||||
); err != nil {
|
||||
return announcements, err
|
||||
}
|
||||
announcements = append(announcements, announcement)
|
||||
}
|
||||
return announcements, nil
|
||||
}
|
|
@ -7,11 +7,11 @@ import (
|
|||
|
||||
// table: DBPREFIXannouncements
|
||||
type Announcement struct {
|
||||
ID uint `json:"no"` // sql: `id`
|
||||
StaffID string `json:"name"` // sql: `staff_id`
|
||||
Subject string `json:"sub"` // sql: `subject`
|
||||
Message string `json:"com"` // sql: `message`
|
||||
Timestamp time.Time `json:"-"` // sql: `timestamp`
|
||||
ID uint // sql: `id`
|
||||
StaffID uint // sql: `staff_id`
|
||||
Subject string // sql: `subject`
|
||||
Message string // sql: `message`
|
||||
Timestamp time.Time // sql: `timestamp`
|
||||
}
|
||||
|
||||
// table: DBPREFIXboard_staff
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"html"
|
||||
"html/template"
|
||||
"path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -250,16 +249,6 @@ var funcMap = template.FuncMap{
|
|||
}
|
||||
return loopArr
|
||||
},
|
||||
"generateConfigTable": func() template.HTML {
|
||||
siteCfg := config.GetSiteConfig()
|
||||
boardCfg := config.GetBoardConfig("")
|
||||
tableOut := `<table style="border-collapse: collapse;" id="config"><tr><th>Field name</th><th>Value</th><th>Type</th><th>Description</th></tr>`
|
||||
|
||||
tableOut += configTable(siteCfg) +
|
||||
configTable(boardCfg) +
|
||||
"</table>"
|
||||
return template.HTML(tableOut)
|
||||
},
|
||||
"isStyleDefault": func(style string) bool {
|
||||
return style == config.GetBoardConfig("").DefaultStyle
|
||||
},
|
||||
|
@ -267,61 +256,3 @@ var funcMap = template.FuncMap{
|
|||
return config.GetVersion().String()
|
||||
},
|
||||
}
|
||||
|
||||
func configTable(cfg interface{}) string {
|
||||
cVal := reflect.ValueOf(cfg)
|
||||
if cVal.Kind() == reflect.Ptr {
|
||||
cVal = cVal.Elem()
|
||||
}
|
||||
var tableOut string
|
||||
if cVal.Kind() != reflect.Struct {
|
||||
return ""
|
||||
}
|
||||
cType := cVal.Type()
|
||||
numFields := cVal.NumField()
|
||||
|
||||
for f := 0; f < numFields; f++ {
|
||||
field := cType.Field(f)
|
||||
name := field.Name
|
||||
|
||||
fVal := reflect.Indirect(cVal).FieldByName(name)
|
||||
fKind := fVal.Kind()
|
||||
// interf := cVal.Field(f).Interface()
|
||||
switch fKind {
|
||||
case reflect.Int:
|
||||
tableOut += `<input name="` + name + `" type="number" value="` + html.EscapeString(fmt.Sprintf("%v", f)) + `" class="config-text"/>`
|
||||
case reflect.String:
|
||||
tableOut += `<input name="` + name + `" type="text" value="` + html.EscapeString(fmt.Sprintf("%v", f)) + `" class="config-text"/>`
|
||||
case reflect.Bool:
|
||||
checked := ""
|
||||
if fVal.Bool() {
|
||||
checked = "checked"
|
||||
}
|
||||
tableOut += `<input name="` + name + `" type="checkbox" ` + checked + " />"
|
||||
|
||||
case reflect.Slice:
|
||||
tableOut += `<textarea name="` + name + `" rows="4" cols="28">`
|
||||
arrLength := fVal.Len()
|
||||
for s := 0; s < arrLength; s++ {
|
||||
newLine := "\n"
|
||||
if s == arrLength-1 {
|
||||
newLine = ""
|
||||
}
|
||||
tableOut += html.EscapeString(fVal.Slice(s, s+1).Index(0).String()) + newLine
|
||||
}
|
||||
tableOut += "</textarea>"
|
||||
default:
|
||||
tableOut += fmt.Sprintf("%v", fKind)
|
||||
}
|
||||
|
||||
tableOut += "</td><td>" + fKind.String() + "</td><td>"
|
||||
defaultTag := field.Tag.Get("default")
|
||||
var defaultTagHTML string
|
||||
if defaultTag != "" {
|
||||
defaultTagHTML = " <b>Default: " + defaultTag + "</b>"
|
||||
}
|
||||
tableOut += field.Tag.Get("description") + defaultTagHTML + "</td>"
|
||||
tableOut += "</tr>"
|
||||
}
|
||||
return tableOut
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ var (
|
|||
FrontPage *template.Template
|
||||
BoardPage *template.Template
|
||||
JsConsts *template.Template
|
||||
ManageAnnouncements *template.Template
|
||||
ManageAppeals *template.Template
|
||||
ManageBans *template.Template
|
||||
ManageBoards *template.Template
|
||||
ManageConfig *template.Template
|
||||
ManageDashboard *template.Template
|
||||
ManageFileBans *template.Template
|
||||
ManageFixThumbnails *template.Template
|
||||
|
@ -141,6 +141,12 @@ func templateLoading(t string, buildAll bool) error {
|
|||
return templateError("threadpage.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "manageannouncements" {
|
||||
ManageAnnouncements, err = LoadTemplate("manage_announcements.html", "page_header.html", "topbar.html", "page_footer.html")
|
||||
if err != nil {
|
||||
return templateError("manage_announcements.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "manageappeals" {
|
||||
ManageAppeals, err = LoadTemplate("manage_appeals.html")
|
||||
if err != nil {
|
||||
|
@ -171,12 +177,6 @@ func templateLoading(t string, buildAll bool) error {
|
|||
return templateError("manage_sections.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "manageconfig" {
|
||||
ManageConfig, err = LoadTemplate("manage_config.html")
|
||||
if err != nil {
|
||||
return templateError("manage_config.html", err)
|
||||
}
|
||||
}
|
||||
if buildAll || t == "managedashboard" {
|
||||
ManageDashboard, err = LoadTemplate("manage_dashboard.html")
|
||||
if err != nil {
|
||||
|
|
|
@ -42,142 +42,21 @@ type uploadInfo struct {
|
|||
func registerAdminPages() {
|
||||
actions = append(actions,
|
||||
Action{
|
||||
ID: "cleanup",
|
||||
Title: "Cleanup",
|
||||
ID: "updateannouncements",
|
||||
Title: "Update staff announcements",
|
||||
Permissions: AdminPerms,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv *zerolog.Event, errEv *zerolog.Event) (output interface{}, err error) {
|
||||
outputStr := ""
|
||||
if request.FormValue("run") == "Run Cleanup" {
|
||||
outputStr += "Removing deleted posts from the database.<hr />"
|
||||
if err = gcsql.PermanentlyRemoveDeletedPosts(); err != nil {
|
||||
errEv.Err(err).
|
||||
Str("cleanup", "removeDeletedPosts").
|
||||
Caller().Send()
|
||||
err = errors.New("Error removing deleted posts from database: " + err.Error())
|
||||
return outputStr + "<tr><td>" + err.Error() + "</td></tr></table>", err
|
||||
}
|
||||
|
||||
outputStr += "Optimizing all tables in database.<hr />"
|
||||
err = gcsql.OptimizeDatabase()
|
||||
if err != nil {
|
||||
errEv.Err(err).
|
||||
Str("sql", "optimization").
|
||||
Caller().Send()
|
||||
err = errors.New("Error optimizing SQL tables: " + err.Error())
|
||||
return outputStr + "<tr><td>" + err.Error() + "</td></tr></table>", err
|
||||
}
|
||||
outputStr += "Cleanup finished"
|
||||
} else {
|
||||
outputStr += `<form action="` + config.GetSystemCriticalConfig().WebRoot + `manage/cleanup" method="post">` +
|
||||
`<input name="run" id="run" type="submit" value="Run Cleanup" />` +
|
||||
`</form>`
|
||||
}
|
||||
return outputStr, nil
|
||||
}},
|
||||
Action{
|
||||
ID: "staff",
|
||||
Title: "Staff",
|
||||
Permissions: JanitorPerms,
|
||||
JSONoutput: OptionalJSON,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv *zerolog.Event, errEv *zerolog.Event) (output interface{}, err error) {
|
||||
var outputStr string
|
||||
do := request.FormValue("do")
|
||||
allStaff, err := getAllStaffNopass(true)
|
||||
if wantsJSON {
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().Msg("Failed getting staff list")
|
||||
}
|
||||
return allStaff, err
|
||||
}
|
||||
JSONoutput: NoJSON,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv *zerolog.Event, errEv *zerolog.Event) (interface{}, error) {
|
||||
announcements, err := getAllAnnouncements()
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().Msg("Failed getting staff list")
|
||||
err = errors.New("Error getting staff list: " + err.Error())
|
||||
errEv.Err(err).Caller().Msg("Unable to get staff announcements")
|
||||
return "", err
|
||||
}
|
||||
|
||||
updateUsername := request.FormValue("update")
|
||||
username := request.FormValue("username")
|
||||
password := request.FormValue("password")
|
||||
passwordConfirm := request.FormValue("passwordconfirm")
|
||||
if (do == "add" || do == "update") && password != passwordConfirm {
|
||||
return "", ErrPasswordConfirm
|
||||
}
|
||||
|
||||
rankStr := request.FormValue("rank")
|
||||
var rank int
|
||||
if rankStr != "" {
|
||||
if rank, err = strconv.Atoi(rankStr); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("rank", rankStr).Send()
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if do == "add" {
|
||||
if staff.Rank < 3 {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
errEv.Err(ErrInsufficientPermission).Caller().
|
||||
Int("rank", staff.Rank).Send()
|
||||
return "", ErrInsufficientPermission
|
||||
}
|
||||
if _, err = gcsql.NewStaff(username, password, rank); err != nil {
|
||||
errEv.Caller().
|
||||
Str("newStaff", username).
|
||||
Str("newPass", password).
|
||||
Int("newRank", rank).
|
||||
Msg("Error creating new staff account")
|
||||
return "", fmt.Errorf("Error creating new staff account %q by %q: %s",
|
||||
username, staff.Username, err.Error())
|
||||
}
|
||||
} else if do == "del" && username != "" {
|
||||
if staff.Rank < 3 {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
errEv.Err(ErrInsufficientPermission).Caller().
|
||||
Int("rank", staff.Rank).Send()
|
||||
return "", ErrInsufficientPermission
|
||||
}
|
||||
if err = gcsql.DeactivateStaff(username); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("delStaff", username).
|
||||
Msg("Error deleting staff account")
|
||||
return "", fmt.Errorf("Error deleting staff account %q by %q: %s",
|
||||
username, staff.Username, err.Error())
|
||||
}
|
||||
} else if do == "update" && updateUsername != "" {
|
||||
if staff.Username != updateUsername && staff.Rank < 3 {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
errEv.Err(ErrInsufficientPermission).Caller().
|
||||
Int("rank", staff.Rank).Send()
|
||||
return "", ErrInsufficientPermission
|
||||
}
|
||||
if err = gcsql.UpdatePassword(updateUsername, password); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("updateStaff", username).
|
||||
Msg("Error updating password")
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if do == "add" || do == "del" {
|
||||
allStaff, err = getAllStaffNopass(true)
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().Msg("Error getting updated staff list")
|
||||
err = errors.New("Error getting updated staff list: " + err.Error())
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
staffBuffer := bytes.NewBufferString("")
|
||||
if err = serverutil.MinifyTemplate(gctemplates.ManageStaff, map[string]interface{}{
|
||||
"do": do,
|
||||
"updateUsername": updateUsername,
|
||||
"allstaff": allStaff,
|
||||
"currentStaff": staff,
|
||||
}, staffBuffer, "text/html"); err != nil {
|
||||
errEv.Err(err).Str("template", "manage_staff.html").Send()
|
||||
return "", errors.New("Error executing staff management page template: " + err.Error())
|
||||
}
|
||||
outputStr += staffBuffer.String()
|
||||
return outputStr, nil
|
||||
pageBuffer := bytes.NewBufferString("")
|
||||
err = serverutil.MinifyTemplate(gctemplates.ManageAnnouncements, map[string]any{
|
||||
"announcements": announcements,
|
||||
}, pageBuffer, "tex/thtml")
|
||||
return pageBuffer.String(), err
|
||||
}},
|
||||
Action{
|
||||
ID: "boards",
|
||||
|
@ -388,6 +267,39 @@ func registerAdminPages() {
|
|||
output = pageBuffer.String()
|
||||
return
|
||||
}},
|
||||
Action{
|
||||
ID: "cleanup",
|
||||
Title: "Cleanup",
|
||||
Permissions: AdminPerms,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv *zerolog.Event, errEv *zerolog.Event) (output interface{}, err error) {
|
||||
outputStr := ""
|
||||
if request.FormValue("run") == "Run Cleanup" {
|
||||
outputStr += "Removing deleted posts from the database.<hr />"
|
||||
if err = gcsql.PermanentlyRemoveDeletedPosts(); err != nil {
|
||||
errEv.Err(err).
|
||||
Str("cleanup", "removeDeletedPosts").
|
||||
Caller().Send()
|
||||
err = errors.New("Error removing deleted posts from database: " + err.Error())
|
||||
return outputStr + "<tr><td>" + err.Error() + "</td></tr></table>", err
|
||||
}
|
||||
|
||||
outputStr += "Optimizing all tables in database.<hr />"
|
||||
err = gcsql.OptimizeDatabase()
|
||||
if err != nil {
|
||||
errEv.Err(err).
|
||||
Str("sql", "optimization").
|
||||
Caller().Send()
|
||||
err = errors.New("Error optimizing SQL tables: " + err.Error())
|
||||
return outputStr + "<tr><td>" + err.Error() + "</td></tr></table>", err
|
||||
}
|
||||
outputStr += "Cleanup finished"
|
||||
} else {
|
||||
outputStr += `<form action="` + config.GetSystemCriticalConfig().WebRoot + `manage/cleanup" method="post">` +
|
||||
`<input name="run" id="run" type="submit" value="Run Cleanup" />` +
|
||||
`</form>`
|
||||
}
|
||||
return outputStr, nil
|
||||
}},
|
||||
Action{
|
||||
ID: "fixthumbnails",
|
||||
Title: "Regenerate thumbnails",
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
|
@ -129,7 +130,112 @@ func registerJanitorPages() {
|
|||
JSONoutput: AlwaysJSON,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv *zerolog.Event, errEv *zerolog.Event) (output interface{}, err error) {
|
||||
// return an array of announcements and any errors
|
||||
return gcsql.GetAllAccouncements()
|
||||
return getAllAnnouncements()
|
||||
}},
|
||||
Action{
|
||||
ID: "staff",
|
||||
Title: "Staff",
|
||||
Permissions: JanitorPerms,
|
||||
JSONoutput: OptionalJSON,
|
||||
Callback: func(writer http.ResponseWriter, request *http.Request, staff *gcsql.Staff, wantsJSON bool, infoEv *zerolog.Event, errEv *zerolog.Event) (output interface{}, err error) {
|
||||
var outputStr string
|
||||
do := request.FormValue("do")
|
||||
allStaff, err := getAllStaffNopass(true)
|
||||
if wantsJSON {
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().Msg("Failed getting staff list")
|
||||
}
|
||||
return allStaff, err
|
||||
}
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().Msg("Failed getting staff list")
|
||||
err = errors.New("Error getting staff list: " + err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
updateUsername := request.FormValue("update")
|
||||
username := request.FormValue("username")
|
||||
password := request.FormValue("password")
|
||||
passwordConfirm := request.FormValue("passwordconfirm")
|
||||
if (do == "add" || do == "update") && password != passwordConfirm {
|
||||
return "", ErrPasswordConfirm
|
||||
}
|
||||
|
||||
rankStr := request.FormValue("rank")
|
||||
var rank int
|
||||
if rankStr != "" {
|
||||
if rank, err = strconv.Atoi(rankStr); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("rank", rankStr).Send()
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if do == "add" {
|
||||
if staff.Rank < 3 {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
errEv.Err(ErrInsufficientPermission).Caller().
|
||||
Int("rank", staff.Rank).Send()
|
||||
return "", ErrInsufficientPermission
|
||||
}
|
||||
if _, err = gcsql.NewStaff(username, password, rank); err != nil {
|
||||
errEv.Caller().
|
||||
Str("newStaff", username).
|
||||
Str("newPass", password).
|
||||
Int("newRank", rank).
|
||||
Msg("Error creating new staff account")
|
||||
return "", fmt.Errorf("Error creating new staff account %q by %q: %s",
|
||||
username, staff.Username, err.Error())
|
||||
}
|
||||
} else if do == "del" && username != "" {
|
||||
if staff.Rank < 3 {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
errEv.Err(ErrInsufficientPermission).Caller().
|
||||
Int("rank", staff.Rank).Send()
|
||||
return "", ErrInsufficientPermission
|
||||
}
|
||||
if err = gcsql.DeactivateStaff(username); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("delStaff", username).
|
||||
Msg("Error deleting staff account")
|
||||
return "", fmt.Errorf("Error deleting staff account %q by %q: %s",
|
||||
username, staff.Username, err.Error())
|
||||
}
|
||||
} else if do == "update" && updateUsername != "" {
|
||||
if staff.Username != updateUsername && staff.Rank < 3 {
|
||||
writer.WriteHeader(http.StatusUnauthorized)
|
||||
errEv.Err(ErrInsufficientPermission).Caller().
|
||||
Int("rank", staff.Rank).Send()
|
||||
return "", ErrInsufficientPermission
|
||||
}
|
||||
if err = gcsql.UpdatePassword(updateUsername, password); err != nil {
|
||||
errEv.Err(err).Caller().
|
||||
Str("updateStaff", username).
|
||||
Msg("Error updating password")
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if do == "add" || do == "del" {
|
||||
allStaff, err = getAllStaffNopass(true)
|
||||
if err != nil {
|
||||
errEv.Err(err).Caller().Msg("Error getting updated staff list")
|
||||
err = errors.New("Error getting updated staff list: " + err.Error())
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
staffBuffer := bytes.NewBufferString("")
|
||||
if err = serverutil.MinifyTemplate(gctemplates.ManageStaff, map[string]interface{}{
|
||||
"do": do,
|
||||
"updateUsername": updateUsername,
|
||||
"allstaff": allStaff,
|
||||
"currentStaff": staff,
|
||||
}, staffBuffer, "text/html"); err != nil {
|
||||
errEv.Err(err).Str("template", "manage_staff.html").Send()
|
||||
return "", errors.New("Error executing staff management page template: " + err.Error())
|
||||
}
|
||||
outputStr += staffBuffer.String()
|
||||
return outputStr, nil
|
||||
}},
|
||||
)
|
||||
}
|
||||
|
|
34
pkg/manage/announcements.go
Normal file
34
pkg/manage/announcements.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package manage
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gochan-org/gochan/pkg/gcsql"
|
||||
)
|
||||
|
||||
type announcementWithName struct {
|
||||
ID uint `json:"no"`
|
||||
Staff string `json:"name"`
|
||||
Subject string `json:"sub"`
|
||||
Message string `json:"com"`
|
||||
Timestamp time.Time `json:"-"`
|
||||
}
|
||||
|
||||
func getAllAnnouncements() ([]announcementWithName, error) {
|
||||
querySQL := `SELECT id, staff, subject, message, timestamp from DBPREFIXannouncements NATURAL JOIN (
|
||||
SELECT id AS staff_id, username AS staff FROM DBPREFIXstaff) S1`
|
||||
rows, err := gcsql.QuerySQL(querySQL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var announcements []announcementWithName
|
||||
for rows.Next() {
|
||||
var announcement announcementWithName
|
||||
if err = rows.Scan(&announcement.ID, &announcement.Staff, &announcement.Subject, &announcement.Message, &announcement.Timestamp); err != nil {
|
||||
rows.Close()
|
||||
return announcements, err
|
||||
}
|
||||
announcements = append(announcements, announcement)
|
||||
}
|
||||
return announcements, rows.Close()
|
||||
}
|
|
@ -127,7 +127,7 @@ func init() {
|
|||
|
||||
func dashboardCallback(_ http.ResponseWriter, _ *http.Request, staff *gcsql.Staff, _ bool, _ *zerolog.Event, errEv *zerolog.Event) (interface{}, error) {
|
||||
dashBuffer := bytes.NewBufferString("")
|
||||
announcements, err := gcsql.GetAllAccouncements()
|
||||
announcements, err := getAllAnnouncements()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
28
templates/manage_announcements.html
Normal file
28
templates/manage_announcements.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
<table>
|
||||
<tr><th>Subject</th><th>Message</th><th>Staff</th><th>Timestamp</th></tr>
|
||||
{{range $a, $announcement := $.announcements -}}<tr>
|
||||
<td>{{$announcement.Subject}}</td>
|
||||
<td>{{$announcement.Message}}</td>
|
||||
<td>{{$announcement.Staff}}</td>
|
||||
<td>{{formatTimestamp $announcement.Timestamp}}</td>
|
||||
</tr>{{else}}<i>No announcements</i>{{end}}
|
||||
</table>
|
||||
<hr/>
|
||||
<header>
|
||||
<h1>Create new announcement</h1>
|
||||
</header>
|
||||
<form>
|
||||
<table id="postbox-static">
|
||||
<tr>
|
||||
<th class="postblock">Subject</th>
|
||||
<td>
|
||||
<input type="text" name="subject" size="25" maxlength="100"/>
|
||||
<input type="submit" value="Submit"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="postblock">Message</th>
|
||||
<td><textarea rows="5" cols="35" name="announcementmsg"></textarea></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
|
@ -1,9 +0,0 @@
|
|||
{{if ne .status ""}}{{.status}}<hr />{{end}}
|
||||
Some fields omitted because they can not be (safely) edited from the web interface while Gochan is running.
|
||||
Edit these directly in gochan.json, then restart Gochan.<br />
|
||||
<span class="warning">This config editor isn't fully stable so MAKE BACKUPS!</span>
|
||||
<form action="{{webPath "/manage/config"}}" method="POST">
|
||||
<input name="do" value="save" type="hidden" />
|
||||
{{generateConfigTable}}<br />
|
||||
<input type="submit" />
|
||||
</form>
|
Loading…
Add table
Add a link
Reference in a new issue