diff --git a/alerts.go b/alerts.go
index de567ccb..0aa57655 100644
--- a/alerts.go
+++ b/alerts.go
@@ -2,8 +2,10 @@ package main
import "log"
import "strings"
+import "strconv"
import "errors"
+// These notes are for me, don't worry about it too much ^_^
/*
"You received a friend invite from {user}"
"{x}{mentioned you on}{user}{'s profile}"
@@ -18,7 +20,7 @@ import "errors"
"{x}{created a new topic}{topic}"
*/
-func build_alert(event string, elementType string, actor_id int, targetUser_id int, elementID int, user User /* The current user */) (string, error) {
+func build_alert(asid int, event string, elementType string, actor_id int, targetUser_id int, elementID int, user User /* The current user */) (string, error) {
var targetUser *User
actor, err := users.CascadeGet(actor_id)
@@ -35,7 +37,7 @@ func build_alert(event string, elementType string, actor_id int, targetUser_id i
}*/
if event == "friend_invite" {
- return `{"msg":"You received a friend invite from {0}","sub":["` + actor.Name + `"],"path":"`+actor.Link+`","avatar":"`+strings.Replace(actor.Avatar,"/","\\/",-1)+`"}`, nil
+ return `{"msg":"You received a friend invite from {0}","sub":["` + actor.Name + `"],"path":"`+actor.Link+`","avatar":"`+strings.Replace(actor.Avatar,"/","\\/",-1)+`","asid":"`+strconv.Itoa(asid)+`"}`, nil
}
var act, post_act, url, area string
@@ -109,7 +111,7 @@ func build_alert(event string, elementType string, actor_id int, targetUser_id i
case "reply": act = "replied to"
}
- return `{"msg":"{0} ` + start_frag + act + post_act + ` {1}` + end_frag + `","sub":["` + actor.Name + `","` + area + `"],"path":"` + url + `","avatar":"` + actor.Avatar + `"}`, nil
+ return `{"msg":"{0} ` + start_frag + act + post_act + ` {1}` + end_frag + `","sub":["` + actor.Name + `","` + area + `"],"path":"` + url + `","avatar":"` + actor.Avatar + `","asid":"`+strconv.Itoa(asid)+`"}`, nil
}
func notify_watchers(asid int64) {
@@ -144,5 +146,5 @@ func notify_watchers(asid int64) {
return
}
- _ = ws_hub.push_alerts(uids, event, elementType, actor_id, targetUser_id, elementID)
+ _ = ws_hub.push_alerts(uids, int(asid), event, elementType, actor_id, targetUser_id, elementID)
}
diff --git a/errors.go b/errors.go
index 8b018b50..c3c93d92 100644
--- a/errors.go
+++ b/errors.go
@@ -118,6 +118,11 @@ func LoginRequired(w http.ResponseWriter, r *http.Request, user User) {
fmt.Fprintln(w,b.String())
}
+func PreErrorJS(errmsg string, w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(500)
+ w.Write([]byte(`{"errmsg":"` + errmsg + `"}`))
+}
+
func PreErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, is_js string) {
w.WriteHeader(500)
if is_js == "0" {
diff --git a/gen_mysql.go b/gen_mysql.go
index e2f3b888..9956a83f 100644
--- a/gen_mysql.go
+++ b/gen_mysql.go
@@ -109,6 +109,7 @@ var delete_reply_stmt *sql.Stmt
var delete_topic_stmt *sql.Stmt
var delete_profile_reply_stmt *sql.Stmt
var delete_forum_perms_by_forum_stmt *sql.Stmt
+var delete_activity_stream_match_stmt *sql.Stmt
var report_exists_stmt *sql.Stmt
var group_count_stmt *sql.Stmt
var modlog_count_stmt *sql.Stmt
@@ -734,6 +735,12 @@ func _gen_mysql() (err error) {
return err
}
+ log.Print("Preparing delete_activity_stream_match statement.")
+ delete_activity_stream_match_stmt, err = db.Prepare("DELETE FROM `activity_stream_matches` WHERE `watcher` = ? AND `asid` = ?")
+ if err != nil {
+ return err
+ }
+
log.Print("Preparing report_exists statement.")
report_exists_stmt, err = db.Prepare("SELECT COUNT(*) AS `count` FROM `topics` WHERE `data` = ? AND `data` != '' AND `parentID` = 1")
if err != nil {
diff --git a/mysql.sql b/mysql.sql
index 48d98ddb..df3d4537 100644
--- a/mysql.sql
+++ b/mysql.sql
@@ -238,7 +238,7 @@ INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`) VALUES ('Awaiting
INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`,`tag`) VALUES ('Not Loggedin','{"ViewTopic":true}','{}','Guest');
INSERT INTO forums(`name`,`active`) VALUES ('Reports',0);
-INSERT INTO forums(`name`,`lastTopicTime`) VALUES ('General',UTC_TIMESTAMP());
+INSERT INTO forums(`name`,`lastTopicTime`,`lastTopicID`,`lastReplyer`,`lastReplyerID`,`lastTopic`) VALUES ('General',UTC_TIMESTAMP(),1,"Admin",1,'Test Topic');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (1,1,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"PinTopic":true,"CloseTopic":true}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (2,1,'{"ViewTopic":true,"CreateReply":true,"CloseTopic":true}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (3,1,'{}');
diff --git a/no_websockets.go b/no_websockets.go
index 5d76f851..62410c28 100644
--- a/no_websockets.go
+++ b/no_websockets.go
@@ -28,11 +28,11 @@ func (hub *WS_Hub) push_message(_ int, _ string) error {
return ws_nouser
}
-func(hub *WS_Hub) push_alert(_ int, _ string, _ string, _ int, _ int, _ int) error {
+func(hub *WS_Hub) push_alert(_ int, _ int, _ string, _ string, _ int, _ int, _ int) error {
return ws_nouser
}
-func(hub *WS_Hub) push_alerts(_ []int, _ string, _ string, _ int, _ int, _ int) error {
+func(hub *WS_Hub) push_alerts(_ []int, _ int, _ string, _ string, _ int, _ int, _ int) error {
return ws_nouser
}
diff --git a/public/global.js b/public/global.js
index b876ad45..e558e322 100644
--- a/public/global.js
+++ b/public/global.js
@@ -1,3 +1,4 @@
+'use strict';
var form_vars = {};
var alertList = [];
var alertCount = 0;
@@ -11,6 +12,14 @@ function post_link(event)
$.ajax({ url: form_action, type: "POST", dataType: "json", data: {js: "1"} });
}
+function bind_to_alerts() {
+ $(".alertItem.withAvatar a").click(function(event) {
+ event.stopPropagation();
+ $.ajax({ url: "/api/?action=set&module=dismiss-alert", type: "POST", dataType: "json", data: { asid: $(this).attr("data-asid") } });
+ });
+}
+
+// TO-DO: Add the ability for users to dismiss alerts
function load_alerts(menu_alerts)
{
var alertListNode = menu_alerts.getElementsByClassName("alertList")[0];
@@ -19,7 +28,7 @@ function load_alerts(menu_alerts)
$.ajax({
type: 'get',
dataType: 'json',
- url:'/api/?action=get&module=alerts&format=json',
+ url:'/api/?action=get&module=alerts',
success: function(data) {
if("errmsg" in data) {
alertListNode.innerHTML = "
"+data.errmsg+"
";
@@ -41,8 +50,8 @@ function load_alerts(menu_alerts)
}
if("avatar" in msg) {
- alist += "";
- alertList.push("");
+ alist += "";
+ alertList.push("");
anyAvatar = true
} else {
alist += "";
@@ -65,6 +74,8 @@ function load_alerts(menu_alerts)
menu_alerts.classList.remove("has_alerts");
}
alertCount = data.msgCount;
+
+ bind_to_alerts();
},
error: function(magic,theStatus,error) {
try {
@@ -123,26 +134,26 @@ $(document).ready(function(){
if ("msg" in data) {
var msg = data.msg
- if("sub" in data) {
- for(var i = 0; i < data.sub.length; i++) {
+ if("sub" in data)
+ for(var i = 0; i < data.sub.length; i++)
msg = msg.replace("\{"+i+"\}", data.sub[i]);
- }
- }
- if("avatar" in data) alertList.push("");
+ if("avatar" in data) alertList.push("");
else alertList.push("");
if(alertList.length > 8) alertList.shift();
//console.log("post alertList",alertList);
alertCount++;
var alist = ""
- for (var i = 0; i < alertList.length; i++) {
- alist += alertList[i];
- }
+ for (var i = 0; i < alertList.length; i++) alist += alertList[i];
//console.log(alist);
- $("#general_alerts").find(".alertList").html(alist); // Add support for other alert feeds like PM Alerts
- $("#general_alerts").find(".alert_counter").text(alertCount);
+ // TO-DO: Add support for other alert feeds like PM Alerts
+ var general_alerts = document.getElementById("general_alerts");
+ var alertListNode = general_alerts.getElementsByClassName("alertList")[0];
+ var alertCounterNode = general_alerts.getElementsByClassName("alert_counter")[0];
+ alertListNode.innerHTML = alist;
+ alertCounterNode.textContent = alertCount;
// TO-DO: Add some sort of notification queue to avoid flooding the end-user with notices?
// TO-DO: Use the site name instead of "Something Happened"
@@ -153,6 +164,8 @@ $(document).ready(function(){
});
setTimeout(n.close.bind(n), 8000);
}
+
+ bind_to_alerts();
}
}
@@ -337,6 +350,7 @@ $(document).ready(function(){
});
});
+ // This one's for Tempra Conflux
$(".ip_item").each(function(){
var ip = this.textContent;
if(ip.length > 10){
diff --git a/query_gen/main.go b/query_gen/main.go
index 6840e560..c671681d 100644
--- a/query_gen/main.go
+++ b/query_gen/main.go
@@ -391,6 +391,10 @@ func write_deletes(adapter qgen.DB_Adapter) error {
adapter.SimpleDelete("delete_forum_perms_by_forum","forums_permissions","fid = ?")
+ adapter.SimpleDelete("delete_activity_stream_match","activity_stream_matches","watcher = ? AND asid = ?")
+
+ //adapter.SimpleDelete("delete_activity_stream_matches_by_watcher","activity_stream_matches","watcher = ?")
+
return nil
}
diff --git a/routes.go b/routes.go
index 71b05b6a..912e82a5 100644
--- a/routes.go
+++ b/routes.go
@@ -841,7 +841,7 @@ func route_topic_create_submit(w http.ResponseWriter, r *http.Request, user User
return
}
- err = fstore.UpdateLastTopic(topic_name,int(lastId),user.Name,user.ID,"",fid)
+ err = fstore.UpdateLastTopic(topic_name,int(lastId),user.Name,user.ID,time.Now().Format("2006-01-02 15:04:05"),fid)
if err != nil && err != ErrNoRows {
InternalError(err,w)
}
@@ -896,8 +896,8 @@ func route_create_reply(w http.ResponseWriter, r *http.Request, user User) {
InternalError(err,w)
return
}
- _, err = update_forum_cache_stmt.Exec(topic.Title,tid,user.Name,user.ID,1)
- if err != nil {
+ err = fstore.UpdateLastTopic(topic.Title,tid,user.Name,user.ID,time.Now().Format("2006-01-02 15:04:05"),topic.ParentID)
+ if err != nil && err != ErrNoRows {
InternalError(err,w)
return
}
@@ -1027,7 +1027,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request, user User) {
}
// Live alerts, if the poster is online and WebSockets is enabled
- _ = ws_hub.push_alert(topic.CreatedBy,"like","topic",user.ID,topic.CreatedBy,tid)
+ _ = ws_hub.push_alert(topic.CreatedBy,int(lastId),"like","topic",user.ID,topic.CreatedBy,tid)
// Reload the topic...
err = topics.Load(tid)
@@ -1137,7 +1137,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request, user User)
}
// Live alerts, if the poster is online and WebSockets is enabled
- _ = ws_hub.push_alert(reply.CreatedBy,"like","post",user.ID,reply.CreatedBy,rid)
+ _ = ws_hub.push_alert(reply.CreatedBy,int(lastId),"like","post",user.ID,reply.CreatedBy,rid)
http.Redirect(w,r,"/topic/" + strconv.Itoa(reply.ParentID),http.StatusSeeOther)
}
@@ -1896,37 +1896,37 @@ func route_register_submit(w http.ResponseWriter, r *http.Request, user User) {
http.Redirect(w,r,"/",http.StatusSeeOther)
}
+// TO-DO: We don't need support XML here to support sitemaps, we could handle those elsewhere
var phrase_login_alerts []byte = []byte(`{"msgs":[{"msg":"Login to see your alerts","path":"/accounts/login"}]}`)
func route_api(w http.ResponseWriter, r *http.Request, user User) {
+ w.Header().Set("Content-Type","application/json")
err := r.ParseForm()
- format := r.FormValue("format")
- // TO-DO: Change is_js from a string to a boolean value
- var is_js string
- if format == "json" {
- is_js = "1"
- } else { // html
- is_js = "0"
- }
if err != nil {
- PreErrorJSQ("Bad Form",w,r,is_js)
+ PreErrorJS("Bad Form",w,r)
return
}
action := r.FormValue("action")
if action != "get" && action != "set" {
- PreErrorJSQ("Invalid Action",w,r,is_js)
+ PreErrorJS("Invalid Action",w,r)
return
}
module := r.FormValue("module")
switch(module) {
- case "alerts": // A feed of events tailored for a specific user
- if format != "json" {
- PreError("You can only fetch alerts in the JSON format!",w,r)
+ case "dismiss-alert":
+ asid, err := strconv.Atoi(r.FormValue("asid"))
+ if err != nil {
+ PreErrorJS("Invalid asid",w,r)
return
}
- w.Header().Set("Content-Type","application/json")
+ _, err = delete_activity_stream_match_stmt.Exec(user.ID,asid)
+ if err != nil {
+ InternalError(err,w)
+ return
+ }
+ case "alerts": // A feed of events tailored for a specific user
if !user.Loggedin {
w.Write(phrase_login_alerts)
return
@@ -1938,10 +1938,10 @@ func route_api(w http.ResponseWriter, r *http.Request, user User) {
err = get_activity_count_by_watcher_stmt.QueryRow(user.ID).Scan(&msgCount)
if err == ErrNoRows {
- PreError("Couldn't find the parent topic",w,r)
+ PreErrorJS("Couldn't find the parent topic",w,r)
return
} else if err != nil {
- InternalError(err,w)
+ InternalErrorJS(err,w,r)
return
}
@@ -1958,7 +1958,7 @@ func route_api(w http.ResponseWriter, r *http.Request, user User) {
InternalErrorJS(err,w,r)
return
}
- res, err := build_alert(event, elementType, actor_id, targetUser_id, elementID, user)
+ res, err := build_alert(asid, event, elementType, actor_id, targetUser_id, elementID, user)
if err != nil {
LocalErrorJS(err.Error(),w,r)
return
@@ -1988,6 +1988,6 @@ func route_api(w http.ResponseWriter, r *http.Request, user User) {
return
}*/
default:
- PreErrorJSQ("Invalid Module",w,r,is_js)
+ PreErrorJS("Invalid Module",w,r)
}
}
diff --git a/template_list.go b/template_list.go
index 914dc54d..409f1aa4 100644
--- a/template_list.go
+++ b/template_list.go
@@ -25,11 +25,9 @@ var header_8 []byte = []byte(`";
-
+var header_10 []byte = []byte(`
`)
var menu_0 []byte = []byte(`
@@ -618,9 +616,9 @@ var forum_6 []byte = []byte(`?page=`)
var forum_7 []byte = []byte(`">>
`)
var forum_8 []byte = []byte(`
-
-
+
diff --git a/templates/account-menu.html b/templates/account-menu.html
index 8e324573..01c77356 100644
--- a/templates/account-menu.html
+++ b/templates/account-menu.html
@@ -7,7 +7,8 @@
-
+
+ {{/** TO-DO: Add an alerts page with pagination to go through alerts which either don't fit in the alerts drop-down or which have already been dismissed. Bear in mind though that dismissed alerts older than two weeks might be purged to save space and to speed up the database **/}}
diff --git a/templates/forum.html b/templates/forum.html
index 5af2066c..1b6b8f25 100644
--- a/templates/forum.html
+++ b/templates/forum.html
@@ -4,8 +4,8 @@
{{if ne .LastPage .Page}}
{{end}}
-
-
{{.Title}}
+
+
{{if ne .CurrentUser.ID 0}}
{{if .CurrentUser.Perms.CreateTopic}}
diff --git a/templates/header.html b/templates/header.html
index bc3988cd..13d548ef 100644
--- a/templates/header.html
+++ b/templates/header.html
@@ -15,9 +15,7 @@
-
+
{{template "menu.html" .}}
diff --git a/themes/shadow/public/main.css b/themes/shadow/public/main.css
index 02d9ff2c..d666c3a9 100644
--- a/themes/shadow/public/main.css
+++ b/themes/shadow/public/main.css
@@ -129,6 +129,7 @@ a {
.opthead, .rowhead, .colstack_head {
padding-bottom: 0px;
padding-top: 3px !important;
+ white-space: nowrap;
}
.rowblock:not(.opthead):not(.colstack_head):not(.rowhead) .rowitem {
@@ -212,12 +213,24 @@ a {
.like_label:before {
content: "+1";
}
-.edit_label:before { content: "Edit"; }
-.trash_label:before { content: "Delete"; }
-.pin_label:before { content: "Pin"; }
-.unpin_label:before { content: "Unpin"; }
-.flag_label:before { content: "Flag"; }
-.level_label:before { content: "Level"; }
+.edit_label:before {
+ content: "Edit";
+}
+.trash_label:before {
+ content: "Delete";
+}
+.pin_label:before {
+ content: "Pin";
+}
+.unpin_label:before {
+ content: "Unpin";
+}
+.flag_label:before {
+ content: "Flag";
+}
+.level_label:before {
+ content: "Level";
+}
.like_count_label:before {
content: "likes";
@@ -252,11 +265,9 @@ a {
.formrow.real_first_child, .formrow:first-child {
margin-top: 8px;
}
-
.formrow.real_first_child .formitem, .formrow:first-child .formitem {
padding-top: 12px;
}
-
.formrow:last-child .formitem {
padding-bottom: 12px;
}
diff --git a/websockets.go b/websockets.go
index 5cd92c85..e2355b10 100644
--- a/websockets.go
+++ b/websockets.go
@@ -87,7 +87,7 @@ func (hub *WS_Hub) push_message(targetUser int, msg string) error {
return nil
}
-func(hub *WS_Hub) push_alert(targetUser int, event string, elementType string, actor_id int, targetUser_id int, elementID int) error {
+func(hub *WS_Hub) push_alert(targetUser int, asid int, event string, elementType string, actor_id int, targetUser_id int, elementID int) error {
//log.Print("In push_alert")
hub.users.RLock()
ws_user, ok := hub.online_users[targetUser]
@@ -97,7 +97,7 @@ func(hub *WS_Hub) push_alert(targetUser int, event string, elementType string, a
}
//log.Print("Building alert")
- alert, err := build_alert(event, elementType, actor_id, targetUser_id, elementID, *ws_user.User)
+ alert, err := build_alert(asid, event, elementType, actor_id, targetUser_id, elementID, *ws_user.User)
if err != nil {
return err
}
@@ -113,7 +113,7 @@ func(hub *WS_Hub) push_alert(targetUser int, event string, elementType string, a
return nil
}
-func(hub *WS_Hub) push_alerts(users []int, event string, elementType string, actor_id int, targetUser_id int, elementID int) error {
+func(hub *WS_Hub) push_alerts(users []int, asid int, event string, elementType string, actor_id int, targetUser_id int, elementID int) error {
//log.Print("In push_alerts")
var ws_users []*WS_User
hub.users.RLock()
@@ -133,7 +133,7 @@ func(hub *WS_Hub) push_alerts(users []int, event string, elementType string, act
}
//log.Print("Building alert")
- alert, err := build_alert(event, elementType, actor_id, targetUser_id, elementID, *ws_user.User)
+ alert, err := build_alert(asid, event, elementType, actor_id, targetUser_id, elementID, *ws_user.User)
if err != nil {
errs = append(errs,err)
}