Added the forum cache. The rest of the code now uses it instead than firing queries on every request.
Added the ability for admins to delete forums. Added the ability for admins to edit forums. Added the Uncategorised Forum for topics with an ID of 0. Possibly for deleted forums in the future? Added the uncategorised forum visibility switch. Creating forums now has an anti-CSRF session check. The same is true with the newly implemented forum deletion and modification features. Cleaned up some of the error code.
This commit is contained in:
parent
84cbb3a5d5
commit
30ecdf8d93
|
@ -12,4 +12,5 @@ var max_request_size = 5 * megabyte
|
|||
|
||||
// Misc
|
||||
var default_route = route_topics
|
||||
var staff_css = "background-color: #ffeaff;background-position: left;"
|
||||
var staff_css = "background-color: #ffeaff;background-position: left;"
|
||||
var uncategorised_forum_visible = true
|
20
errors.go
20
errors.go
|
@ -120,6 +120,26 @@ func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, is_js s
|
|||
}
|
||||
}
|
||||
|
||||
func SecurityError(w http.ResponseWriter, r *http.Request, user User) {
|
||||
errmsg := "There was a security issue with your request."
|
||||
pi := Page{"Security Error","error",user,tList,errmsg}
|
||||
var b bytes.Buffer
|
||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||
errpage := b.String()
|
||||
w.WriteHeader(403)
|
||||
fmt.Fprintln(w,errpage)
|
||||
}
|
||||
|
||||
func NotFound(w http.ResponseWriter, r *http.Request, user User) {
|
||||
errmsg := "The requested page doesn't exist."
|
||||
pi := Page{"Not Found","error",user,tList,errmsg}
|
||||
var b bytes.Buffer
|
||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||
errpage := b.String()
|
||||
w.WriteHeader(404)
|
||||
fmt.Fprintln(w,errpage)
|
||||
}
|
||||
|
||||
func CustomErrorJSQ(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, user User, is_js string) {
|
||||
if is_js == "0" {
|
||||
pi := Page{errtitle,"error",user,tList,errmsg}
|
||||
|
|
1
forum.go
1
forum.go
|
@ -4,6 +4,7 @@ type Forum struct
|
|||
{
|
||||
ID int
|
||||
Name string
|
||||
Active bool
|
||||
LastTopic string
|
||||
LastTopicID int
|
||||
LastReplyer string
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
go build
|
||||
./Grosolo
|
BIN
grosolo.exe
BIN
grosolo.exe
Binary file not shown.
Binary file not shown.
56
main.go
56
main.go
|
@ -42,12 +42,15 @@ var register_stmt *sql.Stmt
|
|||
var username_exists_stmt *sql.Stmt
|
||||
|
||||
var create_forum_stmt *sql.Stmt
|
||||
var delete_forum_stmt *sql.Stmt
|
||||
var update_forum_stmt *sql.Stmt
|
||||
|
||||
var custom_pages map[string]string = make(map[string]string)
|
||||
var templates = template.Must(template.ParseGlob("templates/*"))
|
||||
var no_css_tmpl = template.CSS("")
|
||||
var staff_css_tmpl = template.CSS(staff_css)
|
||||
var groups map[int]Group = make(map[int]Group)
|
||||
var forums map[int]Forum = make(map[int]Forum)
|
||||
var static_files map[string]SFile = make(map[string]SFile)
|
||||
|
||||
func init_database(err error) {
|
||||
|
@ -188,8 +191,20 @@ func init_database(err error) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Preparing delete_forum statement.")
|
||||
delete_forum_stmt, err = db.Prepare("DELETE FROM forums WHERE fid = ?")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Preparing update_forum statement.")
|
||||
update_forum_stmt, err = db.Prepare("UPDATE forums SET name = ? WHERE fid = ?")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Loading the usergroups.")
|
||||
rows, err := db.Query("select gid,name,permissions,is_admin,is_banned from users_groups")
|
||||
rows, err := db.Query("SELECT gid,name,permissions,is_admin,is_banned FROM users_groups")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -207,6 +222,42 @@ func init_database(err error) {
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Loading the forums.")
|
||||
rows, err = db.Query("SELECT fid, name, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime FROM forums")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
forum := Forum{0,"",true,"",0,"",0,""}
|
||||
err := rows.Scan(&forum.ID, &forum.Name, &forum.LastTopic, &forum.LastTopicID, &forum.LastReplyer, &forum.LastReplyerID, &forum.LastTopicTime)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if forum.LastTopicID != 0 {
|
||||
forum.LastTopicTime, err = relative_time(forum.LastTopicTime)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
forum.LastTopic = "None"
|
||||
forum.LastTopicTime = ""
|
||||
}
|
||||
|
||||
forums[forum.ID] = forum
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Adding the uncategorised forum")
|
||||
forums[0] = Forum{0,"Uncategorised",uncategorised_forum_visible,"",0,"",0,""}
|
||||
log.Print("Adding the reports forum")
|
||||
forums[-1] = Forum{-1,"Reports",false,"",0,"",0,""}
|
||||
}
|
||||
|
||||
func main(){
|
||||
|
@ -288,6 +339,9 @@ func main(){
|
|||
// Admin
|
||||
http.HandleFunc("/panel/forums/", route_panel_forums)
|
||||
http.HandleFunc("/panel/forums/create/", route_panel_forums_create_submit)
|
||||
http.HandleFunc("/panel/forums/delete/", route_panel_forums_delete)
|
||||
http.HandleFunc("/panel/forums/delete/submit/", route_panel_forums_delete_submit)
|
||||
http.HandleFunc("/panel/forums/edit/submit/", route_panel_forums_edit_submit)
|
||||
|
||||
http.HandleFunc("/", default_route)
|
||||
|
||||
|
|
6
pages.go
6
pages.go
|
@ -21,6 +21,12 @@ type PageSimple struct
|
|||
Something interface{}
|
||||
}
|
||||
|
||||
type AreYouSure struct
|
||||
{
|
||||
URL string
|
||||
Message string
|
||||
}
|
||||
|
||||
func add_custom_page(path string, f os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -83,4 +83,30 @@ $(document).ready(function(){
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
$(".edit_field").click(function(event)
|
||||
{
|
||||
event.preventDefault();
|
||||
var block_parent = $(this).closest('.editable_parent');
|
||||
var block = block_parent.find('.editable_block').eq(0);
|
||||
block.html("<input name='edit_field' value='" + block.text() + "' type='text'/><a href='" + $(this).closest('a').attr("href") + "'><button class='submit_edit' type='submit'>Update</button></a>");
|
||||
|
||||
$(".submit_edit").click(function(event)
|
||||
{
|
||||
event.preventDefault();
|
||||
var block_parent = $(this).closest('.editable_parent');
|
||||
var block = block_parent.find('.editable_block').eq(0);
|
||||
var newContent = block.find('input').eq(0).val();
|
||||
block.html(newContent);
|
||||
|
||||
var form_action = $(this).closest('a').attr("href");
|
||||
console.log("Form Action: " + form_action);
|
||||
$.ajax({
|
||||
url: form_action + "?session=" + session,
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: {is_js: "1",edit_item: newContent}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
235
routes.go
235
routes.go
|
@ -1,5 +1,6 @@
|
|||
package main
|
||||
|
||||
import "errors"
|
||||
import "log"
|
||||
import "fmt"
|
||||
import "strconv"
|
||||
|
@ -58,14 +59,7 @@ func route_custom_page(w http.ResponseWriter, r *http.Request){
|
|||
pi := Page{"Page","page",user,tList,val}
|
||||
templates.ExecuteTemplate(w,"custom_page.html", pi)
|
||||
} else {
|
||||
errmsg := "The requested page doesn't exist."
|
||||
pi := Page{"Error","error",user,tList,errmsg}
|
||||
|
||||
var b bytes.Buffer
|
||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||
errpage := b.String()
|
||||
w.WriteHeader(404)
|
||||
fmt.Fprintln(w,errpage)
|
||||
NotFound(w,r,user)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +127,6 @@ func route_forum(w http.ResponseWriter, r *http.Request){
|
|||
var(
|
||||
topicList map[int]interface{}
|
||||
currentID int
|
||||
fname string
|
||||
|
||||
tid int
|
||||
title string
|
||||
|
@ -156,18 +149,9 @@ func route_forum(w http.ResponseWriter, r *http.Request){
|
|||
return
|
||||
}
|
||||
|
||||
err = db.QueryRow("select name from forums where fid = ?", fid).Scan(&fname)
|
||||
if err == sql.ErrNoRows {
|
||||
pi := Page{"Error","error",user,tList,"The requested forum doesn't exist."}
|
||||
|
||||
var b bytes.Buffer
|
||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||
errpage := b.String()
|
||||
w.WriteHeader(404)
|
||||
fmt.Fprintln(w,errpage)
|
||||
return
|
||||
} else if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
_, ok := forums[fid]
|
||||
if !ok {
|
||||
NotFound(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -202,7 +186,7 @@ func route_forum(w http.ResponseWriter, r *http.Request){
|
|||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
pi := Page{fname,"forum",user,topicList,0}
|
||||
pi := Page{forums[fid].Name,"forum",user,topicList,0}
|
||||
err = templates.ExecuteTemplate(w,"forum.html", pi)
|
||||
if err != nil {
|
||||
InternalError(err, w, r, user)
|
||||
|
@ -211,46 +195,23 @@ func route_forum(w http.ResponseWriter, r *http.Request){
|
|||
|
||||
func route_forums(w http.ResponseWriter, r *http.Request){
|
||||
user := SessionCheck(w,r)
|
||||
var forumList map[int]interface{}
|
||||
forumList = make(map[int]interface{})
|
||||
var forumList map[int]interface{} = make(map[int]interface{})
|
||||
currentID := 0
|
||||
|
||||
rows, err := db.Query("select fid, name, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime from forums")
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
for _, forum := range forums {
|
||||
if forum.Active {
|
||||
forumList[currentID] = forum
|
||||
currentID++
|
||||
}
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
forum := Forum{0,"","",0,"",0,""}
|
||||
err := rows.Scan(&forum.ID, &forum.Name, &forum.LastTopic,&forum.LastTopicID,&forum.LastReplyer,&forum.LastReplyerID,&forum.LastTopicTime)
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
if forum.LastTopicID != 0 {
|
||||
forum.LastTopicTime, err = relative_time(forum.LastTopicTime)
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
forum.LastTopic = "None"
|
||||
forum.LastTopicTime = ""
|
||||
}
|
||||
|
||||
forumList[currentID] = forum
|
||||
currentID++
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
if len(forums) == 0 {
|
||||
InternalError(errors.New("No forums"),w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
pi := Page{"Forum List","forums",user,forumList,0}
|
||||
err = templates.ExecuteTemplate(w,"forums.html", pi)
|
||||
err := templates.ExecuteTemplate(w,"forums.html", pi)
|
||||
if err != nil {
|
||||
InternalError(err, w, r, user)
|
||||
}
|
||||
|
@ -290,14 +251,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
|
|||
//err = db.QueryRow("select title, content, createdBy, status, is_closed from topics where tid = ?", tid).Scan(&title, &content, &createdBy, &status, &is_closed)
|
||||
err = db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, users.name, users.avatar, users.is_super_admin, users.group from topics left join users ON topics.createdBy = users.uid where tid = ?", topic.ID).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.CreatedByName, &topic.Avatar, &is_super_admin, &group)
|
||||
if err == sql.ErrNoRows {
|
||||
errmsg := "The requested topic doesn't exist."
|
||||
pi := Page{"Error","error",user,tList,errmsg}
|
||||
|
||||
var b bytes.Buffer
|
||||
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||
errpage := b.String()
|
||||
w.WriteHeader(404)
|
||||
fmt.Fprintln(w,errpage)
|
||||
NotFound(w,r,user)
|
||||
return
|
||||
} else if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
|
@ -1036,9 +990,9 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) {
|
|||
var salt string
|
||||
var session string
|
||||
username := html.EscapeString(r.PostFormValue("username"))
|
||||
log.Print("Username: " + username)
|
||||
//log.Print("Username: " + username)
|
||||
password := r.PostFormValue("password")
|
||||
log.Print("Password: " + password)
|
||||
//log.Print("Password: " + password)
|
||||
|
||||
err = login_stmt.QueryRow(username).Scan(&uid, &username, &real_password, &salt)
|
||||
if err == sql.ErrNoRows {
|
||||
|
@ -1112,8 +1066,8 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
log.Print("Successful Login")
|
||||
log.Print("Session: " + session)
|
||||
//log.Print("Successful Login")
|
||||
//log.Print("Session: " + session)
|
||||
cookie := http.Cookie{Name: "uid",Value: strconv.Itoa(uid),Path: "/",MaxAge: year}
|
||||
http.SetCookie(w,&cookie)
|
||||
cookie = http.Cookie{Name: "session",Value: session,Path: "/",MaxAge: year}
|
||||
|
@ -1230,28 +1184,11 @@ func route_panel_forums(w http.ResponseWriter, r *http.Request){
|
|||
var forumList map[int]interface{} = make(map[int]interface{})
|
||||
currentID := 0
|
||||
|
||||
rows, err := db.Query("select fid, name from forums")
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
forum := ForumSimple{0,""}
|
||||
err := rows.Scan(&forum.ID, &forum.Name)
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
for _, forum := range forums {
|
||||
if forum.ID > -1 {
|
||||
forumList[currentID] = forum
|
||||
currentID++
|
||||
}
|
||||
|
||||
forumList[currentID] = forum
|
||||
currentID++
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
pi := Page{"Forum Manager","panel-forums",user,forumList,0}
|
||||
|
@ -1264,17 +1201,135 @@ func route_panel_forums_create_submit(w http.ResponseWriter, r *http.Request){
|
|||
NoPermissions(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
LocalError("Bad Form", w, r, user)
|
||||
return
|
||||
}
|
||||
if r.FormValue("session") != user.Session {
|
||||
SecurityError(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = create_forum_stmt.Exec(r.PostFormValue("forum-name"))
|
||||
fname := r.PostFormValue("forum-name")
|
||||
res, err := create_forum_stmt.Exec(fname)
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w,r, "/panel/forums/", http.StatusSeeOther)
|
||||
lastId, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
forums[int(lastId)] = Forum{int(lastId),fname,true,"",0,"",0,""}
|
||||
http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func route_panel_forums_delete(w http.ResponseWriter, r *http.Request){
|
||||
user := SessionCheck(w,r)
|
||||
if !user.Is_Admin {
|
||||
NoPermissions(w,r,user)
|
||||
return
|
||||
}
|
||||
if r.FormValue("session") != user.Session {
|
||||
SecurityError(w,r,user)
|
||||
return
|
||||
}
|
||||
fid, err := strconv.Atoi(r.URL.Path[len("/panel/forums/delete/"):])
|
||||
if err != nil {
|
||||
LocalError("The provided Forum ID is not a valid number.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := forums[fid];
|
||||
if !ok {
|
||||
LocalError("The forum you're trying to delete doesn't exist.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
confirm_msg := "Are you sure you want to delete the '" + forums[fid].Name + "' forum?"
|
||||
yousure := AreYouSure{"/panel/forums/delete/submit/" + strconv.Itoa(fid),confirm_msg}
|
||||
|
||||
pi := Page{"Delete Forum","panel-forums-delete",user,tList,yousure}
|
||||
templates.ExecuteTemplate(w,"areyousure.html", pi)
|
||||
}
|
||||
|
||||
func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request) {
|
||||
user := SessionCheck(w,r)
|
||||
if !user.Is_Admin {
|
||||
NoPermissions(w,r,user)
|
||||
return
|
||||
}
|
||||
if r.FormValue("session") != user.Session {
|
||||
SecurityError(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
fid, err := strconv.Atoi(r.URL.Path[len("/panel/forums/delete/submit/"):])
|
||||
if err != nil {
|
||||
LocalError("The provided Forum ID is not a valid number.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := forums[fid];
|
||||
if !ok {
|
||||
LocalError("The forum you're trying to delete doesn't exist.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = delete_forum_stmt.Exec(fid)
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
// Remove this forum from the forum cache
|
||||
delete(forums,fid);
|
||||
http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request) {
|
||||
user := SessionCheck(w,r)
|
||||
if !user.Is_Admin {
|
||||
NoPermissions(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
LocalError("Bad Form", w, r, user)
|
||||
return
|
||||
}
|
||||
if r.FormValue("session") != user.Session {
|
||||
SecurityError(w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
fid, err := strconv.Atoi(r.URL.Path[len("/panel/forums/edit/submit/"):])
|
||||
if err != nil {
|
||||
LocalError("The provided Forum ID is not a valid number.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
forum_name := r.PostFormValue("edit_item")
|
||||
|
||||
forum, ok := forums[fid];
|
||||
if !ok {
|
||||
LocalError("The forum you're trying to edit doesn't exist.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = update_forum_stmt.Exec(forum_name, fid)
|
||||
if err != nil {
|
||||
InternalError(err,w,r,user)
|
||||
return
|
||||
}
|
||||
forum.Name = forum_name
|
||||
forums[fid] = forum
|
||||
|
||||
http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther)
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{{template "header.html" . }}
|
||||
<div class="rowblock">
|
||||
<div class="rowitem"><a>Are you sure?</a></div>
|
||||
</div>
|
||||
<div class="rowblock">
|
||||
<div class="rowitem passive">{{.Something.Message}}<br /><br />
|
||||
<a class="username" href="{{.Something.URL}}?session={{.CurrentUser.Session}}">Continue</a>
|
||||
</div>
|
||||
</div>
|
||||
{{template "footer.html" . }}
|
|
@ -4,6 +4,9 @@
|
|||
<title>{{.Title}}</title>
|
||||
<link href="/static/main.css" rel="stylesheet" type="text/css">
|
||||
<script type="text/javascript" src="/static/jquery-1.12.3.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var session = "{{.CurrentUser.Session}}";
|
||||
</script>
|
||||
<script type="text/javascript" src="/static/global.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -5,18 +5,24 @@
|
|||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||
<div class="rowitem passive"><a href="/forum/-1">Reports</a></div>
|
||||
</div>
|
||||
<div class="colblock_right">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem"><a style="font-size: 20px;position:relative;top: -2px;font-weight: normal;text-transform: none;">{{.Name}}</a></div>
|
||||
<div class="rowitem editable_parent" style="font-weight: normal;">
|
||||
<a class="editable_block" style="font-size: 20px;position:relative;top: -2px;text-transform: none;">{{.Name}}</a>
|
||||
<span style="float: right;">
|
||||
<a href="/panel/forums/edit/submit/{{.ID}}" class="username edit_field">Edit</a>
|
||||
<a href="/panel/forums/delete/{{.ID}}?session={{$.CurrentUser.Session}}" class="username">Delete</a>
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
</div><br />
|
||||
<div class="colblock_right">
|
||||
<div class="rowitem"><a>Add Forum</a></div>
|
||||
</div>
|
||||
<div class="colblock_right">
|
||||
<form action="/panel/forums/create/" method="post">
|
||||
<form action="/panel/forums/create/?session={{.CurrentUser.Session}}" method="post">
|
||||
<div class="formrow">
|
||||
<div class="formitem"><a>Forum Name</a></div>
|
||||
<div class="formitem"><input name="forum-name" type="text" /></div>
|
||||
|
|
Loading…
Reference in New Issue