diff --git a/cmd/query_gen/tables.go b/cmd/query_gen/tables.go
index ff17b372..123f4472 100644
--- a/cmd/query_gen/tables.go
+++ b/cmd/query_gen/tables.go
@@ -247,6 +247,7 @@ func createTables(adapter qgen.Adapter) error {
tblColumn{"lastUpdated", "datetime", 0, false, false, ""},
tblColumn{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"},
tblColumn{"likeCount", "int", 0, false, false, "0"},
+ tblColumn{"attachCount", "int", 0, false, false, "0"},
tblColumn{"words", "int", 0, false, false, "1"}, // ? - replies has a default of 1 and topics has 0? why?
tblColumn{"actionType", "varchar", 20, false, false, "''"},
tblColumn{"poll", "int", 0, false, false, "0"},
diff --git a/common/attachments.go b/common/attachments.go
index 35574e8d..1c9a63da 100644
--- a/common/attachments.go
+++ b/common/attachments.go
@@ -26,31 +26,31 @@ type AttachmentStore interface {
MiniTopicGet(id int) (alist []*MiniAttachment, err error)
Add(sectionID int, sectionTable string, originID int, originTable string, uploadedBy int, path string) (int, error)
GlobalCount() int
- CountInTopic(tid int) int
+ CountIn(originTable string, oid int) int
CountInPath(path string) int
Delete(aid int) error
}
type DefaultAttachmentStore struct {
- get *sql.Stmt
- getByTopic *sql.Stmt
- add *sql.Stmt
- count *sql.Stmt
- countInTopic *sql.Stmt
- countInPath *sql.Stmt
- delete *sql.Stmt
+ get *sql.Stmt
+ getByTopic *sql.Stmt
+ add *sql.Stmt
+ count *sql.Stmt
+ countIn *sql.Stmt
+ countInPath *sql.Stmt
+ delete *sql.Stmt
}
func NewDefaultAttachmentStore() (*DefaultAttachmentStore, error) {
acc := qgen.NewAcc()
return &DefaultAttachmentStore{
- get: acc.Select("attachments").Columns("originID, sectionID, uploadedBy, path").Where("attachID = ?").Prepare(),
- getByTopic: acc.Select("attachments").Columns("attachID, sectionID, uploadedBy, path").Where("originTable = 'topics' AND originID = ?").Prepare(),
- add: acc.Insert("attachments").Columns("sectionID, sectionTable, originID, originTable, uploadedBy, path").Fields("?,?,?,?,?,?").Prepare(),
- count: acc.Count("attachments").Prepare(),
- countInTopic: acc.Count("attachments").Where("originTable = 'topics' and originID = ?").Prepare(),
- countInPath: acc.Count("attachments").Where("path = ?").Prepare(),
- delete: acc.Delete("attachments").Where("attachID = ?").Prepare(),
+ get: acc.Select("attachments").Columns("originID, sectionID, uploadedBy, path").Where("attachID = ?").Prepare(),
+ getByTopic: acc.Select("attachments").Columns("attachID, sectionID, uploadedBy, path").Where("originTable = 'topics' AND originID = ?").Prepare(),
+ add: acc.Insert("attachments").Columns("sectionID, sectionTable, originID, originTable, uploadedBy, path").Fields("?,?,?,?,?,?").Prepare(),
+ count: acc.Count("attachments").Prepare(),
+ countIn: acc.Count("attachments").Where("originTable = ? and originID = ?").Prepare(),
+ countInPath: acc.Count("attachments").Where("path = ?").Prepare(),
+ delete: acc.Delete("attachments").Where("attachID = ?").Prepare(),
}, acc.FirstError()
}
@@ -107,8 +107,8 @@ func (store *DefaultAttachmentStore) GlobalCount() (count int) {
return count
}
-func (store *DefaultAttachmentStore) CountInTopic(tid int) (count int) {
- err := store.countInTopic.QueryRow(tid).Scan(&count)
+func (store *DefaultAttachmentStore) CountIn(originTable string, oid int) (count int) {
+ err := store.countIn.QueryRow(originTable, oid).Scan(&count)
if err != nil {
LogError(err)
}
diff --git a/common/parser.go b/common/parser.go
index 412e4c33..799f5ec9 100644
--- a/common/parser.go
+++ b/common/parser.go
@@ -587,7 +587,7 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
// TODO: Reduce the amount of code duplication
if media.Type == "attach" {
- addImage(media.URL + "?sectionID=" + strconv.Itoa(sectionID) + "§ionType=" + sectionType)
+ addImage(media.URL + "?sectionID=" + strconv.Itoa(sectionID) + "§ionType=" + sectionType)
continue
} else if media.Type == "image" {
addImage(media.URL)
diff --git a/langs/english.json b/langs/english.json
index 6ff4ecfa..163465b6 100644
--- a/langs/english.json
+++ b/langs/english.json
@@ -376,6 +376,10 @@
"topic.report_button_text":"Report",
"topic.flag_button_text":"Flag",
+ "topic.select_button_text":"Select",
+ "topic.copy_button_text":"Copy",
+ "topic.upload_button_text":"Upload",
+
"panel_rank_admins":"Admins",
"panel_rank_mods":"Mods",
"panel_rank_banned":"Banned",
diff --git a/patcher/patches.go b/patcher/patches.go
index 54a4f79e..b3a81f44 100644
--- a/patcher/patches.go
+++ b/patcher/patches.go
@@ -22,6 +22,7 @@ func init() {
addPatch(8, patch8)
addPatch(9, patch9)
addPatch(10, patch10)
+ addPatch(11, patch11)
}
func patch0(scanner *bufio.Scanner) (err error) {
@@ -29,7 +30,6 @@ func patch0(scanner *bufio.Scanner) (err error) {
if err != nil {
return err
}
-
err = execStmt(qgen.Builder.DropTable("menu_items"))
if err != nil {
return err
@@ -400,7 +400,6 @@ func patch10(scanner *bufio.Scanner) error {
return err
}
- // We could probably do something more efficient, but as there shouldn't be too many sites right now, we can probably cheat a little, otherwise it'll take forever to get things done
err = acc().Select("topics").Cols("tid").EachInt(func(tid int) error {
stid := itoa(tid)
@@ -430,3 +429,41 @@ func patch10(scanner *bufio.Scanner) error {
_, err = acc().Insert("updates").Columns("dbVersion").Fields("0").Exec()
return err
}
+
+func patch11(scanner *bufio.Scanner) error {
+ err := execStmt(qgen.Builder.AddColumn("replies", tblColumn{"attachCount", "int", 0, false, false, "0"}))
+ if err != nil {
+ return err
+ }
+
+ // Attachments for replies got the topicID rather than the replyID for a while in error, so we want to separate these out
+ _, err = acc().Update("attachments").Set("originTable = 'freplies'").Where("originTable = 'replies'").Exec()
+ if err != nil {
+ return err
+ }
+
+ // We could probably do something more efficient, but as there shouldn't be too many sites right now, we can probably cheat a little, otherwise it'll take forever to get things done
+ return acc().Select("topics").Cols("tid").EachInt(func(tid int) error {
+ stid := itoa(tid)
+
+ count, err := acc().Count("attachments").Where("originTable = 'topics' and originID = " + stid).Total()
+ if err != nil {
+ return err
+ }
+
+ _, err = acc().Update("topics").Set("attachCount = ?").Where("tid = " + stid).Exec(count)
+ return err
+ })
+
+ /*return acc().Select("replies").Cols("rid").EachInt(func(rid int) error {
+ srid := itoa(rid)
+
+ count, err := acc().Count("attachments").Where("originTable = 'replies' and originID = " + srid).Total()
+ if err != nil {
+ return err
+ }
+
+ _, err = acc().Update("replies").Set("attachCount = ?").Where("rid = " + srid).Exec(count)
+ return err
+ })*/
+}
diff --git a/public/global.js b/public/global.js
index b93b380e..7d86b796 100644
--- a/public/global.js
+++ b/public/global.js
@@ -380,7 +380,7 @@ function mainInit(){
$(".topic_name").html(topicNameInput);
$(".topic_name").attr(topicNameInput);
let topicContentInput = $('.topic_content_input').val();
- $(".topic_content").html(topicContentInput.replace(/(\n)+/g,"
"));
+ $(".topic_content").html(topicContentInput.replace("\n","
"));
let topicStatusInput = $('.topic_status_input').val();
$(".topic_status_e:not(.open_edit)").html(topicStatusInput);
@@ -410,18 +410,25 @@ function mainInit(){
$(".edit_item").click(function(event){
event.preventDefault();
- let blockParent = $(this).closest('.editable_parent');
- let block = blockParent.find('.editable_block').eq(0);
- block.html("
");
+ let blockParent = this.closest('.editable_parent');
+ let srcNode = blockParent.querySelector(".edit_source");
+ let block = blockParent.querySelector('.editable_block');
+ block.classList.add("in_edit");
+ let source = "";
+ if(srcNode!=null) source = srcNode.innerText;
+ else source = block.innerHTML;
+ // TODO: Add a client template for this
+ block.innerHTML = "
";
$(".submit_edit").click(function(event){
event.preventDefault();
- let blockParent = $(this).closest('.editable_parent');
- let block = blockParent.find('.editable_block').eq(0);
- let newContent = block.find('textarea').eq(0).val();
- block.html(newContent);
+ block.classList.remove("in_edit");
+ let newContent = block.querySelector('textarea').value;
+ block.innerHTML = newContent.replace("\n","
");
+ if(srcNode!=null) srcNode.innerText = newContent;
- var formAction = $(this).closest('a').attr("href");
+ let formAction = this.closest('a').getAttribute("href");
+ // TODO: Bounce the parsed post back and set innerHTML to it?
$.ajax({ url: formAction, type: "POST", error: ajaxError, dataType: "json", data: { isJs: "1", edit_item: newContent }
});
});
diff --git a/routes/reply.go b/routes/reply.go
index b570223a..42a8a9ba 100644
--- a/routes/reply.go
+++ b/routes/reply.go
@@ -8,8 +8,26 @@ import (
"github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/counters"
+ "github.com/Azareal/Gosora/query_gen"
)
+type ReplyStmts struct {
+ updateAttachs *sql.Stmt
+}
+
+var replyStmts ReplyStmts
+
+// TODO: Move this statement somewhere else
+func init() {
+ common.DbInits.Add(func(acc *qgen.Accumulator) error {
+ replyStmts = ReplyStmts{
+ // TODO: Less race-y attachment count updates
+ updateAttachs: acc.Update("replies").Set("attachCount = ?").Where("rid = ?").Prepare(),
+ }
+ return acc.FirstError()
+ })
+}
+
func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
tid, err := strconv.Atoi(r.PostFormValue("tid"))
if err != nil {
@@ -35,15 +53,6 @@ func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User)
return common.NoPermissions(w, r, user)
}
- // Handle the file attachments
- // TODO: Stop duplicating this code
- if user.Perms.UploadFiles {
- _, rerr := uploadAttachment(w, r, user, topic.ParentID, "forums", tid, "replies")
- if rerr != nil {
- return rerr
- }
- }
-
content := common.PreparseMessage(r.PostFormValue("reply-content"))
// TODO: Fully parse the post and put that in the parsed column
rid, err := common.Rstore.Create(topic, content, user.LastIP, user.ID)
@@ -55,6 +64,16 @@ func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User)
if err != nil {
return common.LocalError("Unable to load the reply", w, r, user)
}
+
+ // Handle the file attachments
+ // TODO: Stop duplicating this code
+ if user.Perms.UploadFiles {
+ _, rerr := uploadAttachment(w, r, user, topic.ParentID, "forums", rid, "replies")
+ if rerr != nil {
+ return rerr
+ }
+ }
+
if r.PostFormValue("has_poll") == "1" {
var maxPollOptions = 10
var pollInputItems = make(map[int]string)
diff --git a/routes/topic.go b/routes/topic.go
index c352961a..920bcf3b 100644
--- a/routes/topic.go
+++ b/routes/topic.go
@@ -599,6 +599,7 @@ func deleteAttachment(w http.ResponseWriter, r *http.Request, user common.User,
// TODO: Stop duplicating this code
// TODO: Use a transaction here
+// TODO: Move this function to neutral ground
func uploadAttachment(w http.ResponseWriter, r *http.Request, user common.User, sid int, sectionTable string, oid int, originTable string) (pathMap map[string]string, rerr common.RouteError) {
pathMap = make(map[string]string)
files, rerr := uploadFilesWithHash(w, r, user, "./attachs/")
@@ -619,9 +620,9 @@ func uploadAttachment(w http.ResponseWriter, r *http.Request, user common.User,
pathMap[filename] = strconv.Itoa(aid)
}
- switch sectionTable {
+ switch originTable {
case "topics":
- _, err = topicStmts.updateAttachs.Exec(common.Attachments.CountInTopic(oid), oid)
+ _, err = topicStmts.updateAttachs.Exec(common.Attachments.CountIn(originTable,oid), oid)
if err != nil {
return nil, common.InternalError(err, w, r)
}
@@ -629,6 +630,11 @@ func uploadAttachment(w http.ResponseWriter, r *http.Request, user common.User,
if err != nil {
return nil, common.InternalError(err, w, r)
}
+ case "replies":
+ _, err = replyStmts.updateAttachs.Exec(common.Attachments.CountIn(originTable,oid), oid)
+ if err != nil {
+ return nil, common.InternalError(err, w, r)
+ }
}
}
diff --git a/schema/mssql/query_replies.sql b/schema/mssql/query_replies.sql
index aa74cc37..96b5decc 100644
--- a/schema/mssql/query_replies.sql
+++ b/schema/mssql/query_replies.sql
@@ -10,6 +10,7 @@ CREATE TABLE [replies] (
[lastUpdated] datetime not null,
[ipaddress] nvarchar (200) DEFAULT '0.0.0.0.0' not null,
[likeCount] int DEFAULT 0 not null,
+ [attachCount] int DEFAULT 0 not null,
[words] int DEFAULT 1 not null,
[actionType] nvarchar (20) DEFAULT '' not null,
[poll] int DEFAULT 0 not null,
diff --git a/schema/mysql/query_replies.sql b/schema/mysql/query_replies.sql
index 636b46d5..65dbe737 100644
--- a/schema/mysql/query_replies.sql
+++ b/schema/mysql/query_replies.sql
@@ -10,6 +10,7 @@ CREATE TABLE `replies` (
`lastUpdated` datetime not null,
`ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null,
`likeCount` int DEFAULT 0 not null,
+ `attachCount` int DEFAULT 0 not null,
`words` int DEFAULT 1 not null,
`actionType` varchar(20) DEFAULT '' not null,
`poll` int DEFAULT 0 not null,
diff --git a/schema/pgsql/query_replies.sql b/schema/pgsql/query_replies.sql
index 6af1fbae..d15948e3 100644
--- a/schema/pgsql/query_replies.sql
+++ b/schema/pgsql/query_replies.sql
@@ -10,6 +10,7 @@ CREATE TABLE "replies" (
`lastUpdated` timestamp not null,
`ipaddress` varchar (200) DEFAULT '0.0.0.0.0' not null,
`likeCount` int DEFAULT 0 not null,
+ `attachCount` int DEFAULT 0 not null,
`words` int DEFAULT 1 not null,
`actionType` varchar (20) DEFAULT '' not null,
`poll` int DEFAULT 0 not null,
diff --git a/templates/topic_alt.html b/templates/topic_alt.html
index 3a192f79..e990c1b7 100644
--- a/templates/topic_alt.html
+++ b/templates/topic_alt.html
@@ -82,17 +82,17 @@
{{if .Topic.Attachments}}