We made more progress with topic views on Cosora. We accidentally broke Tempra Conflux's topic view in the process and we're planning to fix it in the following commit.
Added the ForumPermsStore. Fixed the creation dates of the posts. Added a skippable version of the vhooks. Social Groups now work again, although I'm planning to refactor them ;) Added more Markdown tests and fixed a few Markdown bugs.
This commit is contained in:
parent
0361310eb2
commit
6f45c62815
|
@ -49,6 +49,7 @@ func initDatabase() (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
fpstore = NewForumPermsStore()
|
||||||
|
|
||||||
log.Print("Loading the settings.")
|
log.Print("Loading the settings.")
|
||||||
err = LoadSettings()
|
err = LoadSettings()
|
||||||
|
|
25
extend.go
25
extend.go
|
@ -21,17 +21,23 @@ var hooks = map[string][]func(interface{}) interface{}{
|
||||||
|
|
||||||
// Hooks with a variable number of arguments
|
// Hooks with a variable number of arguments
|
||||||
var vhooks = map[string]func(...interface{}) interface{}{
|
var vhooks = map[string]func(...interface{}) interface{}{
|
||||||
"simple_forum_check_pre_perms": nil,
|
"intercept_build_widgets": nil,
|
||||||
"forum_check_pre_perms": nil,
|
"forum_trow_assign": nil,
|
||||||
"intercept_build_widgets": nil,
|
"topics_topic_row_assign": nil,
|
||||||
"forum_trow_assign": nil,
|
|
||||||
"topics_topic_row_assign": nil,
|
|
||||||
//"topics_user_row_assign": nil,
|
//"topics_user_row_assign": nil,
|
||||||
"topic_reply_row_assign": nil,
|
"topic_reply_row_assign": nil,
|
||||||
"create_group_preappend": nil, // What is this? Investigate!
|
"create_group_preappend": nil, // What is this? Investigate!
|
||||||
"topic_create_pre_loop": nil,
|
"topic_create_pre_loop": nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hooks with a variable number of arguments and return values for skipping the parent function and propagating an error upwards
|
||||||
|
var vhookSkippable = map[string]func(...interface{}) (bool, RouteError){
|
||||||
|
"simple_forum_check_pre_perms": nil,
|
||||||
|
"forum_check_pre_perms": nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
//var vhookErrorable = map[string]func(...interface{}) (interface{}, RouteError){}
|
||||||
|
|
||||||
// Coming Soon:
|
// Coming Soon:
|
||||||
type Message interface {
|
type Message interface {
|
||||||
ID() int
|
ID() int
|
||||||
|
@ -221,6 +227,9 @@ func (plugin *Plugin) AddHook(name string, handler interface{}) {
|
||||||
case func(...interface{}) interface{}:
|
case func(...interface{}) interface{}:
|
||||||
vhooks[name] = h
|
vhooks[name] = h
|
||||||
plugin.Hooks[name] = 0
|
plugin.Hooks[name] = 0
|
||||||
|
case func(...interface{}) (bool, RouteError):
|
||||||
|
vhookSkippable[name] = h
|
||||||
|
plugin.Hooks[name] = 0
|
||||||
default:
|
default:
|
||||||
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
||||||
}
|
}
|
||||||
|
@ -258,6 +267,8 @@ func (plugin *Plugin) RemoveHook(name string, handler interface{}) {
|
||||||
preRenderHooks[name] = hook
|
preRenderHooks[name] = hook
|
||||||
case func(...interface{}) interface{}:
|
case func(...interface{}) interface{}:
|
||||||
delete(vhooks, name)
|
delete(vhooks, name)
|
||||||
|
case func(...interface{}) (bool, RouteError):
|
||||||
|
delete(vhookSkippable, name)
|
||||||
default:
|
default:
|
||||||
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
||||||
}
|
}
|
||||||
|
@ -302,6 +313,10 @@ func runVhook(name string, data ...interface{}) interface{} {
|
||||||
return vhooks[name](data...)
|
return vhooks[name](data...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runVhookSkippable(name string, data ...interface{}) (bool, RouteError) {
|
||||||
|
return vhookSkippable[name](data...)
|
||||||
|
}
|
||||||
|
|
||||||
func runVhookNoreturn(name string, data ...interface{}) {
|
func runVhookNoreturn(name string, data ...interface{}) {
|
||||||
_ = vhooks[name](data...)
|
_ = vhooks[name](data...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
var fpstore *ForumPermsStore
|
||||||
|
|
||||||
|
type ForumPermsStore struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewForumPermsStore() *ForumPermsStore {
|
||||||
|
return &ForumPermsStore{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fps *ForumPermsStore) Get(fid int, gid int) (fperms ForumPerms, err error) {
|
||||||
|
// TODO: Add a hook here and have plugin_socialgroups use it
|
||||||
|
group, err := gstore.Get(gid)
|
||||||
|
if err != nil {
|
||||||
|
return fperms, ErrNoRows
|
||||||
|
}
|
||||||
|
return group.Forums[fid], nil
|
||||||
|
}
|
|
@ -532,8 +532,8 @@ func buildForumPermissions() error {
|
||||||
groups, err := gstore.GetAll()
|
groups, err := gstore.GetAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, group := range groups {
|
for _, group := range groups {
|
||||||
if dev.DebugMode {
|
if dev.DebugMode {
|
||||||
log.Print("Adding the forum permissions for Group #" + strconv.Itoa(group.ID) + " - " + group.Name)
|
log.Print("Adding the forum permissions for Group #" + strconv.Itoa(group.ID) + " - " + group.Name)
|
||||||
|
|
|
@ -45,7 +45,7 @@ func deactivateMarkdown() {
|
||||||
// An adapter for the parser, so that the parser can call itself recursively.
|
// An adapter for the parser, so that the parser can call itself recursively.
|
||||||
// This is less for the simple Markdown elements like bold and italics and more for the really complicated ones I plan on adding at some point.
|
// This is less for the simple Markdown elements like bold and italics and more for the really complicated ones I plan on adding at some point.
|
||||||
func markdownParse(msg string) string {
|
func markdownParse(msg string) string {
|
||||||
msg = strings.TrimSpace(_markdownParse(msg+" ", 0))
|
msg = strings.TrimSuffix(_markdownParse(msg+" ", 0), " ")
|
||||||
log.Print("final msg: ", msg)
|
log.Print("final msg: ", msg)
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
@ -172,9 +172,9 @@ func _markdownParse(msg string, n int) string {
|
||||||
|
|
||||||
index++
|
index++
|
||||||
|
|
||||||
//log.Print("preskip index",index)
|
//log.Print("preskip index: ", index)
|
||||||
//log.Print("preskip msg[index]",msg[index])
|
//log.Print("preskip msg[index]: ", msg[index])
|
||||||
//log.Print("preskip string(msg[index])",string(msg[index]))
|
//log.Print("preskip string(msg[index]): ", string(msg[index]))
|
||||||
index = markdownSkipUntilAsterisk(msg, index)
|
index = markdownSkipUntilAsterisk(msg, index)
|
||||||
|
|
||||||
if index >= len(msg) {
|
if index >= len(msg) {
|
||||||
|
@ -222,8 +222,8 @@ func _markdownParse(msg string, n int) string {
|
||||||
sIndex++
|
sIndex++
|
||||||
}
|
}
|
||||||
|
|
||||||
//log.Print("sIndex",sIndex)
|
//log.Print("sIndex: ", sIndex)
|
||||||
//log.Print("lIndex",lIndex)
|
//log.Print("lIndex: ", lIndex)
|
||||||
|
|
||||||
if lIndex <= sIndex {
|
if lIndex <= sIndex {
|
||||||
//log.Print("unclosed markdown element @ lIndex <= sIndex")
|
//log.Print("unclosed markdown element @ lIndex <= sIndex")
|
||||||
|
@ -241,19 +241,19 @@ func _markdownParse(msg string, n int) string {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
//log.Print("final sIndex",sIndex)
|
//log.Print("final sIndex: ", sIndex)
|
||||||
//log.Print("final lIndex",lIndex)
|
//log.Print("final lIndex: ",lIndex)
|
||||||
//log.Print("final index",index)
|
//log.Print("final index: ", index)
|
||||||
//log.Print("final msg[index]",msg[index])
|
//log.Print("final msg[index]: ", msg[index])
|
||||||
//log.Print("final string(msg[index])",string(msg[index]))
|
//log.Print("final string(msg[index]): ", string(msg[index]))
|
||||||
|
|
||||||
//log.Print("final msg[sIndex]",msg[sIndex])
|
//log.Print("final msg[sIndex]: ", msg[sIndex])
|
||||||
//log.Print("final string(msg[sIndex])",string(msg[sIndex]))
|
//log.Print("final string(msg[sIndex]): ", string(msg[sIndex]))
|
||||||
//log.Print("final msg[lIndex]",msg[lIndex])
|
//log.Print("final msg[lIndex]: ", msg[lIndex])
|
||||||
//log.Print("final string(msg[lIndex])",string(msg[lIndex]))
|
//log.Print("final string(msg[lIndex]): ", string(msg[lIndex]))
|
||||||
|
|
||||||
//log.Print("[]byte(msg[:sIndex])",[]byte(msg[:sIndex]))
|
//log.Print("[]byte(msg[:sIndex]): ", []byte(msg[:sIndex]))
|
||||||
//log.Print("[]byte(msg[:lIndex])",[]byte(msg[:lIndex]))
|
//log.Print("[]byte(msg[:lIndex]): ", []byte(msg[:lIndex]))
|
||||||
|
|
||||||
outbytes = append(outbytes, msg[lastElement:startIndex]...)
|
outbytes = append(outbytes, msg[lastElement:startIndex]...)
|
||||||
|
|
||||||
|
@ -278,13 +278,13 @@ func _markdownParse(msg string, n int) string {
|
||||||
index--
|
index--
|
||||||
case '\\':
|
case '\\':
|
||||||
if (index + 1) < len(msg) {
|
if (index + 1) < len(msg) {
|
||||||
outbytes = append(outbytes, msg[lastElement:index]...)
|
if isMarkdownStartChar(msg[index+1]) && msg[index+1] != '\\' {
|
||||||
index++
|
outbytes = append(outbytes, msg[lastElement:index]...)
|
||||||
lastElement = index
|
index++
|
||||||
|
lastElement = index
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//case '`':
|
//case '`':
|
||||||
//case '_':
|
|
||||||
//case '~':
|
|
||||||
//case 10: // newline
|
//case 10: // newline
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,6 +298,10 @@ func _markdownParse(msg string, n int) string {
|
||||||
return string(outbytes)
|
return string(outbytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isMarkdownStartChar(char byte) bool {
|
||||||
|
return char == '\\' || char == '~' || char == '_' || char == 10 || char == '`' || char == '*'
|
||||||
|
}
|
||||||
|
|
||||||
func markdownFindChar(data string, index int, char byte) bool {
|
func markdownFindChar(data string, index int, char byte) bool {
|
||||||
for ; index < len(data); index++ {
|
for ; index < len(data); index++ {
|
||||||
item := data[index]
|
item := data[index]
|
||||||
|
|
|
@ -561,7 +561,7 @@ func socialgroupsTopicCreatePreLoop(args ...interface{}) interface{} {
|
||||||
// TODO: Add privacy options
|
// TODO: Add privacy options
|
||||||
// TODO: Add support for multiple boards and add per-board simplified permissions
|
// TODO: Add support for multiple boards and add per-board simplified permissions
|
||||||
// TODO: Take isJs into account for routes which expect JSON responses
|
// TODO: Take isJs into account for routes which expect JSON responses
|
||||||
func socialgroupsForumCheck(args ...interface{}) (skip interface{}) {
|
func socialgroupsForumCheck(args ...interface{}) (skip bool, rerr RouteError) {
|
||||||
var r = args[1].(*http.Request)
|
var r = args[1].(*http.Request)
|
||||||
var fid = args[3].(*int)
|
var fid = args[3].(*int)
|
||||||
var forum = fstore.DirtyGet(*fid)
|
var forum = fstore.DirtyGet(*fid)
|
||||||
|
@ -569,19 +569,14 @@ func socialgroupsForumCheck(args ...interface{}) (skip interface{}) {
|
||||||
if forum.ParentType == "socialgroup" {
|
if forum.ParentType == "socialgroup" {
|
||||||
var err error
|
var err error
|
||||||
var w = args[0].(http.ResponseWriter)
|
var w = args[0].(http.ResponseWriter)
|
||||||
var success = args[4].(*bool)
|
|
||||||
sgItem, ok := r.Context().Value("socialgroups_current_group").(*SocialGroup)
|
sgItem, ok := r.Context().Value("socialgroups_current_group").(*SocialGroup)
|
||||||
if !ok {
|
if !ok {
|
||||||
sgItem, err = socialgroupsGetGroup(forum.ParentID)
|
sgItem, err = socialgroupsGetGroup(forum.ParentID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
InternalError(errors.New("Unable to find the parent group for a forum"), w, r)
|
return true, InternalError(errors.New("Unable to find the parent group for a forum"), w, r)
|
||||||
*success = false
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
if !sgItem.Active {
|
if !sgItem.Active {
|
||||||
NotFound(w, r)
|
return true, NotFound(w, r)
|
||||||
*success = false
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
r = r.WithContext(context.WithValue(r.Context(), "socialgroups_current_group", sgItem))
|
r = r.WithContext(context.WithValue(r.Context(), "socialgroups_current_group", sgItem))
|
||||||
}
|
}
|
||||||
|
@ -600,16 +595,16 @@ func socialgroupsForumCheck(args ...interface{}) (skip interface{}) {
|
||||||
|
|
||||||
err = socialgroupsGetMemberStmt.QueryRow(sgItem.ID, user.ID).Scan(&rank, &posts, &joinedAt)
|
err = socialgroupsGetMemberStmt.QueryRow(sgItem.ID, user.ID).Scan(&rank, &posts, &joinedAt)
|
||||||
if err != nil && err != ErrNoRows {
|
if err != nil && err != ErrNoRows {
|
||||||
*success = false
|
return true, InternalError(err, w, r)
|
||||||
InternalError(err, w, r)
|
|
||||||
return false
|
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return true
|
// TODO: Should we let admins / guests into public groups?
|
||||||
|
return true, LocalError("You're not part of this group!", w, r, *user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement bans properly by adding the Local Ban API in the next commit
|
// TODO: Implement bans properly by adding the Local Ban API in the next commit
|
||||||
|
// TODO: How does this even work? Refactor it along with the rest of this plugin!
|
||||||
if rank < 0 {
|
if rank < 0 {
|
||||||
return true
|
return true, LocalError("You've been banned from this group!", w, r, *user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basic permissions for members, more complicated permissions coming in the next commit!
|
// Basic permissions for members, more complicated permissions coming in the next commit!
|
||||||
|
@ -622,10 +617,10 @@ func socialgroupsForumCheck(args ...interface{}) (skip interface{}) {
|
||||||
} else {
|
} else {
|
||||||
overrideForumPerms(&user.Perms, true)
|
overrideForumPerms(&user.Perms, true)
|
||||||
}
|
}
|
||||||
return true
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Override redirects? I don't think this is needed quite yet
|
// TODO: Override redirects? I don't think this is needed quite yet
|
||||||
|
|
|
@ -214,6 +214,8 @@ func TestMarkdownRender(t *testing.T) {
|
||||||
msgList = addMEPair(msgList, "**hi*", "*<i>hi</i>")
|
msgList = addMEPair(msgList, "**hi*", "*<i>hi</i>")
|
||||||
msgList = addMEPair(msgList, "***hi***", "<b><i>hi</i></b>")
|
msgList = addMEPair(msgList, "***hi***", "<b><i>hi</i></b>")
|
||||||
msgList = addMEPair(msgList, "***h***", "<b><i>h</i></b>")
|
msgList = addMEPair(msgList, "***h***", "<b><i>h</i></b>")
|
||||||
|
msgList = addMEPair(msgList, "\\***h**\\*", "*<b>h</b>*")
|
||||||
|
msgList = addMEPair(msgList, "\\*\\**h*\\*\\*", "**<i>h</i>**")
|
||||||
msgList = addMEPair(msgList, "\\*hi\\*", "*hi*")
|
msgList = addMEPair(msgList, "\\*hi\\*", "*hi*")
|
||||||
msgList = addMEPair(msgList, "d\\*hi\\*", "d*hi*")
|
msgList = addMEPair(msgList, "d\\*hi\\*", "d*hi*")
|
||||||
msgList = addMEPair(msgList, "\\*hi\\*d", "*hi*d")
|
msgList = addMEPair(msgList, "\\*hi\\*d", "*hi*d")
|
||||||
|
@ -225,8 +227,10 @@ func TestMarkdownRender(t *testing.T) {
|
||||||
msgList = addMEPair(msgList, "\\\\\\d", "\\\\\\d")
|
msgList = addMEPair(msgList, "\\\\\\d", "\\\\\\d")
|
||||||
msgList = addMEPair(msgList, "d\\", "d\\")
|
msgList = addMEPair(msgList, "d\\", "d\\")
|
||||||
msgList = addMEPair(msgList, "\\d\\", "\\d\\")
|
msgList = addMEPair(msgList, "\\d\\", "\\d\\")
|
||||||
|
msgList = addMEPair(msgList, "*_hi_*", "<i><u>hi</u></i>")
|
||||||
msgList = addMEPair(msgList, "*~hi~*", "<i><s>hi</s></i>")
|
msgList = addMEPair(msgList, "*~hi~*", "<i><s>hi</s></i>")
|
||||||
msgList = addMEPair(msgList, "~*hi*~", "<s><i>hi</i></s>")
|
msgList = addMEPair(msgList, "~*hi*~", "<s><i>hi</i></s>")
|
||||||
|
msgList = addMEPair(msgList, "~ *hi* ~", "<s> <i>hi</i> </s>")
|
||||||
msgList = addMEPair(msgList, "_~hi~_", "<u><s>hi</s></u>")
|
msgList = addMEPair(msgList, "_~hi~_", "<u><s>hi</s></u>")
|
||||||
msgList = addMEPair(msgList, "***~hi~***", "<b><i><s>hi</s></i></b>")
|
msgList = addMEPair(msgList, "***~hi~***", "<b><i><s>hi</s></i></b>")
|
||||||
msgList = addMEPair(msgList, "**", "**")
|
msgList = addMEPair(msgList, "**", "**")
|
||||||
|
@ -255,4 +259,37 @@ func TestMarkdownRender(t *testing.T) {
|
||||||
t.Error("Expected:", item.Expects)
|
t.Error("Expected:", item.Expects)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, item := range msgList {
|
||||||
|
res = markdownParse("\n" + item.Msg)
|
||||||
|
if res != "\n"+item.Expects {
|
||||||
|
t.Error("Testing string '\n" + item.Msg + "'")
|
||||||
|
t.Error("Bad output:", "'"+res+"'")
|
||||||
|
//t.Error("Ouput in bytes:", []byte(res))
|
||||||
|
t.Error("Expected:", "\n"+item.Expects)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range msgList {
|
||||||
|
res = markdownParse("\t" + item.Msg)
|
||||||
|
if res != "\t"+item.Expects {
|
||||||
|
t.Error("Testing string '\t" + item.Msg + "'")
|
||||||
|
t.Error("Bad output:", "'"+res+"'")
|
||||||
|
//t.Error("Ouput in bytes:", []byte(res))
|
||||||
|
t.Error("Expected:", "\t"+item.Expects)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range msgList {
|
||||||
|
res = markdownParse("d" + item.Msg)
|
||||||
|
if res != "d"+item.Expects {
|
||||||
|
t.Error("Testing string 'd" + item.Msg + "'")
|
||||||
|
t.Error("Bad output:", "'"+res+"'")
|
||||||
|
//t.Error("Ouput in bytes:", []byte(res))
|
||||||
|
t.Error("Expected:", "d"+item.Expects)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Write suffix tests and double string tests
|
||||||
|
// TODO: Write similar prefix, suffix, and double string tests for plugin_bbcode. Ditto for the outer parser along with suitable tests for that like making sure the URL parser and media embedder works.
|
||||||
}
|
}
|
||||||
|
|
79
reply.go
79
reply.go
|
@ -6,52 +6,57 @@
|
||||||
*/
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// ? - Should we add a reply store to centralise all the reply logic? Would this cover profile replies too or would that be separate?
|
// ? - Should we add a reply store to centralise all the reply logic? Would this cover profile replies too or would that be separate?
|
||||||
var rstore ReplyStore
|
var rstore ReplyStore
|
||||||
var prstore ProfileReplyStore
|
var prstore ProfileReplyStore
|
||||||
|
|
||||||
type ReplyUser struct {
|
type ReplyUser struct {
|
||||||
ID int
|
ID int
|
||||||
ParentID int
|
ParentID int
|
||||||
Content string
|
Content string
|
||||||
ContentHtml string
|
ContentHtml string
|
||||||
CreatedBy int
|
CreatedBy int
|
||||||
UserLink string
|
UserLink string
|
||||||
CreatedByName string
|
CreatedByName string
|
||||||
Group int
|
Group int
|
||||||
CreatedAt string
|
CreatedAt time.Time
|
||||||
LastEdit int
|
RelativeCreatedAt string
|
||||||
LastEditBy int
|
LastEdit int
|
||||||
Avatar string
|
LastEditBy int
|
||||||
ClassName string
|
Avatar string
|
||||||
ContentLines int
|
ClassName string
|
||||||
Tag string
|
ContentLines int
|
||||||
URL string
|
Tag string
|
||||||
URLPrefix string
|
URL string
|
||||||
URLName string
|
URLPrefix string
|
||||||
Level int
|
URLName string
|
||||||
IPAddress string
|
Level int
|
||||||
Liked bool
|
IPAddress string
|
||||||
LikeCount int
|
Liked bool
|
||||||
ActionType string
|
LikeCount int
|
||||||
ActionIcon string
|
ActionType string
|
||||||
|
ActionIcon string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Reply struct {
|
type Reply struct {
|
||||||
ID int
|
ID int
|
||||||
ParentID int
|
ParentID int
|
||||||
Content string
|
Content string
|
||||||
CreatedBy int
|
CreatedBy int
|
||||||
Group int
|
Group int
|
||||||
CreatedAt string
|
CreatedAt time.Time
|
||||||
LastEdit int
|
RelativeCreatedAt string
|
||||||
LastEditBy int
|
LastEdit int
|
||||||
ContentLines int
|
LastEditBy int
|
||||||
IPAddress string
|
ContentLines int
|
||||||
Liked bool
|
IPAddress string
|
||||||
LikeCount int
|
Liked bool
|
||||||
|
LikeCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrAlreadyLiked = errors.New("You already liked this!")
|
var ErrAlreadyLiked = errors.New("You already liked this!")
|
||||||
|
|
43
routes.go
43
routes.go
|
@ -533,22 +533,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) RouteError
|
||||||
if postGroup.IsMod || postGroup.IsAdmin {
|
if postGroup.IsMod || postGroup.IsAdmin {
|
||||||
topic.ClassName = config.StaffCSS
|
topic.ClassName = config.StaffCSS
|
||||||
}
|
}
|
||||||
|
topic.RelativeCreatedAt = relativeTime(topic.CreatedAt)
|
||||||
/*if headerVars.Settings["url_tags"] == false {
|
|
||||||
topic.URLName = ""
|
|
||||||
} else {
|
|
||||||
topic.URL, ok = external_sites[topic.URLPrefix]
|
|
||||||
if !ok {
|
|
||||||
topic.URL = topic.URLName
|
|
||||||
} else {
|
|
||||||
topic.URL = topic.URL + topic.URLName
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
topic.CreatedAt, err = relativeTimeFromString(topic.CreatedAt)
|
|
||||||
if err != nil {
|
|
||||||
topic.CreatedAt = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make a function for this? Build a more sophisticated noavatar handling system?
|
// TODO: Make a function for this? Build a more sophisticated noavatar handling system?
|
||||||
if topic.Avatar != "" {
|
if topic.Avatar != "" {
|
||||||
|
@ -604,7 +589,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) RouteError
|
||||||
replyItem.ClassName = ""
|
replyItem.ClassName = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make a function for this? Build a more sophisticated noavatar handling system?
|
// TODO: Make a function for this? Build a more sophisticated noavatar handling system? Do bulk user loads and let the UserStore initialise this?
|
||||||
if replyItem.Avatar != "" {
|
if replyItem.Avatar != "" {
|
||||||
if replyItem.Avatar[0] == '.' {
|
if replyItem.Avatar[0] == '.' {
|
||||||
replyItem.Avatar = "/uploads/avatar_" + strconv.Itoa(replyItem.CreatedBy) + replyItem.Avatar
|
replyItem.Avatar = "/uploads/avatar_" + strconv.Itoa(replyItem.CreatedBy) + replyItem.Avatar
|
||||||
|
@ -614,22 +599,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) RouteError
|
||||||
}
|
}
|
||||||
|
|
||||||
replyItem.Tag = postGroup.Tag
|
replyItem.Tag = postGroup.Tag
|
||||||
|
replyItem.RelativeCreatedAt = relativeTime(replyItem.CreatedAt)
|
||||||
/*if headerVars.Settings["url_tags"] == false {
|
|
||||||
replyItem.URLName = ""
|
|
||||||
} else {
|
|
||||||
replyItem.URL, ok = external_sites[replyItem.URLPrefix]
|
|
||||||
if !ok {
|
|
||||||
replyItem.URL = replyItem.URLName
|
|
||||||
} else {
|
|
||||||
replyItem.URL = replyItem.URL + replyItem.URLName
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
replyItem.CreatedAt, err = relativeTimeFromString(replyItem.CreatedAt)
|
|
||||||
if err != nil {
|
|
||||||
replyItem.CreatedAt = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// We really shouldn't have inline HTML, we should do something about this...
|
// We really shouldn't have inline HTML, we should do something about this...
|
||||||
if replyItem.ActionType != "" {
|
if replyItem.ActionType != "" {
|
||||||
|
@ -683,7 +653,8 @@ func routeProfile(w http.ResponseWriter, r *http.Request, user User) RouteError
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var replyContent, replyCreatedByName, replyCreatedAt, replyAvatar, replyTag, replyClassName string
|
var replyCreatedAt time.Time
|
||||||
|
var replyContent, replyCreatedByName, replyRelativeCreatedAt, replyAvatar, replyTag, replyClassName string
|
||||||
var rid, replyCreatedBy, replyLastEdit, replyLastEditBy, replyLines, replyGroup int
|
var rid, replyCreatedBy, replyLastEdit, replyLastEditBy, replyLines, replyGroup int
|
||||||
var replyList []ReplyUser
|
var replyList []ReplyUser
|
||||||
|
|
||||||
|
@ -736,6 +707,7 @@ func routeProfile(w http.ResponseWriter, r *http.Request, user User) RouteError
|
||||||
} else {
|
} else {
|
||||||
replyClassName = ""
|
replyClassName = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if replyAvatar != "" {
|
if replyAvatar != "" {
|
||||||
if replyAvatar[0] == '.' {
|
if replyAvatar[0] == '.' {
|
||||||
replyAvatar = "/uploads/avatar_" + strconv.Itoa(replyCreatedBy) + replyAvatar
|
replyAvatar = "/uploads/avatar_" + strconv.Itoa(replyCreatedBy) + replyAvatar
|
||||||
|
@ -754,10 +726,11 @@ func routeProfile(w http.ResponseWriter, r *http.Request, user User) RouteError
|
||||||
|
|
||||||
replyLiked := false
|
replyLiked := false
|
||||||
replyLikeCount := 0
|
replyLikeCount := 0
|
||||||
|
replyRelativeCreatedAt = relativeTime(replyCreatedAt)
|
||||||
|
|
||||||
// TODO: Add a hook here
|
// TODO: Add a hook here
|
||||||
|
|
||||||
replyList = append(replyList, ReplyUser{rid, puser.ID, replyContent, parseMessage(replyContent, 0, ""), replyCreatedBy, buildProfileURL(nameToSlug(replyCreatedByName), replyCreatedBy), replyCreatedByName, replyGroup, replyCreatedAt, replyLastEdit, replyLastEditBy, replyAvatar, replyClassName, replyLines, replyTag, "", "", "", 0, "", replyLiked, replyLikeCount, "", ""})
|
replyList = append(replyList, ReplyUser{rid, puser.ID, replyContent, parseMessage(replyContent, 0, ""), replyCreatedBy, buildProfileURL(nameToSlug(replyCreatedByName), replyCreatedBy), replyCreatedByName, replyGroup, replyCreatedAt, replyRelativeCreatedAt, replyLastEdit, replyLastEditBy, replyAvatar, replyClassName, replyLines, replyTag, "", "", "", 0, "", replyLiked, replyLikeCount, "", ""})
|
||||||
}
|
}
|
||||||
err = rows.Err()
|
err = rows.Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -59,51 +59,51 @@ func simpleForumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fi
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is there a better way of doing the skip AND the success flag on this hook like multiple returns?
|
// Is there a better way of doing the skip AND the success flag on this hook like multiple returns?
|
||||||
if vhooks["simple_forum_check_pre_perms"] != nil {
|
if vhookSkippable["simple_forum_check_pre_perms"] != nil {
|
||||||
if runVhook("simple_forum_check_pre_perms", w, r, user, &fid, &rerr, &headerLite).(bool) {
|
var skip bool
|
||||||
|
skip, rerr = runVhookSkippable("simple_forum_check_pre_perms", w, r, user, &fid, &headerLite)
|
||||||
|
if skip {
|
||||||
return headerLite, rerr
|
return headerLite, rerr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group, err := gstore.Get(user.Group)
|
fperms, err := fpstore.Get(fid, user.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: Refactor this
|
// TODO: Refactor this
|
||||||
log.Printf("Group #%d doesn't exist despite being used by User #%d", user.Group, user.ID)
|
log.Printf("Unable to get the forum perms for Group #%d for User #%d", user.Group, user.ID)
|
||||||
return nil, PreError("Something weird happened", w, r)
|
return nil, PreError("Something weird happened", w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
fperms := group.Forums[fid]
|
|
||||||
cascadeForumPerms(fperms, user)
|
cascadeForumPerms(fperms, user)
|
||||||
return headerLite, nil
|
return headerLite, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func forumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerVars *HeaderVars, ferr RouteError) {
|
func forumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerVars *HeaderVars, rerr RouteError) {
|
||||||
headerVars, ferr = UserCheck(w, r, user)
|
headerVars, rerr = UserCheck(w, r, user)
|
||||||
if ferr != nil {
|
if rerr != nil {
|
||||||
return headerVars, ferr
|
return headerVars, rerr
|
||||||
}
|
}
|
||||||
if !fstore.Exists(fid) {
|
if !fstore.Exists(fid) {
|
||||||
return headerVars, NotFound(w, r)
|
return headerVars, NotFound(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if vhooks["forum_check_pre_perms"] != nil {
|
if vhookSkippable["forum_check_pre_perms"] != nil {
|
||||||
if runVhook("forum_check_pre_perms", w, r, user, &fid, &ferr, &headerVars).(bool) {
|
var skip bool
|
||||||
return headerVars, ferr
|
skip, rerr = runVhookSkippable("forum_check_pre_perms", w, r, user, &fid, &headerVars)
|
||||||
|
if skip {
|
||||||
|
return headerVars, rerr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group, err := gstore.Get(user.Group)
|
fperms, err := fpstore.Get(fid, user.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: Refactor this
|
// TODO: Refactor this
|
||||||
log.Printf("Group #%d doesn't exist despite being used by User #%d", user.Group, user.ID)
|
log.Printf("Unable to get the forum perms for Group #%d for User #%d", user.Group, user.ID)
|
||||||
return headerVars, PreError("Something weird happened", w, r)
|
return nil, PreError("Something weird happened", w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
fperms := group.Forums[fid]
|
|
||||||
//log.Printf("user.Perms: %+v\n", user.Perms)
|
//log.Printf("user.Perms: %+v\n", user.Perms)
|
||||||
//log.Printf("fperms: %+v\n", fperms)
|
//log.Printf("fperms: %+v\n", fperms)
|
||||||
cascadeForumPerms(fperms, user)
|
cascadeForumPerms(fperms, user)
|
||||||
return headerVars, ferr
|
return headerVars, rerr
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Put this on the user instance? Do we really want forum specific logic in there? Maybe, a method which spits a new pointer with the same contents as user?
|
// TODO: Put this on the user instance? Do we really want forum specific logic in there? Maybe, a method which spits a new pointer with the same contents as user?
|
||||||
|
|
|
@ -92,9 +92,10 @@ func compileTemplates() error {
|
||||||
|
|
||||||
log.Print("Compiling the templates")
|
log.Print("Compiling the templates")
|
||||||
|
|
||||||
topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, "Date", time.Now(), "Date", 0, "", "127.0.0.1", 0, 1, "classname", "weird-data", buildProfileURL("fake-user", 62), "Fake User", config.DefaultGroup, "", 0, "", "", "", "", "", 58, false}
|
var now = time.Now()
|
||||||
|
topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, now, relativeTime(now), now, relativeTime(now), 0, "", "127.0.0.1", 0, 1, "classname", "weird-data", buildProfileURL("fake-user", 62), "Fake User", config.DefaultGroup, "", 0, "", "", "", "", "", 58, false}
|
||||||
var replyList []ReplyUser
|
var replyList []ReplyUser
|
||||||
replyList = append(replyList, ReplyUser{0, 0, "Yo!", "Yo!", 0, "alice", "Alice", config.DefaultGroup, "", 0, 0, "", "", 0, "", "", "", "", 0, "127.0.0.1", false, 1, "", ""})
|
replyList = append(replyList, ReplyUser{0, 0, "Yo!", "Yo!", 0, "alice", "Alice", config.DefaultGroup, now, relativeTime(now), 0, 0, "", "", 0, "", "", "", "", 0, "127.0.0.1", false, 1, "", ""})
|
||||||
|
|
||||||
var varList = make(map[string]VarItem)
|
var varList = make(map[string]VarItem)
|
||||||
tpage := TopicPage{"Title", user, headerVars, replyList, topic, 1, 1}
|
tpage := TopicPage{"Title", user, headerVars, replyList, topic, 1, 1}
|
||||||
|
|
203
template_list.go
203
template_list.go
|
@ -351,7 +351,7 @@ var topic_alt_29 = []byte(`</textarea>
|
||||||
<div class="button_container">
|
<div class="button_container">
|
||||||
`)
|
`)
|
||||||
var topic_alt_30 = []byte(`<a href="/topic/like/submit/`)
|
var topic_alt_30 = []byte(`<a href="/topic/like/submit/`)
|
||||||
var topic_alt_31 = []byte(`" class="action_button">+1</a>`)
|
var topic_alt_31 = []byte(`" class="action_button like_item">+1</a>`)
|
||||||
var topic_alt_32 = []byte(`<a href="/topic/edit/`)
|
var topic_alt_32 = []byte(`<a href="/topic/edit/`)
|
||||||
var topic_alt_33 = []byte(`" class="action_button open_edit">Edit</a>`)
|
var topic_alt_33 = []byte(`" class="action_button open_edit">Edit</a>`)
|
||||||
var topic_alt_34 = []byte(`<a href="/topic/delete/submit/`)
|
var topic_alt_34 = []byte(`<a href="/topic/delete/submit/`)
|
||||||
|
@ -369,106 +369,129 @@ var topic_alt_44 = []byte(`
|
||||||
var topic_alt_45 = []byte(`?session=`)
|
var topic_alt_45 = []byte(`?session=`)
|
||||||
var topic_alt_46 = []byte(`&type=topic" class="action_button report_item">Report</a>
|
var topic_alt_46 = []byte(`&type=topic" class="action_button report_item">Report</a>
|
||||||
`)
|
`)
|
||||||
var topic_alt_47 = []byte(`<a class="action_button action_button_right like_count hide_on_micro">`)
|
var topic_alt_47 = []byte(`
|
||||||
var topic_alt_48 = []byte(` up</a>`)
|
<div class="action_button_right">
|
||||||
var topic_alt_49 = []byte(`
|
`)
|
||||||
<a class="action_button action_button_right created_at hide_on_mobile">`)
|
var topic_alt_48 = []byte(`<a class="action_button like_count hide_on_micro">`)
|
||||||
var topic_alt_50 = []byte(`</a>
|
var topic_alt_49 = []byte(`</a>`)
|
||||||
`)
|
var topic_alt_50 = []byte(`
|
||||||
var topic_alt_51 = []byte(`<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">`)
|
<a class="action_button created_at hide_on_mobile">`)
|
||||||
var topic_alt_52 = []byte(`</a>`)
|
var topic_alt_51 = []byte(`</a>
|
||||||
var topic_alt_53 = []byte(`
|
`)
|
||||||
|
var topic_alt_52 = []byte(`<a href="#" title="IP Address" class="action_button ip_item hide_on_mobile">`)
|
||||||
|
var topic_alt_53 = []byte(`</a>`)
|
||||||
|
var topic_alt_54 = []byte(`
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><div style="clear:both;"></div>
|
</div><div style="clear:both;"></div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
`)
|
`)
|
||||||
var topic_alt_54 = []byte(`
|
var topic_alt_55 = []byte(`
|
||||||
<article itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item `)
|
<article itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item `)
|
||||||
var topic_alt_55 = []byte(`action_item`)
|
var topic_alt_56 = []byte(`action_item`)
|
||||||
var topic_alt_56 = []byte(`">
|
var topic_alt_57 = []byte(`">
|
||||||
<div class="userinfo" aria-label="The information on the poster">
|
<div class="userinfo" aria-label="The information on the poster">
|
||||||
<div class="avatar_item" style="background-image: url(`)
|
<div class="avatar_item" style="background-image: url(`)
|
||||||
var topic_alt_57 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
var topic_alt_58 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||||
<a href="`)
|
<a href="`)
|
||||||
var topic_alt_58 = []byte(`" class="the_name" rel="author">`)
|
var topic_alt_59 = []byte(`" class="the_name" rel="author">`)
|
||||||
var topic_alt_59 = []byte(`</a>
|
var topic_alt_60 = []byte(`</a>
|
||||||
`)
|
`)
|
||||||
var topic_alt_60 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
var topic_alt_61 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||||
var topic_alt_61 = []byte(`</div><div class="tag_post"></div></div>`)
|
var topic_alt_62 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||||
var topic_alt_62 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
var topic_alt_63 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||||
var topic_alt_63 = []byte(`</div><div class="tag_post"></div></div>`)
|
var topic_alt_64 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||||
var topic_alt_64 = []byte(`
|
var topic_alt_65 = []byte(`
|
||||||
</div>
|
</div>
|
||||||
<div class="content_container" `)
|
<div class="content_container" `)
|
||||||
var topic_alt_65 = []byte(`style="margin-left: 0px;"`)
|
var topic_alt_66 = []byte(`style="margin-left: 0px;"`)
|
||||||
var topic_alt_66 = []byte(`>
|
var topic_alt_67 = []byte(`>
|
||||||
`)
|
`)
|
||||||
var topic_alt_67 = []byte(`
|
var topic_alt_68 = []byte(`
|
||||||
<span class="action_icon" style="font-size: 18px;padding-right: 5px;">`)
|
<span class="action_icon" style="font-size: 18px;padding-right: 5px;">`)
|
||||||
var topic_alt_68 = []byte(`</span>
|
|
||||||
<span itemprop="text">`)
|
|
||||||
var topic_alt_69 = []byte(`</span>
|
var topic_alt_69 = []byte(`</span>
|
||||||
|
<span itemprop="text">`)
|
||||||
|
var topic_alt_70 = []byte(`</span>
|
||||||
`)
|
`)
|
||||||
var topic_alt_70 = []byte(`
|
var topic_alt_71 = []byte(`
|
||||||
<div class="editable_block user_content" itemprop="text">`)
|
<div class="editable_block user_content" itemprop="text">`)
|
||||||
var topic_alt_71 = []byte(`</div>
|
var topic_alt_72 = []byte(`</div>
|
||||||
<div class="button_container">
|
<div class="button_container">
|
||||||
`)
|
`)
|
||||||
var topic_alt_72 = []byte(`<a href="/reply/like/submit/`)
|
var topic_alt_73 = []byte(`<a href="/reply/like/submit/`)
|
||||||
var topic_alt_73 = []byte(`" class="action_button">+1</a>`)
|
var topic_alt_74 = []byte(`" class="action_button like_item">+1</a>`)
|
||||||
var topic_alt_74 = []byte(`<a href="/reply/edit/submit/`)
|
var topic_alt_75 = []byte(`<a href="/reply/edit/submit/`)
|
||||||
var topic_alt_75 = []byte(`" class="action_button edit_item">Edit</a>`)
|
var topic_alt_76 = []byte(`" class="action_button edit_item">Edit</a>`)
|
||||||
var topic_alt_76 = []byte(`<a href="/reply/delete/submit/`)
|
var topic_alt_77 = []byte(`<a href="/reply/delete/submit/`)
|
||||||
var topic_alt_77 = []byte(`" class="action_button delete_item">Delete</a>`)
|
var topic_alt_78 = []byte(`" class="action_button delete_item">Delete</a>`)
|
||||||
var topic_alt_78 = []byte(`
|
var topic_alt_79 = []byte(`
|
||||||
<a href="/report/submit/`)
|
<a href="/report/submit/`)
|
||||||
var topic_alt_79 = []byte(`?session=`)
|
var topic_alt_80 = []byte(`?session=`)
|
||||||
var topic_alt_80 = []byte(`&type=reply" class="action_button report_item">Report</a>
|
var topic_alt_81 = []byte(`&type=reply" class="action_button report_item">Report</a>
|
||||||
`)
|
`)
|
||||||
var topic_alt_81 = []byte(`<a class="action_button action_button_right like_count hide_on_micro">`)
|
var topic_alt_82 = []byte(`
|
||||||
var topic_alt_82 = []byte(` up</a>`)
|
<div class="action_button_right">
|
||||||
var topic_alt_83 = []byte(`
|
`)
|
||||||
<a class="action_button action_button_right created_at hide_on_mobile">`)
|
var topic_alt_83 = []byte(`<a class="action_button like_count hide_on_micro">`)
|
||||||
var topic_alt_84 = []byte(`</a>
|
var topic_alt_84 = []byte(`</a>`)
|
||||||
`)
|
var topic_alt_85 = []byte(`
|
||||||
var topic_alt_85 = []byte(`<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">`)
|
<a class="action_button created_at hide_on_mobile">`)
|
||||||
var topic_alt_86 = []byte(`</a>`)
|
var topic_alt_86 = []byte(`</a>
|
||||||
var topic_alt_87 = []byte(`
|
`)
|
||||||
|
var topic_alt_87 = []byte(`<a href="#" title="IP Address" class="action_button ip_item hide_on_mobile">`)
|
||||||
|
var topic_alt_88 = []byte(`</a>`)
|
||||||
|
var topic_alt_89 = []byte(`
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`)
|
`)
|
||||||
var topic_alt_88 = []byte(`
|
var topic_alt_90 = []byte(`
|
||||||
</div>
|
</div>
|
||||||
<div style="clear:both;"></div>
|
<div style="clear:both;"></div>
|
||||||
</article>
|
</article>
|
||||||
`)
|
`)
|
||||||
var topic_alt_89 = []byte(`</div>
|
var topic_alt_91 = []byte(`</div>
|
||||||
|
|
||||||
`)
|
`)
|
||||||
var topic_alt_90 = []byte(`
|
|
||||||
<div class="rowblock topic_reply_form quick_create_form">
|
|
||||||
<form id="reply_form" enctype="multipart/form-data" action="/reply/create/" method="post"></form>
|
|
||||||
<input form="reply_form" name="tid" value='`)
|
|
||||||
var topic_alt_91 = []byte(`' type="hidden" />
|
|
||||||
<div class="formrow real_first_child">
|
|
||||||
<div class="formitem">
|
|
||||||
<textarea id="input_content" form="reply_form" name="reply-content" placeholder="Insert reply here" required></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="formrow quick_button_row">
|
|
||||||
<div class="formitem">
|
|
||||||
<button form="reply_form" name="reply-button" class="formbutton">Create Reply</button>
|
|
||||||
`)
|
|
||||||
var topic_alt_92 = []byte(`
|
var topic_alt_92 = []byte(`
|
||||||
<input name="upload_files" form="reply_form" id="upload_files" multiple type="file" style="display: none;" />
|
<div class="rowblock topic_reply_container">
|
||||||
<label for="upload_files" class="formbutton add_file_button">Add File</label>
|
<div class="userinfo" aria-label="The information on the poster">
|
||||||
<div id="upload_file_dock"></div>`)
|
<div class="avatar_item" style="background-image: url(`)
|
||||||
var topic_alt_93 = []byte(`
|
var topic_alt_93 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||||
|
<a href="`)
|
||||||
|
var topic_alt_94 = []byte(`" class="the_name" rel="author">`)
|
||||||
|
var topic_alt_95 = []byte(`</a>
|
||||||
|
`)
|
||||||
|
var topic_alt_96 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||||
|
var topic_alt_97 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||||
|
var topic_alt_98 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||||
|
var topic_alt_99 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||||
|
var topic_alt_100 = []byte(`
|
||||||
|
</div>
|
||||||
|
<div class="rowblock topic_reply_form quick_create_form">
|
||||||
|
<form id="reply_form" enctype="multipart/form-data" action="/reply/create/" method="post"></form>
|
||||||
|
<input form="reply_form" name="tid" value='`)
|
||||||
|
var topic_alt_101 = []byte(`' type="hidden" />
|
||||||
|
<div class="formrow real_first_child">
|
||||||
|
<div class="formitem">
|
||||||
|
<textarea id="input_content" form="reply_form" name="reply-content" placeholder="What do you think?" required></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow quick_button_row">
|
||||||
|
<div class="formitem">
|
||||||
|
<button form="reply_form" name="reply-button" class="formbutton">Create Reply</button>
|
||||||
|
`)
|
||||||
|
var topic_alt_102 = []byte(`
|
||||||
|
<input name="upload_files" form="reply_form" id="upload_files" multiple type="file" style="display: none;" />
|
||||||
|
<label for="upload_files" class="formbutton add_file_button">Add File</label>
|
||||||
|
<div id="upload_file_dock"></div>`)
|
||||||
|
var topic_alt_103 = []byte(`
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`)
|
`)
|
||||||
var topic_alt_94 = []byte(`
|
var topic_alt_104 = []byte(`
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
@ -738,40 +761,40 @@ var topics_10 = []byte(`<img class="little_row_avatar" src="`)
|
||||||
var topics_11 = []byte(`" height="64" />`)
|
var topics_11 = []byte(`" height="64" />`)
|
||||||
var topics_12 = []byte(`
|
var topics_12 = []byte(`
|
||||||
<div class="main_form">
|
<div class="main_form">
|
||||||
<div class="topic_meta">
|
<div class="topic_meta">
|
||||||
<div class="formrow topic_board_row real_first_child">
|
<div class="formrow topic_board_row real_first_child">
|
||||||
<div class="formitem"><select form="topic_create_form_form" id="topic_board_input" name="topic-board">
|
<div class="formitem"><select form="topic_create_form_form" id="topic_board_input" name="topic-board">
|
||||||
`)
|
`)
|
||||||
var topics_13 = []byte(`<option `)
|
var topics_13 = []byte(`<option `)
|
||||||
var topics_14 = []byte(`selected`)
|
var topics_14 = []byte(`selected`)
|
||||||
var topics_15 = []byte(` value="`)
|
var topics_15 = []byte(` value="`)
|
||||||
var topics_16 = []byte(`">`)
|
var topics_16 = []byte(`">`)
|
||||||
var topics_17 = []byte(`</option>`)
|
var topics_17 = []byte(`</option>`)
|
||||||
var topics_18 = []byte(`
|
var topics_18 = []byte(`
|
||||||
</select></div>
|
</select></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow topic_name_row">
|
<div class="formrow topic_name_row">
|
||||||
<div class="formitem">
|
<div class="formitem">
|
||||||
<input form="topic_create_form_form" name="topic-name" placeholder="What's up?" required>
|
<input form="topic_create_form_form" name="topic-name" placeholder="What's up?" required>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="formrow topic_content_row">
|
||||||
<div class="formrow topic_content_row">
|
<div class="formitem">
|
||||||
<div class="formitem">
|
<textarea form="topic_create_form_form" id="input_content" name="topic-content" placeholder="Insert post here" required></textarea>
|
||||||
<textarea form="topic_create_form_form" id="input_content" name="topic-content" placeholder="Insert post here" required></textarea>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="formrow quick_button_row">
|
||||||
<div class="formrow quick_button_row">
|
<div class="formitem">
|
||||||
<div class="formitem">
|
<button form="topic_create_form_form" class="formbutton">Create Topic</button>
|
||||||
<button form="topic_create_form_form" class="formbutton">Create Topic</button>
|
`)
|
||||||
`)
|
|
||||||
var topics_19 = []byte(`
|
var topics_19 = []byte(`
|
||||||
<input name="upload_files" form="topic_create_form_form" id="upload_files" multiple type="file" style="display: none;" />
|
<input name="upload_files" form="topic_create_form_form" id="upload_files" multiple type="file" style="display: none;" />
|
||||||
<label for="upload_files" class="formbutton add_file_button">Add File</label>
|
<label for="upload_files" class="formbutton add_file_button">Add File</label>
|
||||||
<div id="upload_file_dock"></div>`)
|
<div id="upload_file_dock"></div>`)
|
||||||
var topics_20 = []byte(`
|
var topics_20 = []byte(`
|
||||||
<button class="formbutton close_form">Cancel</button>
|
<button class="formbutton close_form">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
// Code generated by Gosora. More below:
|
// Code generated by Gosora. More below:
|
||||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||||
package main
|
package main
|
||||||
import "net/http"
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
// nolint
|
// nolint
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -182,108 +182,126 @@ w.Write(topic_alt_45)
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
w.Write(topic_alt_46)
|
w.Write(topic_alt_46)
|
||||||
}
|
}
|
||||||
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
|
||||||
w.Write(topic_alt_47)
|
w.Write(topic_alt_47)
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.LikeCount)))
|
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
||||||
w.Write(topic_alt_48)
|
w.Write(topic_alt_48)
|
||||||
}
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.LikeCount)))
|
||||||
w.Write(topic_alt_49)
|
w.Write(topic_alt_49)
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedAt))
|
|
||||||
w.Write(topic_alt_50)
|
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
|
||||||
w.Write(topic_alt_51)
|
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
|
||||||
w.Write(topic_alt_52)
|
|
||||||
}
|
}
|
||||||
|
w.Write(topic_alt_50)
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.RelativeCreatedAt))
|
||||||
|
w.Write(topic_alt_51)
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||||
|
w.Write(topic_alt_52)
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||||
w.Write(topic_alt_53)
|
w.Write(topic_alt_53)
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_54)
|
||||||
if len(tmpl_topic_alt_vars.ItemList) != 0 {
|
if len(tmpl_topic_alt_vars.ItemList) != 0 {
|
||||||
for _, item := range tmpl_topic_alt_vars.ItemList {
|
for _, item := range tmpl_topic_alt_vars.ItemList {
|
||||||
w.Write(topic_alt_54)
|
|
||||||
if item.ActionType != "" {
|
|
||||||
w.Write(topic_alt_55)
|
w.Write(topic_alt_55)
|
||||||
}
|
if item.ActionType != "" {
|
||||||
w.Write(topic_alt_56)
|
w.Write(topic_alt_56)
|
||||||
w.Write([]byte(item.Avatar))
|
}
|
||||||
w.Write(topic_alt_57)
|
w.Write(topic_alt_57)
|
||||||
w.Write([]byte(item.UserLink))
|
w.Write([]byte(item.Avatar))
|
||||||
w.Write(topic_alt_58)
|
w.Write(topic_alt_58)
|
||||||
w.Write([]byte(item.CreatedByName))
|
w.Write([]byte(item.UserLink))
|
||||||
w.Write(topic_alt_59)
|
w.Write(topic_alt_59)
|
||||||
if item.Tag != "" {
|
w.Write([]byte(item.CreatedByName))
|
||||||
w.Write(topic_alt_60)
|
w.Write(topic_alt_60)
|
||||||
w.Write([]byte(item.Tag))
|
if item.Tag != "" {
|
||||||
w.Write(topic_alt_61)
|
w.Write(topic_alt_61)
|
||||||
} else {
|
w.Write([]byte(item.Tag))
|
||||||
w.Write(topic_alt_62)
|
w.Write(topic_alt_62)
|
||||||
w.Write([]byte(strconv.Itoa(item.Level)))
|
|
||||||
w.Write(topic_alt_63)
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_64)
|
|
||||||
if item.ActionType != "" {
|
|
||||||
w.Write(topic_alt_65)
|
|
||||||
}
|
|
||||||
w.Write(topic_alt_66)
|
|
||||||
if item.ActionType != "" {
|
|
||||||
w.Write(topic_alt_67)
|
|
||||||
w.Write([]byte(item.ActionIcon))
|
|
||||||
w.Write(topic_alt_68)
|
|
||||||
w.Write([]byte(item.ActionType))
|
|
||||||
w.Write(topic_alt_69)
|
|
||||||
} else {
|
} else {
|
||||||
|
w.Write(topic_alt_63)
|
||||||
|
w.Write([]byte(strconv.Itoa(item.Level)))
|
||||||
|
w.Write(topic_alt_64)
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_65)
|
||||||
|
if item.ActionType != "" {
|
||||||
|
w.Write(topic_alt_66)
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_67)
|
||||||
|
if item.ActionType != "" {
|
||||||
|
w.Write(topic_alt_68)
|
||||||
|
w.Write([]byte(item.ActionIcon))
|
||||||
|
w.Write(topic_alt_69)
|
||||||
|
w.Write([]byte(item.ActionType))
|
||||||
w.Write(topic_alt_70)
|
w.Write(topic_alt_70)
|
||||||
w.Write([]byte(item.ContentHtml))
|
} else {
|
||||||
w.Write(topic_alt_71)
|
w.Write(topic_alt_71)
|
||||||
|
w.Write([]byte(item.ContentHtml))
|
||||||
|
w.Write(topic_alt_72)
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
||||||
w.Write(topic_alt_72)
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(topic_alt_73)
|
w.Write(topic_alt_73)
|
||||||
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
|
w.Write(topic_alt_74)
|
||||||
}
|
}
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditReply {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.EditReply {
|
||||||
w.Write(topic_alt_74)
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(topic_alt_75)
|
w.Write(topic_alt_75)
|
||||||
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
|
w.Write(topic_alt_76)
|
||||||
}
|
}
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteReply {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteReply {
|
||||||
w.Write(topic_alt_76)
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
|
||||||
w.Write(topic_alt_77)
|
w.Write(topic_alt_77)
|
||||||
}
|
|
||||||
w.Write(topic_alt_78)
|
|
||||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
|
w.Write(topic_alt_78)
|
||||||
|
}
|
||||||
w.Write(topic_alt_79)
|
w.Write(topic_alt_79)
|
||||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||||
w.Write(topic_alt_80)
|
w.Write(topic_alt_80)
|
||||||
}
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||||
if item.LikeCount > 0 {
|
|
||||||
w.Write(topic_alt_81)
|
w.Write(topic_alt_81)
|
||||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
}
|
||||||
w.Write(topic_alt_82)
|
w.Write(topic_alt_82)
|
||||||
}
|
if item.LikeCount > 0 {
|
||||||
w.Write(topic_alt_83)
|
w.Write(topic_alt_83)
|
||||||
w.Write([]byte(item.CreatedAt))
|
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||||
w.Write(topic_alt_84)
|
w.Write(topic_alt_84)
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
}
|
||||||
w.Write(topic_alt_85)
|
w.Write(topic_alt_85)
|
||||||
w.Write([]byte(item.IPAddress))
|
w.Write([]byte(item.RelativeCreatedAt))
|
||||||
w.Write(topic_alt_86)
|
w.Write(topic_alt_86)
|
||||||
}
|
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||||
w.Write(topic_alt_87)
|
w.Write(topic_alt_87)
|
||||||
}
|
w.Write([]byte(item.IPAddress))
|
||||||
w.Write(topic_alt_88)
|
w.Write(topic_alt_88)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
w.Write(topic_alt_89)
|
w.Write(topic_alt_89)
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply {
|
}
|
||||||
w.Write(topic_alt_90)
|
w.Write(topic_alt_90)
|
||||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
}
|
||||||
|
}
|
||||||
w.Write(topic_alt_91)
|
w.Write(topic_alt_91)
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.UploadFiles {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply {
|
||||||
w.Write(topic_alt_92)
|
w.Write(topic_alt_92)
|
||||||
}
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Avatar))
|
||||||
w.Write(topic_alt_93)
|
w.Write(topic_alt_93)
|
||||||
}
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Link))
|
||||||
w.Write(topic_alt_94)
|
w.Write(topic_alt_94)
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Name))
|
||||||
|
w.Write(topic_alt_95)
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Tag != "" {
|
||||||
|
w.Write(topic_alt_96)
|
||||||
|
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Tag))
|
||||||
|
w.Write(topic_alt_97)
|
||||||
|
} else {
|
||||||
|
w.Write(topic_alt_98)
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.CurrentUser.Level)))
|
||||||
|
w.Write(topic_alt_99)
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_100)
|
||||||
|
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||||
|
w.Write(topic_alt_101)
|
||||||
|
if tmpl_topic_alt_vars.CurrentUser.Perms.UploadFiles {
|
||||||
|
w.Write(topic_alt_102)
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_103)
|
||||||
|
}
|
||||||
|
w.Write(topic_alt_104)
|
||||||
w.Write(footer_0)
|
w.Write(footer_0)
|
||||||
if len(tmpl_topic_alt_vars.Header.Themes) != 0 {
|
if len(tmpl_topic_alt_vars.Header.Themes) != 0 {
|
||||||
for _, item := range tmpl_topic_alt_vars.Header.Themes {
|
for _, item := range tmpl_topic_alt_vars.Header.Themes {
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea>
|
<textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea>
|
||||||
<div class="button_container">
|
<div class="button_container">
|
||||||
{{if .CurrentUser.Loggedin}}
|
{{if .CurrentUser.Loggedin}}
|
||||||
{{if .CurrentUser.Perms.LikeItem}}<a href="/topic/like/submit/{{.Topic.ID}}" class="action_button">+1</a>{{end}}
|
{{if .CurrentUser.Perms.LikeItem}}<a href="/topic/like/submit/{{.Topic.ID}}" class="action_button like_item">+1</a>{{end}}
|
||||||
{{if .CurrentUser.Perms.EditTopic}}<a href="/topic/edit/{{.Topic.ID}}" class="action_button open_edit">Edit</a>{{end}}
|
{{if .CurrentUser.Perms.EditTopic}}<a href="/topic/edit/{{.Topic.ID}}" class="action_button open_edit">Edit</a>{{end}}
|
||||||
{{if .CurrentUser.Perms.DeleteTopic}}<a href="/topic/delete/submit/{{.Topic.ID}}" class="action_button delete_item">Delete</a>{{end}}
|
{{if .CurrentUser.Perms.DeleteTopic}}<a href="/topic/delete/submit/{{.Topic.ID}}" class="action_button delete_item">Delete</a>{{end}}
|
||||||
{{if .CurrentUser.Perms.CloseTopic}}
|
{{if .CurrentUser.Perms.CloseTopic}}
|
||||||
|
@ -43,9 +43,11 @@
|
||||||
{{if .Topic.Sticky}}<a href='/topic/unstick/submit/{{.Topic.ID}}' class="action_button">Unpin</a>{{else}}<a href='/topic/stick/submit/{{.Topic.ID}}' class="action_button">Pin</a>{{end}}{{end}}
|
{{if .Topic.Sticky}}<a href='/topic/unstick/submit/{{.Topic.ID}}' class="action_button">Unpin</a>{{else}}<a href='/topic/stick/submit/{{.Topic.ID}}' class="action_button">Pin</a>{{end}}{{end}}
|
||||||
<a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="action_button report_item">Report</a>
|
<a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="action_button report_item">Report</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .Topic.LikeCount}}<a class="action_button action_button_right like_count hide_on_micro">{{.Topic.LikeCount}} up</a>{{end}}
|
<div class="action_button_right">
|
||||||
<a class="action_button action_button_right created_at hide_on_mobile">{{.Topic.CreatedAt}}</a>
|
{{if .Topic.LikeCount}}<a class="action_button like_count hide_on_micro">{{.Topic.LikeCount}}</a>{{end}}
|
||||||
{{if .CurrentUser.Perms.ViewIPs}}<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">{{.Topic.IPAddress}}</a>{{end}}
|
<a class="action_button created_at hide_on_mobile">{{.Topic.RelativeCreatedAt}}</a>
|
||||||
|
{{if .CurrentUser.Perms.ViewIPs}}<a href="#" title="IP Address" class="action_button ip_item hide_on_mobile">{{.Topic.IPAddress}}</a>{{end}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><div style="clear:both;"></div>
|
</div><div style="clear:both;"></div>
|
||||||
</article>
|
</article>
|
||||||
|
@ -66,14 +68,16 @@
|
||||||
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
|
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
|
||||||
<div class="button_container">
|
<div class="button_container">
|
||||||
{{if $.CurrentUser.Loggedin}}
|
{{if $.CurrentUser.Loggedin}}
|
||||||
{{if $.CurrentUser.Perms.LikeItem}}<a href="/reply/like/submit/{{.ID}}" class="action_button">+1</a>{{end}}
|
{{if $.CurrentUser.Perms.LikeItem}}<a href="/reply/like/submit/{{.ID}}" class="action_button like_item">+1</a>{{end}}
|
||||||
{{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}" class="action_button edit_item">Edit</a>{{end}}
|
{{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}" class="action_button edit_item">Edit</a>{{end}}
|
||||||
{{if $.CurrentUser.Perms.DeleteReply}}<a href="/reply/delete/submit/{{.ID}}" class="action_button delete_item">Delete</a>{{end}}
|
{{if $.CurrentUser.Perms.DeleteReply}}<a href="/reply/delete/submit/{{.ID}}" class="action_button delete_item">Delete</a>{{end}}
|
||||||
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="action_button report_item">Report</a>
|
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="action_button report_item">Report</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .LikeCount}}<a class="action_button action_button_right like_count hide_on_micro">{{.LikeCount}} up</a>{{end}}
|
<div class="action_button_right">
|
||||||
<a class="action_button action_button_right created_at hide_on_mobile">{{.CreatedAt}}</a>
|
{{if .LikeCount}}<a class="action_button like_count hide_on_micro">{{.LikeCount}}</a>{{end}}
|
||||||
{{if $.CurrentUser.Perms.ViewIPs}}<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">{{.IPAddress}}</a>{{end}}
|
<a class="action_button created_at hide_on_mobile">{{.RelativeCreatedAt}}</a>
|
||||||
|
{{if $.CurrentUser.Perms.ViewIPs}}<a href="#" title="IP Address" class="action_button ip_item hide_on_mobile">{{.IPAddress}}</a>{{end}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -82,21 +86,28 @@
|
||||||
{{end}}</div>
|
{{end}}</div>
|
||||||
|
|
||||||
{{if .CurrentUser.Perms.CreateReply}}
|
{{if .CurrentUser.Perms.CreateReply}}
|
||||||
<div class="rowblock topic_reply_form quick_create_form">
|
<div class="rowblock topic_reply_container">
|
||||||
<form id="reply_form" enctype="multipart/form-data" action="/reply/create/" method="post"></form>
|
<div class="userinfo" aria-label="The information on the poster">
|
||||||
<input form="reply_form" name="tid" value='{{.Topic.ID}}' type="hidden" />
|
<div class="avatar_item" style="background-image: url({{.CurrentUser.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||||
<div class="formrow real_first_child">
|
<a href="{{.CurrentUser.Link}}" class="the_name" rel="author">{{.CurrentUser.Name}}</a>
|
||||||
<div class="formitem">
|
{{if .CurrentUser.Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.CurrentUser.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level {{.CurrentUser.Level}}</div><div class="tag_post"></div></div>{{end}}
|
||||||
<textarea id="input_content" form="reply_form" name="reply-content" placeholder="Insert reply here" required></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow quick_button_row">
|
<div class="rowblock topic_reply_form quick_create_form">
|
||||||
<div class="formitem">
|
<form id="reply_form" enctype="multipart/form-data" action="/reply/create/" method="post"></form>
|
||||||
<button form="reply_form" name="reply-button" class="formbutton">Create Reply</button>
|
<input form="reply_form" name="tid" value='{{.Topic.ID}}' type="hidden" />
|
||||||
{{if .CurrentUser.Perms.UploadFiles}}
|
<div class="formrow real_first_child">
|
||||||
<input name="upload_files" form="reply_form" id="upload_files" multiple type="file" style="display: none;" />
|
<div class="formitem">
|
||||||
<label for="upload_files" class="formbutton add_file_button">Add File</label>
|
<textarea id="input_content" form="reply_form" name="reply-content" placeholder="What do you think?" required></textarea>
|
||||||
<div id="upload_file_dock"></div>{{end}}
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow quick_button_row">
|
||||||
|
<div class="formitem">
|
||||||
|
<button form="reply_form" name="reply-button" class="formbutton">Create Reply</button>
|
||||||
|
{{if .CurrentUser.Perms.UploadFiles}}
|
||||||
|
<input name="upload_files" form="reply_form" id="upload_files" multiple type="file" style="display: none;" />
|
||||||
|
<label for="upload_files" class="formbutton add_file_button">Add File</label>
|
||||||
|
<div id="upload_file_dock"></div>{{end}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -37,32 +37,32 @@
|
||||||
<form name="topic_create_form_form" id="topic_create_form_form" enctype="multipart/form-data" action="/topic/create/submit/" method="post"></form>
|
<form name="topic_create_form_form" id="topic_create_form_form" enctype="multipart/form-data" action="/topic/create/submit/" method="post"></form>
|
||||||
{{if .CurrentUser.Avatar}}<img class="little_row_avatar" src="{{.CurrentUser.Avatar}}" height="64" />{{end}}
|
{{if .CurrentUser.Avatar}}<img class="little_row_avatar" src="{{.CurrentUser.Avatar}}" height="64" />{{end}}
|
||||||
<div class="main_form">
|
<div class="main_form">
|
||||||
<div class="topic_meta">
|
<div class="topic_meta">
|
||||||
<div class="formrow topic_board_row real_first_child">
|
<div class="formrow topic_board_row real_first_child">
|
||||||
<div class="formitem"><select form="topic_create_form_form" id="topic_board_input" name="topic-board">
|
<div class="formitem"><select form="topic_create_form_form" id="topic_board_input" name="topic-board">
|
||||||
{{range .ForumList}}<option {{if eq .ID $.DefaultForum}}selected{{end}} value="{{.ID}}">{{.Name}}</option>{{end}}
|
{{range .ForumList}}<option {{if eq .ID $.DefaultForum}}selected{{end}} value="{{.ID}}">{{.Name}}</option>{{end}}
|
||||||
</select></div>
|
</select></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="formrow topic_name_row">
|
<div class="formrow topic_name_row">
|
||||||
<div class="formitem">
|
<div class="formitem">
|
||||||
<input form="topic_create_form_form" name="topic-name" placeholder="What's up?" required>
|
<input form="topic_create_form_form" name="topic-name" placeholder="What's up?" required>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="formrow topic_content_row">
|
||||||
<div class="formrow topic_content_row">
|
<div class="formitem">
|
||||||
<div class="formitem">
|
<textarea form="topic_create_form_form" id="input_content" name="topic-content" placeholder="Insert post here" required></textarea>
|
||||||
<textarea form="topic_create_form_form" id="input_content" name="topic-content" placeholder="Insert post here" required></textarea>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="formrow quick_button_row">
|
|
||||||
<div class="formitem">
|
|
||||||
<button form="topic_create_form_form" class="formbutton">Create Topic</button>
|
|
||||||
{{if .CurrentUser.Perms.UploadFiles}}
|
|
||||||
<input name="upload_files" form="topic_create_form_form" id="upload_files" multiple type="file" style="display: none;" />
|
|
||||||
<label for="upload_files" class="formbutton add_file_button">Add File</label>
|
|
||||||
<div id="upload_file_dock"></div>{{end}}
|
|
||||||
<button class="formbutton close_form">Cancel</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="formrow quick_button_row">
|
||||||
|
<div class="formitem">
|
||||||
|
<button form="topic_create_form_form" class="formbutton">Create Topic</button>
|
||||||
|
{{if .CurrentUser.Perms.UploadFiles}}
|
||||||
|
<input name="upload_files" form="topic_create_form_form" id="upload_files" multiple type="file" style="display: none;" />
|
||||||
|
<label for="upload_files" class="formbutton add_file_button">Add File</label>
|
||||||
|
<div id="upload_file_dock"></div>{{end}}
|
||||||
|
<button class="formbutton close_form">Cancel</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
--primary-link-color: hsl(0,0%,40%);
|
--primary-link-color: hsl(0,0%,40%);
|
||||||
--primary-text-color: hsl(0,0%,20%);
|
--primary-text-color: hsl(0,0%,20%);
|
||||||
--lightened-primary-text-color: hsl(0,0%,30%);
|
--lightened-primary-text-color: hsl(0,0%,30%);
|
||||||
|
--extra-lightened-primary-text-color: hsl(0,0%,40%);
|
||||||
--inverse-primary-text-color: white;
|
--inverse-primary-text-color: white;
|
||||||
--light-text-color: hsl(0,0%,55%);
|
--light-text-color: hsl(0,0%,55%);
|
||||||
|
--lighter-text-color: hsl(0,0%,65%);
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
@ -402,6 +404,25 @@ select, input, textarea {
|
||||||
color: hsl(0,0%,30%);
|
color: hsl(0,0%,30%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topic_reply_container {
|
||||||
|
display: flex;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
.topic_reply_form {
|
||||||
|
margin: 0px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.topic_reply_form .trumbowyg-button-pane:after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.topic_reply_form .trumbowyg-editor {
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
.topic_reply_form .quick_button_row {
|
||||||
|
margin-bottom: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
#prevFloat, #nextFloat {
|
#prevFloat, #nextFloat {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -600,33 +621,67 @@ select, input, textarea {
|
||||||
}
|
}
|
||||||
.userinfo {
|
.userinfo {
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
padding: 18px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-left: 24px;
|
padding-top: 30px;
|
||||||
padding-right: 24px;
|
padding-left: 42px;
|
||||||
padding-bottom: 12px;
|
padding-right: 42px;
|
||||||
|
padding-bottom: 18px;
|
||||||
|
height: min-content;
|
||||||
|
/*overflow: hidden;
|
||||||
|
text-overflow: ellipsis;*/
|
||||||
}
|
}
|
||||||
.content_container {
|
.content_container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 16px;
|
padding: 17px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.avatar_item {
|
.avatar_item {
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
width: 90px;
|
width: 84px;
|
||||||
height: 90px;
|
height: 84px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 12px;
|
||||||
background-size: 128px;
|
background-size: 120px;
|
||||||
|
}
|
||||||
|
.the_name, .userinfo .tag_block {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
.the_name {
|
.the_name {
|
||||||
font-size: 19px;
|
font-size: 18px;
|
||||||
color: var(--lightened-primary-text-color);
|
color: var(--lightened-primary-text-color);
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
}
|
||||||
.userinfo .tag_block {
|
.userinfo .tag_block {
|
||||||
|
color: var(--extra-lightened-primary-text-color);
|
||||||
|
}
|
||||||
|
.button_container {
|
||||||
|
margin-top: auto;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.action_button {
|
||||||
|
margin-right: 5px;
|
||||||
|
color: var(--light-text-color);
|
||||||
|
font-size: 14px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.action_button_right {
|
||||||
|
display: inline-flex;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
}
|
||||||
|
.like_count:after {
|
||||||
|
content: " likes";
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
.created_at:before, .ip_item:before {
|
||||||
|
border-left: 1px solid var(--element-border-color);
|
||||||
|
content: "";
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 1px;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
.created_at {
|
||||||
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: 670px) {
|
@media(max-width: 670px) {
|
||||||
|
|
|
@ -652,6 +652,9 @@ button.username {
|
||||||
padding-right: 7px;
|
padding-right: 7px;
|
||||||
}
|
}
|
||||||
.action_button_right {
|
.action_button_right {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.action_button_right .action_button {
|
||||||
border-left: solid 1px #eaeaea;
|
border-left: solid 1px #eaeaea;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
|
@ -660,10 +663,21 @@ button.username {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.like_label:before { content: "😀"; }
|
.like_label:before {
|
||||||
.edit_label:before { content: "🖊️"; }
|
content: "😀";
|
||||||
.trash_label:before { content: "🗑️"; }
|
}
|
||||||
.flag_label:before { content: "🚩"; }
|
.like_count:after {
|
||||||
|
content: " up";
|
||||||
|
}
|
||||||
|
.edit_label:before {
|
||||||
|
content: "🖊️";
|
||||||
|
}
|
||||||
|
.trash_label:before {
|
||||||
|
content: "🗑️";
|
||||||
|
}
|
||||||
|
.flag_label:before {
|
||||||
|
content: "🚩";
|
||||||
|
}
|
||||||
|
|
||||||
.mod_button {
|
.mod_button {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
|
|
6
topic.go
6
topic.go
|
@ -24,7 +24,8 @@ type Topic struct {
|
||||||
CreatedBy int
|
CreatedBy int
|
||||||
IsClosed bool
|
IsClosed bool
|
||||||
Sticky bool
|
Sticky bool
|
||||||
CreatedAt string
|
CreatedAt time.Time
|
||||||
|
RelativeCreatedAt string
|
||||||
LastReplyAt time.Time
|
LastReplyAt time.Time
|
||||||
RelativeLastReplyAt string
|
RelativeLastReplyAt string
|
||||||
//LastReplyBy int
|
//LastReplyBy int
|
||||||
|
@ -45,7 +46,8 @@ type TopicUser struct {
|
||||||
CreatedBy int
|
CreatedBy int
|
||||||
IsClosed bool
|
IsClosed bool
|
||||||
Sticky bool
|
Sticky bool
|
||||||
CreatedAt string
|
CreatedAt time.Time
|
||||||
|
RelativeCreatedAt string
|
||||||
LastReplyAt time.Time
|
LastReplyAt time.Time
|
||||||
RelativeLastReplyAt string
|
RelativeLastReplyAt string
|
||||||
//LastReplyBy int
|
//LastReplyBy int
|
||||||
|
|
Loading…
Reference in New Issue