Improved the CSS for the usernames and moderation buttons.

Stickies now show up in yellow on the topic list and in topics.
The topic list is now sorted by stickies, then the date of the last reply, then the date it was originally created.
Added the ability to stick and unstick topics.
Added the ability to delete topics.
This commit is contained in:
Azareal 2016-12-03 10:25:39 +00:00
parent 77c291bc34
commit 8ff76d1bc8
11 changed files with 139 additions and 11 deletions

BIN
pinned-topic.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

BIN
ren5.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

View File

@ -10,6 +10,7 @@ CREATE TABLE `users`(
`createdAt` datetime not null,
`lastActiveAt` datetime not null,
`session` varchar(200) DEFAULT '',
`email` varchar(200) DEFAULT '',
`avatar` varchar(20) DEFAULT '',
primary key(`uid`)
);
@ -19,6 +20,7 @@ CREATE TABLE `users_groups`(
`name` varchar(100) not null,
`permissions` text not null,
`is_admin` tinyint DEFAULT 0 not null,
`is_banned` tinyint DEFAULT 0 not null,
primary key(`gid`)
);

View File

@ -56,6 +56,15 @@ func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user U
}
}
func NoPermissions(w http.ResponseWriter, r *http.Request, user User) {
errmsg := "You don't have permission to do that."
pi := Page{"Local Error","error",user,tList,errmsg}
var b bytes.Buffer
templates.ExecuteTemplate(&b,"error.html", pi)
errpage := b.String()
http.Error(w,errpage,403)
}
func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) {
errmsg := "You don't have permission to do that."
if is_js == "0" {

View File

@ -24,6 +24,9 @@ var create_reply_stmt *sql.Stmt
var edit_topic_stmt *sql.Stmt
var edit_reply_stmt *sql.Stmt
var delete_reply_stmt *sql.Stmt
var delete_topic_stmt *sql.Stmt
var stick_topic_stmt *sql.Stmt
var unstick_topic_stmt *sql.Stmt
var login_stmt *sql.Stmt
var update_session_stmt *sql.Stmt
var logout_stmt *sql.Stmt
@ -87,6 +90,24 @@ func init_database(err error) {
log.Fatal(err)
}
log.Print("Preparing delete_topic statement.")
delete_topic_stmt, err = db.Prepare("DELETE FROM topics WHERE tid = ?")
if err != nil {
log.Fatal(err)
}
log.Print("Preparing stick_topic statement.")
stick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 1 WHERE tid = ?")
if err != nil {
log.Fatal(err)
}
log.Print("Preparing unstick_topic statement.")
unstick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 0 WHERE tid = ?")
if err != nil {
log.Fatal(err)
}
log.Print("Preparing login statement.")
login_stmt, err = db.Prepare("SELECT `uid`, `name`, `password`, `salt` FROM `users` WHERE `name` = ?")
if err != nil {
@ -172,6 +193,9 @@ func main(){
http.HandleFunc("/reply/edit/submit/", route_reply_edit_submit) //POST
http.HandleFunc("/reply/delete/submit/", route_reply_delete_submit) //POST
http.HandleFunc("/topic/edit/submit/", route_edit_topic) //POST
http.HandleFunc("/topic/delete/submit/", route_delete_topic)
http.HandleFunc("/topic/stick/submit/", route_stick_topic)
http.HandleFunc("/topic/unstick/submit/", route_unstick_topic)
// Custom Pages
http.HandleFunc("/pages/", route_custom_page)

View File

@ -93,7 +93,7 @@ li:not(:last-child)
.rowitem
{
width: 99%;
width: 100%;
padding-left: 8px;
padding-right: 8px;
padding-top: 17px;
@ -242,6 +242,21 @@ button
display: none;
}
.username
{
text-transform: none;
margin-left: 0px;
padding-left: 4px;
padding-right: 4px;
padding-top: 2px;
padding-bottom: 2px;
color: #505050; /* 80,80,80 */
border-style: dotted;
border-color: #505050; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */
border-width: 1px;
font-size: 15px;
}
.show_on_edit
{
display: none;

View File

@ -68,7 +68,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){
topicList = make(map[int]interface{})
currentID = 0
rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid")
rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC")
if err != nil {
InternalError(err,w,r,user)
return
@ -340,6 +340,82 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) {
}
}
func route_delete_topic(w http.ResponseWriter, r *http.Request) {
user := SessionCheck(w,r)
if !user.Is_Admin {
NoPermissions(w,r,user)
return
}
tid, err := strconv.Atoi(r.URL.Path[len("/topic/delete/submit/"):])
if err != nil {
LocalError("The provided TopicID is not a valid number.",w,r,user)
return
}
err = db.QueryRow("SELECT tid from topics where tid = ?", tid).Scan(&tid)
if err == sql.ErrNoRows {
LocalError("The topic you tried to delete doesn't exist.",w,r,user)
return
} else if err != nil {
InternalError(err,w,r,user)
return
}
_, err = delete_topic_stmt.Exec(tid)
if err != nil {
InternalError(err,w,r,user)
return
}
log.Print("The topic '" + strconv.Itoa(tid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".")
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func route_stick_topic(w http.ResponseWriter, r *http.Request) {
user := SessionCheck(w,r)
if !user.Is_Admin {
NoPermissions(w,r,user)
return
}
tid, err := strconv.Atoi(r.URL.Path[len("/topic/stick/submit/"):])
if err != nil {
LocalError("The provided TopicID is not a valid number.",w,r,user)
return
}
_, err = stick_topic_stmt.Exec(tid)
if err != nil {
InternalError(err,w,r,user)
return
}
http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
}
func route_unstick_topic(w http.ResponseWriter, r *http.Request) {
user := SessionCheck(w,r)
if !user.Is_Admin {
NoPermissions(w,r,user)
return
}
tid, err := strconv.Atoi(r.URL.Path[len("/topic/unstick/submit/"):])
if err != nil {
LocalError("The provided TopicID is not a valid number.",w,r,user)
return
}
_, err = unstick_topic_stmt.Exec(tid)
if err != nil {
InternalError(err,w,r,user)
return
}
http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
}
func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) {
user := SessionCheck(w,r)
err := r.ParseForm()

View File

@ -1,3 +1,4 @@
<!--<link rel="stylesheet" href="https://use.fontawesome.com/8670aa03ca.css">-->
</div>
</body>
</html>

View File

@ -1,16 +1,17 @@
{{template "header.html" . }}
<div class="rowblock">
<form action='/topic/edit/submit/{{.Something.ID}}' method="post">
<div class="rowitem">
<div class="rowitem"{{ if .Something.Sticky }}style="background-color: #FFFFEA;"{{end}}>
<a class='topic_name hide_on_edit'>{{.Something.Title}}</a>
<span class='topic_status topic_status_e topic_status_{{.Something.Status}} hide_on_edit'>{{.Something.Status}}</span>
<a href='/topic/edit/{{.Something.ID}}' class="topic_status hide_on_edit open_edit">Edit</a>
<a href='/topic/delete/{{.Something.ID}}' class="topic_status">Delete</a>
<a href='/topic/edit/{{.Something.ID}}' class="username hide_on_edit open_edit" style="font-weight: normal;">Edit</a>
<a href='/topic/delete/submit/{{.Something.ID}}' class="username" style="font-weight: normal;">Delete</a>
{{ if .Something.Sticky }}<a href='/topic/unstick/submit/{{.Something.ID}}' class="username" style="font-weight: normal;">Unpin</a>{{else}}<a href='/topic/stick/submit/{{.Something.ID}}' class="username" style="font-weight: normal;">Pin</a>{{end}}
<input class='show_on_edit topic_name_input' name="topic_name" value='{{.Something.Title}}' type="text" />
<select name="topic_status" class='show_on_edit topic_status_input'>
<option>closed</option>
<option>open</option>
<option>closed</option>
</select>
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
</div>
@ -21,7 +22,7 @@
<span class="hide_on_edit topic_content">{{.Something.Content}}</span>
<textarea name="topic_content" class="show_on_edit topic_content_input">{{.Something.Content}}</textarea>
<br /><br />
<a class="topic_status" style="padding-left: 0px;margin-left: 0px;">{{.Something.CreatedByName}}<a/>
<a class="username">{{.Something.CreatedByName}}<a/>
</div>
</div><br />
<div class="rowblock" style="overflow: hidden;">
@ -29,9 +30,9 @@
<div class="rowitem passive deletable_block editable_parent" style="{{ if $element.Avatar }}background-image: url({{ $element.Avatar }});background-position: left;background-repeat: no-repeat;background-size: 128px;padding-left: 136px;{{end}}">
<span class="editable_block">{{$element.ContentHtml}}</span>
<br /><br />
<a class="topic_status" style="padding-left: 0px;margin-left: 0px;">{{$element.CreatedByName}}<a/>
<a href="/reply/edit/submit/{{$element.ID}}"><button class="topic_status edit_item">Edit</button></a>
<a href="/reply/delete/submit/{{$element.ID}}"><button class="topic_status delete_item">Delete</button></a>
<a class="username">{{$element.CreatedByName}}<a/>
<a href="/reply/edit/submit/{{$element.ID}}"><button class="username edit_item">Edit</button></a>
<a href="/reply/delete/submit/{{$element.ID}}"><button class="username delete_item">Delete</button></a>
</div>{{ end }}
</div>
<div class="rowblock">

View File

@ -3,7 +3,7 @@
<div class="rowitem"><a>Topic List</a></div>
</div>
<div class="rowblock">
{{range .ItemList}}<div class="rowitem passive"{{ if .Avatar }} style="background-image: url({{ .Avatar }});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;"{{end}}>
{{range .ItemList}}<div class="rowitem passive" style="{{ if .Avatar }}background-image: url({{ .Avatar }});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}{{ if .Sticky }}background-color: #FFFFCC;{{end}}">
<a href="/topic/{{.ID}}">{{.Title}}</a> {{if .Is_Closed}}<span class="topic_status topic_status_closed">closed</span>{{else}}<span class="topic_status topic_status_open">open</span>{{end}}
</div>{{end}}
</div>

BIN
topic-list.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB