Fixed the forum editor on Cosora. More excavating coming up.
Tweaked the preparser to hopefully fix a few problems with the WYSIWYG Editor. Added BulkGetCopy to the ForumStores. Added InternalErrorXML and SilentInternalErrorXML. Tweaked the element queries so that the topic titles aren't truncated too short. Began refactoring the topic list logic, more to come here.
This commit is contained in:
parent
e919812ee2
commit
21999cd7c6
|
@ -1,13 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"./common"
|
||||
"./query_gen/lib"
|
||||
)
|
||||
|
||||
// TODO: Make this a static file somehow? Is it possible for us to put this file somewhere else?
|
||||
|
@ -23,8 +23,6 @@ Disallow: /report/
|
|||
return nil
|
||||
}
|
||||
|
||||
var xmlInternalError = []byte(`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<error>A problem has occured</error>`)
|
||||
var sitemapPageCap = 40000 // 40k, bump it up to 50k once we gzip this? Does brotli work on sitemaps?
|
||||
|
||||
func writeXMLHeader(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -110,11 +108,7 @@ func routeSitemapForums(w http.ResponseWriter, r *http.Request) common.RouteErro
|
|||
|
||||
group, err := common.Groups.Get(common.GuestUser.Group)
|
||||
if err != nil {
|
||||
log.Print("The guest group doesn't exist for some reason")
|
||||
// TODO: Add XML error handling to errors.go
|
||||
w.WriteHeader(500)
|
||||
w.Write(xmlInternalError)
|
||||
return common.HandledRouteError()
|
||||
return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r)
|
||||
}
|
||||
|
||||
writeXMLHeader(w, r)
|
||||
|
@ -145,54 +139,29 @@ func routeSitemapTopics(w http.ResponseWriter, r *http.Request) common.RouteErro
|
|||
</sitemap>
|
||||
`))
|
||||
}
|
||||
writeXMLHeader(w, r)
|
||||
|
||||
group, err := common.Groups.Get(common.GuestUser.Group)
|
||||
if err != nil {
|
||||
log.Print("The guest group doesn't exist for some reason")
|
||||
// TODO: Add XML error handling to errors.go
|
||||
w.WriteHeader(500)
|
||||
w.Write(xmlInternalError)
|
||||
return common.HandledRouteError()
|
||||
return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r)
|
||||
}
|
||||
|
||||
var argList []interface{}
|
||||
var qlist string
|
||||
var visibleForums []common.Forum
|
||||
for _, fid := range group.CanSee {
|
||||
forum := common.Forums.DirtyGet(fid)
|
||||
if forum.Name != "" && forum.Active {
|
||||
argList = append(argList, strconv.Itoa(fid))
|
||||
qlist += "?,"
|
||||
visibleForums = append(visibleForums, forum.Copy())
|
||||
}
|
||||
}
|
||||
if qlist != "" {
|
||||
qlist = qlist[0 : len(qlist)-1]
|
||||
}
|
||||
|
||||
// TODO: Abstract this
|
||||
topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "")
|
||||
topicCount, err := common.TopicCountInForums(visibleForums)
|
||||
if err != nil {
|
||||
// TODO: Add XML error handling to errors.go
|
||||
w.WriteHeader(500)
|
||||
w.Write(xmlInternalError)
|
||||
common.LogError(err)
|
||||
return common.HandledRouteError()
|
||||
}
|
||||
defer topicCountStmt.Close()
|
||||
|
||||
var topicCount int
|
||||
err = topicCountStmt.QueryRow(argList...).Scan(&topicCount)
|
||||
if err != nil && err != ErrNoRows {
|
||||
// TODO: Add XML error handling to errors.go
|
||||
w.WriteHeader(500)
|
||||
w.Write(xmlInternalError)
|
||||
common.LogError(err)
|
||||
return common.HandledRouteError()
|
||||
return common.InternalErrorXML(err, w, r)
|
||||
}
|
||||
|
||||
var pageCount = topicCount / sitemapPageCap
|
||||
//log.Print("topicCount", topicCount)
|
||||
//log.Print("pageCount", pageCount)
|
||||
writeXMLHeader(w, r)
|
||||
w.Write([]byte("<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n"))
|
||||
for i := 0; i <= pageCount; i++ {
|
||||
sitemapItem("sitemaps/topics_page_" + strconv.Itoa(i) + ".xml")
|
||||
|
@ -215,45 +184,21 @@ func routeSitemapTopic(w http.ResponseWriter, r *http.Request, page int) common.
|
|||
|
||||
group, err := common.Groups.Get(common.GuestUser.Group)
|
||||
if err != nil {
|
||||
log.Print("The guest group doesn't exist for some reason")
|
||||
// TODO: Add XML error handling to errors.go
|
||||
w.WriteHeader(500)
|
||||
w.Write(xmlInternalError)
|
||||
return common.HandledRouteError()
|
||||
return common.SilentInternalErrorXML(errors.New("The guest group doesn't exist for some reason"), w, r)
|
||||
}
|
||||
|
||||
var argList []interface{}
|
||||
var qlist string
|
||||
var visibleForums []common.Forum
|
||||
for _, fid := range group.CanSee {
|
||||
forum := common.Forums.DirtyGet(fid)
|
||||
if forum.Name != "" && forum.Active {
|
||||
argList = append(argList, strconv.Itoa(fid))
|
||||
qlist += "?,"
|
||||
visibleForums = append(visibleForums, forum.Copy())
|
||||
}
|
||||
}
|
||||
if qlist != "" {
|
||||
qlist = qlist[0 : len(qlist)-1]
|
||||
}
|
||||
|
||||
// TODO: Abstract this
|
||||
topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "")
|
||||
argList, qlist := common.ForumListToArgQ(visibleForums)
|
||||
topicCount, err := common.ArgQToTopicCount(argList, qlist)
|
||||
if err != nil {
|
||||
// TODO: Add XML error handling to errors.go
|
||||
w.WriteHeader(500)
|
||||
w.Write(xmlInternalError)
|
||||
common.LogError(err)
|
||||
return common.HandledRouteError()
|
||||
}
|
||||
defer topicCountStmt.Close()
|
||||
|
||||
var topicCount int
|
||||
err = topicCountStmt.QueryRow(argList...).Scan(&topicCount)
|
||||
if err != nil && err != ErrNoRows {
|
||||
// TODO: Add XML error handling to errors.go
|
||||
w.WriteHeader(500)
|
||||
w.Write(xmlInternalError)
|
||||
common.LogError(err)
|
||||
return common.HandledRouteError()
|
||||
return common.InternalErrorXML(err, w, r)
|
||||
}
|
||||
|
||||
var pageCount = topicCount / sitemapPageCap
|
||||
|
|
|
@ -99,6 +99,26 @@ func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) RouteErr
|
|||
return HandledRouteError()
|
||||
}
|
||||
|
||||
var xmlInternalError = []byte(`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<error>A problem has occured</error>`)
|
||||
|
||||
func InternalErrorXML(err error, w http.ResponseWriter, r *http.Request) RouteError {
|
||||
w.Header().Set("Content-Type", "application/xml")
|
||||
w.WriteHeader(500)
|
||||
w.Write(xmlInternalError)
|
||||
LogError(err)
|
||||
return HandledRouteError()
|
||||
}
|
||||
|
||||
// TODO: Stop killing the instance upon hitting an error with InternalError* and deprecate this
|
||||
func SilentInternalErrorXML(err error, w http.ResponseWriter, r *http.Request) RouteError {
|
||||
w.Header().Set("Content-Type", "application/xml")
|
||||
w.WriteHeader(500)
|
||||
w.Write(xmlInternalError)
|
||||
log.Print("InternalError: ", err)
|
||||
return HandledRouteError()
|
||||
}
|
||||
|
||||
func PreError(errmsg string, w http.ResponseWriter, r *http.Request) RouteError {
|
||||
w.WriteHeader(500)
|
||||
pi := Page{"Error", GuestUser, DefaultHeaderVar(), tList, errmsg}
|
||||
|
|
|
@ -27,6 +27,7 @@ type ForumStore interface {
|
|||
DirtyGet(id int) *Forum
|
||||
Get(id int) (*Forum, error)
|
||||
BypassGet(id int) (*Forum, error)
|
||||
BulkGetCopy(ids []int) (forums []Forum, err error)
|
||||
Reload(id int) error // ? - Should we move this to ForumCache? It might require us to do some unnecessary casting though
|
||||
//Update(Forum) error
|
||||
Delete(id int) error
|
||||
|
@ -188,6 +189,19 @@ func (mfs *MemoryForumStore) BypassGet(id int) (*Forum, error) {
|
|||
return forum, err
|
||||
}
|
||||
|
||||
// TODO: Optimise this
|
||||
func (mfs *MemoryForumStore) BulkGetCopy(ids []int) (forums []Forum, err error) {
|
||||
forums = make([]Forum, len(ids))
|
||||
for i, id := range ids {
|
||||
forum, err := mfs.Get(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
forums[i] = forum.Copy()
|
||||
}
|
||||
return forums, nil
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) Reload(id int) error {
|
||||
var forum = &Forum{ID: id}
|
||||
err := mfs.get.QueryRow(id).Scan(&forum.Name, &forum.Desc, &forum.Active, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopicID, &forum.LastReplyerID)
|
||||
|
|
|
@ -165,10 +165,10 @@ func shortcodeToUnicode(msg string) string {
|
|||
}
|
||||
|
||||
func PreparseMessage(msg string) string {
|
||||
msg = strings.Replace(msg, "<p><br>", "\n", -1)
|
||||
msg = strings.Replace(msg, "<p>", "\n", -1)
|
||||
msg = strings.Replace(msg, "<p><br>", "\n\n", -1)
|
||||
msg = strings.Replace(msg, "<p>", "\n\n", -1)
|
||||
msg = strings.Replace(msg, "</p>", "", -1)
|
||||
msg = strings.Replace(msg, "<br>", "\n", -1)
|
||||
msg = strings.Replace(msg, "<br>", "\n\n", -1)
|
||||
if Sshooks["preparse_preassign"] != nil {
|
||||
msg = RunSshook("preparse_preassign", msg)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package common
|
||||
|
||||
import "strconv"
|
||||
import "../query_gen/lib"
|
||||
|
||||
// Internal. Don't rely on it.
|
||||
func ForumListToArgQ(forums []Forum) (argList []interface{}, qlist string) {
|
||||
for _, forum := range forums {
|
||||
argList = append(argList, strconv.Itoa(forum.ID))
|
||||
qlist += "?,"
|
||||
}
|
||||
if qlist != "" {
|
||||
qlist = qlist[0 : len(qlist)-1]
|
||||
}
|
||||
return argList, qlist
|
||||
}
|
||||
|
||||
// Internal. Don't rely on it.
|
||||
func ArgQToTopicCount(argList []interface{}, qlist string) (topicCount int, err error) {
|
||||
topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer topicCountStmt.Close()
|
||||
|
||||
err = topicCountStmt.QueryRow(argList...).Scan(&topicCount)
|
||||
if err != nil && err != ErrNoRows {
|
||||
return 0, err
|
||||
}
|
||||
return topicCount, err
|
||||
}
|
||||
|
||||
func TopicCountInForums(forums []Forum) (topicCount int, err error) {
|
||||
return ArgQToTopicCount(ForumListToArgQ(forums))
|
||||
}
|
26
routes.go
26
routes.go
|
@ -135,8 +135,6 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo
|
|||
headerVars.Zone = "topics"
|
||||
headerVars.MetaDesc = headerVars.Settings["meta_desc"].(string)
|
||||
|
||||
// TODO: Add a function for the qlist stuff
|
||||
var qlist string
|
||||
group, err := common.Groups.Get(user.Group)
|
||||
if err != nil {
|
||||
log.Printf("Group #%d doesn't exist despite being used by common.User #%d", user.Group, user.ID)
|
||||
|
@ -156,39 +154,28 @@ func routeTopics(w http.ResponseWriter, r *http.Request, user common.User) commo
|
|||
|
||||
// We need a list of the visible forums for Quick Topic
|
||||
var forumList []common.Forum
|
||||
var argList []interface{}
|
||||
|
||||
for _, fid := range canSee {
|
||||
forum := common.Forums.DirtyGet(fid)
|
||||
if forum.Name != "" && forum.Active {
|
||||
// This bit's for quick topic, as we don't want unbound forums (e.g. ones in plugin_socialgroups) showing up
|
||||
// ? - Would it be useful, if we could post in social groups from /topics/?
|
||||
if (forum.ParentType == "" || forum.ParentType == "forum") && user.Loggedin {
|
||||
fcopy := forum.Copy()
|
||||
// TODO: Add a hook here for plugin_guilds
|
||||
forumList = append(forumList, fcopy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ? - Should we be showing plugin_guilds posts on /topics/?
|
||||
// ? - Would it be useful, if we could post in social groups from /topics/?
|
||||
argList = append(argList, strconv.Itoa(fid))
|
||||
qlist += "?,"
|
||||
}
|
||||
}
|
||||
argList, qlist := common.ForumListToArgQ(forumList)
|
||||
|
||||
// ! Need an inline error not a page level error
|
||||
if qlist == "" {
|
||||
return common.NotFound(w, r)
|
||||
}
|
||||
qlist = qlist[0 : len(qlist)-1]
|
||||
|
||||
// TODO: Abstract this
|
||||
topicCountStmt, err := qgen.Builder.SimpleCount("topics", "parentID IN("+qlist+")", "")
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer topicCountStmt.Close()
|
||||
|
||||
var topicCount int
|
||||
err = topicCountStmt.QueryRow(argList...).Scan(&topicCount)
|
||||
topicCount, err := common.ArgQToTopicCount(argList, qlist)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -304,7 +291,6 @@ func routeForum(w http.ResponseWriter, r *http.Request, user common.User, sfid s
|
|||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
|
||||
if !user.Perms.ViewTopic {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
|
|
@ -580,11 +580,10 @@ select, input, textarea, button {
|
|||
display: inline-block;
|
||||
}
|
||||
.topic_list .rowtopic span {
|
||||
max-width: 112px;
|
||||
max-width: 162px;
|
||||
overflow: hidden;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.topic_list .rowsmall {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
@ -596,17 +595,9 @@ select, input, textarea, button {
|
|||
font-size: 15px;
|
||||
}
|
||||
|
||||
.topic_list .rowsmall.starter:before {
|
||||
content: "\f007";
|
||||
font: normal normal normal 14px/1 FontAwesome;
|
||||
margin-right: 5px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.topic_list .lastReplyAt {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.topic_list .topic_status_e {
|
||||
display: none;
|
||||
}
|
||||
|
@ -615,7 +606,6 @@ select, input, textarea, button {
|
|||
flex: 1 1 calc(100% - 380px);
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.topic_inner_right {
|
||||
margin-left: 15%;
|
||||
margin-right: auto;
|
||||
|
@ -633,12 +623,9 @@ select, input, textarea, button {
|
|||
.topic_inner_right {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.topic_inner_right span {
|
||||
/*font-size: 15px;*/
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.topic_inner_right span:after {
|
||||
font-size: 13.5px;
|
||||
}
|
||||
|
@ -656,7 +643,6 @@ select, input, textarea, button {
|
|||
content: var(--likes-lang-string);
|
||||
color: var(--lightened-primary-text-color);
|
||||
}
|
||||
|
||||
.parent_forum {
|
||||
color: var(--lightened-primary-text-color);
|
||||
}
|
||||
|
@ -684,7 +670,7 @@ select, input, textarea, button {
|
|||
margin-top: 12px;
|
||||
margin-left: 8px;
|
||||
margin-bottom: 14px;
|
||||
width: 240px;
|
||||
width: 220px;
|
||||
}
|
||||
.topic_right > span {
|
||||
margin-top: 12px;
|
||||
|
@ -698,7 +684,7 @@ select, input, textarea, button {
|
|||
background-color: hsl(81, 60%, 95%);
|
||||
}
|
||||
|
||||
@element .topic_left .rowtopic and (min-width: 110px) {
|
||||
@element .topic_left .rowtopic and (min-width: 160px) {
|
||||
$this, $this span, $this + .parent_forum {
|
||||
float: left;
|
||||
}
|
||||
|
@ -712,6 +698,18 @@ select, input, textarea, button {
|
|||
}
|
||||
}
|
||||
|
||||
@element .topic_list and (min-width: 738px) {
|
||||
.topic_left .topic_inner_left {
|
||||
width: calc(240px + 1%);
|
||||
}
|
||||
}
|
||||
|
||||
@element .topic_list and (min-width: 875px) {
|
||||
.topic_left .topic_inner_left {
|
||||
width: calc(240px + 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.forum_list, .post_container {
|
||||
border: none;
|
||||
}
|
||||
|
@ -778,6 +776,9 @@ select, input, textarea, button {
|
|||
.userinfo .tag_block {
|
||||
color: var(--extra-lightened-primary-text-color);
|
||||
}
|
||||
.post_item .user_content {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.button_container {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
|
|
|
@ -77,10 +77,41 @@
|
|||
.formlist .formitem {
|
||||
padding: 8px;
|
||||
}
|
||||
#forum_quick_perms .panel_floater,
|
||||
.panel_theme_mobile, .panel_theme_tag {
|
||||
display: none;
|
||||
}
|
||||
#panel_plugins .rowitem {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#forum_quick_perms .formitem {
|
||||
display: flex;
|
||||
}
|
||||
#forum_quick_perms .formitem .edit_fields {
|
||||
margin-left: 3px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.perm_preset_no_access:before {
|
||||
content: "No Access";
|
||||
color: hsl(0,100%,20%);
|
||||
}
|
||||
.perm_preset_read_only:before, .perm_preset_can_post:before {
|
||||
color: hsl(120,100%,20%);
|
||||
}
|
||||
.perm_preset_read_only:before {
|
||||
content: "Read Only";
|
||||
}
|
||||
.perm_preset_can_post:before {
|
||||
content: "Can Post";
|
||||
}
|
||||
.perm_preset_can_moderate:before {
|
||||
content: "Can Moderate";
|
||||
color: hsl(240,100%,20%);
|
||||
}
|
||||
.perm_preset_custom:before {
|
||||
content: "Custom";
|
||||
color: hsl(0,0%,20%);
|
||||
}
|
||||
.perm_preset_default:before {
|
||||
content: "Default";
|
||||
}
|
Loading…
Reference in New Issue