Posts should now be properly rendered after an inline edit.
Moved uploadAttachment and deleteAttachment from route/topic.go to route/attachments.go Fixes #47
This commit is contained in:
parent
bf2af0ae96
commit
4813403fbb
|
@ -380,7 +380,7 @@ function mainInit(){
|
||||||
$(".topic_name").html(topicNameInput);
|
$(".topic_name").html(topicNameInput);
|
||||||
$(".topic_name").attr(topicNameInput);
|
$(".topic_name").attr(topicNameInput);
|
||||||
let topicContentInput = $('.topic_content_input').val();
|
let topicContentInput = $('.topic_content_input').val();
|
||||||
$(".topic_content").html(topicContentInput.replace("\n","<br><br>"));
|
$(".topic_content").html(quickParse(topicContentInput));
|
||||||
let topicStatusInput = $('.topic_status_input').val();
|
let topicStatusInput = $('.topic_status_input').val();
|
||||||
$(".topic_status_e:not(.open_edit)").html(topicStatusInput);
|
$(".topic_status_e:not(.open_edit)").html(topicStatusInput);
|
||||||
|
|
||||||
|
@ -408,6 +408,20 @@ function mainInit(){
|
||||||
$(this).closest('.deletable_block').remove();
|
$(this).closest('.deletable_block').remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Miniature implementation of the parser to avoid sending as much data back and forth
|
||||||
|
function quickParse(msg) {
|
||||||
|
msg = msg.replace(":)", "😀")
|
||||||
|
msg = msg.replace(":(", "😞")
|
||||||
|
msg = msg.replace(":D", "😃")
|
||||||
|
msg = msg.replace(":P", "😛")
|
||||||
|
msg = msg.replace(":O", "😲")
|
||||||
|
msg = msg.replace(":p", "😛")
|
||||||
|
msg = msg.replace(":o", "😲")
|
||||||
|
msg = msg.replace(";)", "😉")
|
||||||
|
msg = msg.replace("\n","<br>")
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
$(".edit_item").click(function(event){
|
$(".edit_item").click(function(event){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let blockParent = this.closest('.editable_parent');
|
let blockParent = this.closest('.editable_parent');
|
||||||
|
@ -418,18 +432,26 @@ function mainInit(){
|
||||||
if(srcNode!=null) source = srcNode.innerText;
|
if(srcNode!=null) source = srcNode.innerText;
|
||||||
else source = block.innerHTML;
|
else source = block.innerHTML;
|
||||||
// TODO: Add a client template for this
|
// TODO: Add a client template for this
|
||||||
block.innerHTML = "<textarea style='width: 99%;' name='edit_item'>" + source + "</textarea><br /><a href='" + this.closest('a').getAttribute("href") + "'><button class='submit_edit' type='submit'>Update</button></a>";
|
block.innerHTML = "<textarea style='width: 99%;' name='edit_item'>" + source + "</textarea><br><a href='" + this.closest('a').getAttribute("href") + "'><button class='submit_edit' type='submit'>Update</button></a>";
|
||||||
|
|
||||||
$(".submit_edit").click(function(event){
|
$(".submit_edit").click(function(event){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
block.classList.remove("in_edit");
|
block.classList.remove("in_edit");
|
||||||
let newContent = block.querySelector('textarea').value;
|
let newContent = block.querySelector('textarea').value;
|
||||||
block.innerHTML = newContent.replace("\n","<br><br>");
|
block.innerHTML = quickParse(newContent);
|
||||||
if(srcNode!=null) srcNode.innerText = newContent;
|
if(srcNode!=null) srcNode.innerText = newContent;
|
||||||
|
|
||||||
let formAction = this.closest('a').getAttribute("href");
|
let formAction = this.closest('a').getAttribute("href");
|
||||||
// TODO: Bounce the parsed post back and set innerHTML to it?
|
// 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 }
|
$.ajax({
|
||||||
|
url: formAction,
|
||||||
|
type: "POST",
|
||||||
|
dataType: "json",
|
||||||
|
data: { js: "1", edit_item: newContent },
|
||||||
|
error: ajaxError,
|
||||||
|
success: (data,status,xhr) => {
|
||||||
|
if("Content" in data) block.innerHTML = data["Content"];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,7 @@ package routes
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -84,3 +85,75 @@ func ShowAttachment(w http.ResponseWriter, r *http.Request, user common.User, fi
|
||||||
http.ServeFile(w, r, "./attachs/"+filename)
|
http.ServeFile(w, r, "./attachs/"+filename)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add a table for the files and lock the file row when performing tasks related to the file
|
||||||
|
func deleteAttachment(w http.ResponseWriter, r *http.Request, user common.User, aid int, js bool) common.RouteError {
|
||||||
|
attach, err := common.Attachments.Get(aid)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return common.NotFoundJSQ(w, r, nil, js)
|
||||||
|
} else if err != nil {
|
||||||
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = common.Attachments.Delete(aid)
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
|
|
||||||
|
count := common.Attachments.CountInPath(attach.Path)
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
|
if count == 0 {
|
||||||
|
err := os.Remove("./attachs/" + attach.Path)
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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/")
|
||||||
|
if rerr != nil {
|
||||||
|
return nil, rerr
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, filename := range files {
|
||||||
|
aid, err := common.Attachments.Add(sid, sectionTable, oid, originTable, user.ID, filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := pathMap[filename]
|
||||||
|
if ok {
|
||||||
|
pathMap[filename] += "," + strconv.Itoa(aid)
|
||||||
|
} else {
|
||||||
|
pathMap[filename] = strconv.Itoa(aid)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch originTable {
|
||||||
|
case "topics":
|
||||||
|
_, err = topicStmts.updateAttachs.Exec(common.Attachments.CountIn(originTable, oid), oid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
err = common.Topics.Reload(oid)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pathMap, nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -28,17 +29,24 @@ func init() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type JsonReply struct {
|
||||||
|
Content string
|
||||||
|
}
|
||||||
|
|
||||||
func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||||
|
// TODO: Use this
|
||||||
|
js := r.FormValue("js") == "1"
|
||||||
|
|
||||||
tid, err := strconv.Atoi(r.PostFormValue("tid"))
|
tid, err := strconv.Atoi(r.PostFormValue("tid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.PreError("Failed to convert the Topic ID", w, r)
|
return common.PreErrorJSQ("Failed to convert the Topic ID", w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
topic, err := common.Topics.Get(tid)
|
topic, err := common.Topics.Get(tid)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return common.PreError("Couldn't find the parent topic", w, r)
|
return common.PreErrorJSQ("Couldn't find the parent topic", w, r, js)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add hooks to make use of headerLite
|
// TODO: Add hooks to make use of headerLite
|
||||||
|
@ -47,22 +55,22 @@ func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User)
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ViewTopic || !user.Perms.CreateReply {
|
if !user.Perms.ViewTopic || !user.Perms.CreateReply {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissionsJSQ(w, r, user, js)
|
||||||
}
|
}
|
||||||
if topic.IsClosed && !user.Perms.CloseTopic {
|
if topic.IsClosed && !user.Perms.CloseTopic {
|
||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissionsJSQ(w, r, user, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
content := common.PreparseMessage(r.PostFormValue("reply-content"))
|
content := common.PreparseMessage(r.PostFormValue("reply-content"))
|
||||||
// TODO: Fully parse the post and put that in the parsed column
|
// TODO: Fully parse the post and put that in the parsed column
|
||||||
rid, err := common.Rstore.Create(topic, content, user.LastIP, user.ID)
|
rid, err := common.Rstore.Create(topic, content, user.LastIP, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
reply, err := common.Rstore.Get(rid)
|
reply, err := common.Rstore.Get(rid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.LocalError("Unable to load the reply", w, r, user)
|
return common.LocalErrorJSQ("Unable to load the reply", w, r, user, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the file attachments
|
// Handle the file attachments
|
||||||
|
@ -84,13 +92,13 @@ func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User)
|
||||||
if strings.HasPrefix(key, "pollinputitem[") {
|
if strings.HasPrefix(key, "pollinputitem[") {
|
||||||
halves := strings.Split(key, "[")
|
halves := strings.Split(key, "[")
|
||||||
if len(halves) != 2 {
|
if len(halves) != 2 {
|
||||||
return common.LocalError("Malformed pollinputitem", w, r, user)
|
return common.LocalErrorJSQ("Malformed pollinputitem", w, r, user, js)
|
||||||
}
|
}
|
||||||
halves[1] = strings.TrimSuffix(halves[1], "]")
|
halves[1] = strings.TrimSuffix(halves[1], "]")
|
||||||
|
|
||||||
index, err := strconv.Atoi(halves[1])
|
index, err := strconv.Atoi(halves[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.LocalError("Malformed pollinputitem", w, r, user)
|
return common.LocalErrorJSQ("Malformed pollinputitem", w, r, user, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are duplicates, then something has gone horribly wrong, so let's ignore them, this'll likely happen during an attack
|
// If there are duplicates, then something has gone horribly wrong, so let's ignore them, this'll likely happen during an attack
|
||||||
|
@ -115,25 +123,35 @@ func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User)
|
||||||
pollType := 0 // Basic single choice
|
pollType := 0 // Basic single choice
|
||||||
_, err := common.Polls.Create(reply, pollType, seqPollInputItems)
|
_, err := common.Polls.Create(reply, pollType, seqPollInputItems)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.LocalError("Failed to add poll to reply", w, r, user) // TODO: Might need to be an internal error as it could leave phantom polls?
|
return common.LocalErrorJSQ("Failed to add poll to reply", w, r, user, js) // TODO: Might need to be an internal error as it could leave phantom polls?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = common.Forums.UpdateLastTopic(tid, user.ID, topic.ParentID)
|
err = common.Forums.UpdateLastTopic(tid, user.ID, topic.ParentID)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
common.AddActivityAndNotifyAll(user.ID, topic.CreatedBy, "reply", "topic", tid)
|
common.AddActivityAndNotifyAll(user.ID, topic.CreatedBy, "reply", "topic", tid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
|
||||||
|
|
||||||
wcount := common.WordCount(content)
|
wcount := common.WordCount(content)
|
||||||
err = user.IncreasePostStats(wcount, false)
|
err = user.IncreasePostStats(wcount, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.InternalError(err, w, r)
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
|
|
||||||
|
if js {
|
||||||
|
outBytes, err := json.Marshal(JsonReply{common.ParseMessage(reply.Content, topic.ParentID, "forums")})
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
|
w.Write(outBytes)
|
||||||
|
} else {
|
||||||
|
// TODO: Send the user to the specific post on the page
|
||||||
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.PostCounter.Bump()
|
counters.PostCounter.Bump()
|
||||||
|
@ -143,25 +161,25 @@ func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User)
|
||||||
// TODO: Disable stat updates in posts handled by plugin_guilds
|
// TODO: Disable stat updates in posts handled by plugin_guilds
|
||||||
// TODO: Update the stats after edits so that we don't under or over decrement stats during deletes
|
// TODO: Update the stats after edits so that we don't under or over decrement stats during deletes
|
||||||
func ReplyEditSubmit(w http.ResponseWriter, r *http.Request, user common.User, srid string) common.RouteError {
|
func ReplyEditSubmit(w http.ResponseWriter, r *http.Request, user common.User, srid string) common.RouteError {
|
||||||
isJs := (r.PostFormValue("js") == "1")
|
js := (r.PostFormValue("js") == "1")
|
||||||
|
|
||||||
rid, err := strconv.Atoi(srid)
|
rid, err := strconv.Atoi(srid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs)
|
return common.PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
reply, err := common.Rstore.Get(rid)
|
reply, err := common.Rstore.Get(rid)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return common.PreErrorJSQ("The target reply doesn't exist.", w, r, isJs)
|
return common.PreErrorJSQ("The target reply doesn't exist.", w, r, js)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
topic, err := reply.Topic()
|
topic, err := reply.Topic()
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return common.PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
|
return common.PreErrorJSQ("The parent topic doesn't exist.", w, r, js)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add hooks to make use of headerLite
|
// TODO: Add hooks to make use of headerLite
|
||||||
|
@ -170,24 +188,37 @@ func ReplyEditSubmit(w http.ResponseWriter, r *http.Request, user common.User, s
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
if !user.Perms.ViewTopic || !user.Perms.EditReply {
|
if !user.Perms.ViewTopic || !user.Perms.EditReply {
|
||||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
return common.NoPermissionsJSQ(w, r, user, js)
|
||||||
}
|
}
|
||||||
if topic.IsClosed && !user.Perms.CloseTopic {
|
if topic.IsClosed && !user.Perms.CloseTopic {
|
||||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
return common.NoPermissionsJSQ(w, r, user, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = reply.SetPost(r.PostFormValue("edit_item"))
|
err = reply.SetPost(r.PostFormValue("edit_item"))
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return common.PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
|
return common.PreErrorJSQ("The parent topic doesn't exist.", w, r, js)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isJs {
|
// TODO: Avoid the load to get this faster?
|
||||||
|
reply, err = common.Rstore.Get(rid)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return common.PreErrorJSQ("The updated reply doesn't exist.", w, r, js)
|
||||||
|
} else if err != nil {
|
||||||
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !js {
|
||||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(topic.ID)+"#reply-"+strconv.Itoa(rid), http.StatusSeeOther)
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(topic.ID)+"#reply-"+strconv.Itoa(rid), http.StatusSeeOther)
|
||||||
} else {
|
} else {
|
||||||
w.Write(successJSONBytes)
|
outBytes, err := json.Marshal(JsonReply{common.ParseMessage(reply.Content, topic.ParentID, "forums")})
|
||||||
|
if err != nil {
|
||||||
|
return common.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
|
w.Write(outBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -569,78 +569,6 @@ func uploadFilesWithHash(w http.ResponseWriter, r *http.Request, user common.Use
|
||||||
return filenames, nil
|
return filenames, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add a table for the files and lock the file row when performing tasks related to the file
|
|
||||||
func deleteAttachment(w http.ResponseWriter, r *http.Request, user common.User, aid int, js bool) common.RouteError {
|
|
||||||
attach, err := common.Attachments.Get(aid)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return common.NotFoundJSQ(w, r, nil, js)
|
|
||||||
} else if err != nil {
|
|
||||||
return common.InternalErrorJSQ(err, w, r, js)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = common.Attachments.Delete(aid)
|
|
||||||
if err != nil {
|
|
||||||
return common.InternalErrorJSQ(err, w, r, js)
|
|
||||||
}
|
|
||||||
|
|
||||||
count := common.Attachments.CountInPath(attach.Path)
|
|
||||||
if err != nil {
|
|
||||||
return common.InternalErrorJSQ(err, w, r, js)
|
|
||||||
}
|
|
||||||
if count == 0 {
|
|
||||||
err := os.Remove("./attachs/" + attach.Path)
|
|
||||||
if err != nil {
|
|
||||||
return common.InternalErrorJSQ(err, w, r, js)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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/")
|
|
||||||
if rerr != nil {
|
|
||||||
return nil, rerr
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, filename := range files {
|
|
||||||
aid, err := common.Attachments.Add(sid, sectionTable, oid, originTable, user.ID, filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, common.InternalError(err, w, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, ok := pathMap[filename]
|
|
||||||
if ok {
|
|
||||||
pathMap[filename] += "," + strconv.Itoa(aid)
|
|
||||||
} else {
|
|
||||||
pathMap[filename] = strconv.Itoa(aid)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch originTable {
|
|
||||||
case "topics":
|
|
||||||
_, err = topicStmts.updateAttachs.Exec(common.Attachments.CountIn(originTable,oid), oid)
|
|
||||||
if err != nil {
|
|
||||||
return nil, common.InternalError(err, w, r)
|
|
||||||
}
|
|
||||||
err = common.Topics.Reload(oid)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pathMap, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Update the stats after edits so that we don't under or over decrement stats during deletes
|
// TODO: Update the stats after edits so that we don't under or over decrement stats during deletes
|
||||||
// TODO: Disable stat updates in posts handled by plugin_guilds
|
// TODO: Disable stat updates in posts handled by plugin_guilds
|
||||||
func EditTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError {
|
func EditTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError {
|
||||||
|
|
Loading…
Reference in New Issue