More conversations work.
Add support for AS in columns for SimpleInnerJoin. Add a referrer policy to improve privacy a little. Shorten /static/ to /s/ since it comes up so much. Remove some obsolete code. Shorten some variable names. Reduce the amount of boilerplate in the patcher. Added the RefNoTrack and RefNoRef privacy config settings. You may need to run the updater / patcher for this commit.
This commit is contained in:
parent
6ba4b665e3
commit
4d8c97812d
@ -362,7 +362,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||
)
|
||||
|
||||
//columns("participants, createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?")
|
||||
/*qgen.Install.CreateTable("conversations", "", "",
|
||||
qgen.Install.CreateTable("conversations", "", "",
|
||||
[]tC{
|
||||
tC{"cid", "int", 0, false, true, ""},
|
||||
tC{"createdBy", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||
@ -393,7 +393,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||
tC{"uid", "int", 0, false, false, ""},
|
||||
tC{"cid", "int", 0, false, false, ""},
|
||||
}, nil,
|
||||
)*/
|
||||
)
|
||||
|
||||
qgen.Install.CreateTable("activity_stream_matches", "", "",
|
||||
[]tC{
|
||||
|
@ -1,8 +1,9 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"time"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
//"strconv"
|
||||
"database/sql"
|
||||
|
||||
@ -17,62 +18,63 @@ var Convos ConversationStore
|
||||
var convoStmts ConvoStmts
|
||||
|
||||
type ConvoStmts struct {
|
||||
getPosts *sql.Stmt
|
||||
fetchPost *sql.Stmt
|
||||
getPosts *sql.Stmt
|
||||
countPosts *sql.Stmt
|
||||
edit *sql.Stmt
|
||||
create *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
edit *sql.Stmt
|
||||
create *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
|
||||
editPost *sql.Stmt
|
||||
editPost *sql.Stmt
|
||||
createPost *sql.Stmt
|
||||
deletePost *sql.Stmt
|
||||
}
|
||||
|
||||
/*func init() {
|
||||
func init() {
|
||||
DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||
convoStmts = ConvoStmts{
|
||||
getPosts: acc.Select("conversations_posts").Columns("pid, body, post, createdBy").Where("cid = ?").Limit("?,?").Prepare(),
|
||||
fetchPost: acc.Select("conversations_posts").Columns("cid, body, post, createdBy").Where("pid = ?").Prepare(),
|
||||
getPosts: acc.Select("conversations_posts").Columns("pid, body, post, createdBy").Where("cid = ?").Limit("?,?").Prepare(),
|
||||
countPosts: acc.Count("conversations_posts").Where("cid = ?").Prepare(),
|
||||
//edit: acc.Update("conversations").Set("participants = ?, lastReplyBy = ?, lastReplyAt = ?").Where("cid = ?").Prepare(),
|
||||
edit: acc.Update("conversations").Set("lastReplyBy = ?, lastReplyAt = ?").Where("cid = ?").Prepare(),
|
||||
//create: acc.Insert("conversations").Columns("participants, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||
create: acc.Insert("conversations").Columns("createdAt, lastReplyAt").Fields("UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||
edit: acc.Update("conversations").Set("lastReplyBy = ?, lastReplyAt = ?").Where("cid = ?").Prepare(),
|
||||
create: acc.Insert("conversations").Columns("createdAt, lastReplyAt").Fields("UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||
|
||||
editPost: acc.Update("conversations_posts").Set("body = ?, post = ?").Where("cid = ?").Prepare(),
|
||||
editPost: acc.Update("conversations_posts").Set("body = ?, post = ?").Where("cid = ?").Prepare(),
|
||||
createPost: acc.Insert("conversations_posts").Columns("cid, body, post, createdBy").Fields("?,?,?,?").Prepare(),
|
||||
deletePost: acc.Delete("conversations_posts").Where("pid = ?").Prepare(),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
}*/
|
||||
}
|
||||
|
||||
type Conversation struct {
|
||||
ID int
|
||||
//Participants string
|
||||
CreatedBy int
|
||||
CreatedAt time.Time
|
||||
ID int
|
||||
CreatedBy int
|
||||
CreatedAt time.Time
|
||||
LastReplyBy int
|
||||
LastReplyAt time.Time
|
||||
}
|
||||
|
||||
func (co *Conversation) Posts(offset int) (posts []*ConversationPost, err error) {
|
||||
rows, err := convoStmts.getPosts.Query(co.ID, offset, Config.ItemsPerPage)
|
||||
func (co *Conversation) Posts(offset, itemsPerPage int) (posts []*ConversationPost, err error) {
|
||||
rows, err := convoStmts.getPosts.Query(co.ID, offset, itemsPerPage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
convo := &ConversationPost{CID: co.ID}
|
||||
err := rows.Scan(&convo.ID, &convo.Body, &convo.Post, &convo.CreatedBy)
|
||||
p := &ConversationPost{CID: co.ID}
|
||||
err := rows.Scan(&p.ID, &p.Body, &p.Post, &p.CreatedBy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
convo, err = ConvoPostProcess.OnLoad(convo)
|
||||
p, err = ConvoPostProcess.OnLoad(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
posts = append(posts, convo)
|
||||
posts = append(posts, p)
|
||||
}
|
||||
|
||||
|
||||
return posts, rows.Err()
|
||||
}
|
||||
|
||||
@ -85,12 +87,12 @@ func (co *Conversation) PostsCount() (count int) {
|
||||
}
|
||||
|
||||
func (co *Conversation) Update() error {
|
||||
_, err := convoStmts.edit.Exec(/*co.Participants, */co.CreatedAt, co.LastReplyBy, co.LastReplyAt, co.ID)
|
||||
_, err := convoStmts.edit.Exec(co.CreatedAt, co.LastReplyBy, co.LastReplyAt, co.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (co *Conversation) Create() (int, error) {
|
||||
res, err := convoStmts.create.Exec(/*co.Participants*/)
|
||||
res, err := convoStmts.create.Exec()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -109,39 +111,34 @@ type ConversationStore interface {
|
||||
}
|
||||
|
||||
type DefaultConversationStore struct {
|
||||
get *sql.Stmt
|
||||
getUser *sql.Stmt
|
||||
getUserCount *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
deletePosts *sql.Stmt
|
||||
create *sql.Stmt
|
||||
get *sql.Stmt
|
||||
getUser *sql.Stmt
|
||||
getUserCount *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
deletePosts *sql.Stmt
|
||||
deleteParticipants *sql.Stmt
|
||||
create *sql.Stmt
|
||||
addParticipant *sql.Stmt
|
||||
count *sql.Stmt
|
||||
count *sql.Stmt
|
||||
}
|
||||
|
||||
func NewDefaultConversationStore(acc *qgen.Accumulator) (*DefaultConversationStore, error) {
|
||||
return &DefaultConversationStore{
|
||||
//get: acc.Select("conversations").Columns("participants, createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
|
||||
get: acc.Select("conversations").Columns("createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
|
||||
|
||||
//("replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress, replies.likeCount, replies.attachCount, replies.actionType", "replies.createdBy = users.uid", "replies.tid = ?", "replies.rid ASC", "?,?")
|
||||
//(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string)
|
||||
|
||||
//getUser: acc.SimpleLeftJoin("conversations_participants AS cp","conversations AS c","c.cid, c.participants, c.createdBy, c.createdAt, c.lastReplyBy, c.lastReplyAt","cp.cid = c.cid","cp.uid = ?","c.lastReplyAt DESC, c.createdAt DESC, c.cid DESC","?,?"),
|
||||
getUser: acc.SimpleLeftJoin("conversations_participants AS cp","conversations AS c","c.cid, c.createdBy, c.createdAt, c.lastReplyBy, c.lastReplyAt","cp.cid = c.cid","cp.uid = ?","c.lastReplyAt DESC, c.createdAt DESC, c.cid DESC","?,?"),
|
||||
getUserCount: acc.Count("conversations_participants").Where("uid = ?").Prepare(),
|
||||
delete: acc.Delete("conversations").Where("cid = ?").Prepare(),
|
||||
deletePosts: acc.Delete("conversations_posts").Where("cid = ?").Prepare(),
|
||||
//create: acc.Insert("conversations").Columns("participants, createdBy, createdAt, lastReplyAt").Fields("?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||
create: acc.Insert("conversations").Columns("createdBy, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||
get: acc.Select("conversations").Columns("createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
|
||||
getUser: acc.SimpleInnerJoin("conversations_participants AS cp", "conversations AS c", "cp.cid, c.createdBy, c.createdAt, c.lastReplyBy, c.lastReplyAt", "cp.cid = c.cid", "cp.uid = ?", "c.lastReplyAt DESC, c.createdAt DESC, c.cid DESC", "?,?"),
|
||||
getUserCount: acc.Count("conversations_participants").Where("uid = ?").Prepare(),
|
||||
delete: acc.Delete("conversations").Where("cid = ?").Prepare(),
|
||||
deletePosts: acc.Delete("conversations_posts").Where("cid = ?").Prepare(),
|
||||
deleteParticipants: acc.Delete("conversations_participants").Where("cid = ?").Prepare(),
|
||||
create: acc.Insert("conversations").Columns("createdBy, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||
addParticipant: acc.Insert("conversations_participants").Columns("uid, cid").Fields("?,?").Prepare(),
|
||||
count: acc.Count("conversations").Prepare(),
|
||||
count: acc.Count("conversations").Prepare(),
|
||||
}, acc.FirstError()
|
||||
}
|
||||
|
||||
func (s *DefaultConversationStore) Get(id int) (*Conversation, error) {
|
||||
convo := &Conversation{ID: id}
|
||||
err := s.get.QueryRow(id).Scan(/*&convo.Participants, */&convo.CreatedBy, &convo.CreatedAt, &convo.LastReplyBy, &convo.LastReplyAt)
|
||||
err := s.get.QueryRow(id).Scan(&convo.CreatedBy, &convo.CreatedAt, &convo.LastReplyBy, &convo.LastReplyAt)
|
||||
return convo, err
|
||||
}
|
||||
|
||||
@ -154,7 +151,7 @@ func (s *DefaultConversationStore) GetUser(uid int, offset int) (cos []*Conversa
|
||||
|
||||
for rows.Next() {
|
||||
co := &Conversation{}
|
||||
err := rows.Scan(&co.ID, /*&co.Participants,*/ &co.CreatedBy, &co.CreatedAt, &co.LastReplyBy, &co.LastReplyAt)
|
||||
err := rows.Scan(&co.ID, &co.CreatedBy, &co.CreatedAt, &co.LastReplyBy, &co.LastReplyAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -179,6 +176,10 @@ func (s *DefaultConversationStore) Delete(id int) error {
|
||||
return err
|
||||
}
|
||||
_, err = s.deletePosts.Exec(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.deleteParticipants.Exec(id)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -186,13 +187,7 @@ func (s *DefaultConversationStore) Create(content string, createdBy int, partici
|
||||
if len(participants) == 0 {
|
||||
return 0, errors.New("no participants set")
|
||||
}
|
||||
/*var pstr string
|
||||
for _, parti := range participants {
|
||||
pstr += strconv.Itoa(parti) + ","
|
||||
}
|
||||
pstr = pstr[:len(pstr)-1]*/
|
||||
|
||||
res, err := s.create.Exec(createdBy/*, pstr*/)
|
||||
res, err := s.create.Exec(createdBy)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -211,12 +206,12 @@ func (s *DefaultConversationStore) Create(content string, createdBy int, partici
|
||||
}
|
||||
|
||||
for _, p := range participants {
|
||||
_, err := s.addParticipant.Exec(p,lastID)
|
||||
_, err := s.addParticipant.Exec(p, lastID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
_, err = s.addParticipant.Exec(createdBy,lastID)
|
||||
_, err = s.addParticipant.Exec(createdBy, lastID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -231,4 +226,4 @@ func (s *DefaultConversationStore) Count() (count int) {
|
||||
LogError(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"io"
|
||||
"encoding/hex"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
)
|
||||
|
||||
var ConvoPostProcess ConvoPostProcessor = NewDefaultConvoPostProcessor()
|
||||
@ -99,13 +99,17 @@ func (pr *AesConvoPostProcessor) OnSave(co *ConversationPost) (*ConversationPost
|
||||
}
|
||||
|
||||
type ConversationPost struct {
|
||||
ID int
|
||||
CID int
|
||||
Body string
|
||||
Post string // aes, ''
|
||||
ID int
|
||||
CID int
|
||||
Body string
|
||||
Post string // aes, ''
|
||||
CreatedBy int
|
||||
}
|
||||
|
||||
func (co *ConversationPost) Fetch() error {
|
||||
return convoStmts.fetchPost.QueryRow(co.ID).Scan(&co.CID, &co.Body, &co.Post, &co.CreatedBy)
|
||||
}
|
||||
|
||||
func (co *ConversationPost) Update() error {
|
||||
lco, err := ConvoPostProcess.OnSave(co)
|
||||
if err != nil {
|
||||
@ -122,11 +126,16 @@ func (co *ConversationPost) Create() (int, error) {
|
||||
return 0, err
|
||||
}
|
||||
//GetHookTable().VhookNoRet("convo_post_create", lco)
|
||||
res, err := convoStmts.createPost.Exec(lco.CID, lco.Body, lco.Post)
|
||||
res, err := convoStmts.createPost.Exec(lco.CID, lco.Body, lco.Post, lco.CreatedBy)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
lastID, err := res.LastInsertId()
|
||||
return int(lastID), err
|
||||
}
|
||||
}
|
||||
|
||||
func (co *ConversationPost) Delete() error {
|
||||
_, err := convoStmts.deletePost.Exec(co.ID)
|
||||
return err
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ func (list SFileList) JSTmplInit() error {
|
||||
hasher.Write(data)
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
|
||||
list.Set("/static/"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
list.Set("/s/"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
|
||||
DebugLogf("Added the '%s' static file.", path)
|
||||
return nil
|
||||
@ -285,7 +285,7 @@ func (list SFileList) Init() error {
|
||||
}
|
||||
}
|
||||
|
||||
list.Set("/static/"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mimetype, f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
list.Set("/s/"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mimetype, f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
|
||||
DebugLogf("Added the '%s' static file.", path)
|
||||
return nil
|
||||
@ -318,7 +318,7 @@ func (list SFileList) Add(path string, prefix string) error {
|
||||
hasher.Write(data)
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
|
||||
list.Set("/static"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
list.Set("/s"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
|
||||
DebugLogf("Added the '%s' static file", path)
|
||||
return nil
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Azareal/Gosora/common/phrases"
|
||||
p "github.com/Azareal/Gosora/common/phrases"
|
||||
)
|
||||
|
||||
/*type HResource struct {
|
||||
@ -15,7 +15,7 @@ import (
|
||||
Hash string
|
||||
}*/
|
||||
|
||||
// TODO: Allow resources in spots other than /static/ and possibly even external domains (e.g. CDNs)
|
||||
// TODO: Allow resources in spots other than /s/ and possibly even external domains (e.g. CDNs)
|
||||
// TODO: Preload Trumboyg on Cosora on the forum list
|
||||
type Header struct {
|
||||
Title string
|
||||
@ -50,9 +50,9 @@ type Header struct {
|
||||
ExtData ExtData
|
||||
}
|
||||
|
||||
func (header *Header) AddScript(name string) {
|
||||
func (h *Header) AddScript(name string) {
|
||||
// TODO: Use a secondary static file map to avoid this concatenation?
|
||||
fname := "/static/" + name
|
||||
fname := "/s/" + name
|
||||
var oname string
|
||||
if fname[0] == '/' && fname[1] != '/' {
|
||||
file, ok := StaticFiles.Get(fname)
|
||||
@ -64,11 +64,11 @@ func (header *Header) AddScript(name string) {
|
||||
oname = name
|
||||
}
|
||||
//log.Print("oname:", oname)
|
||||
header.Scripts = append(header.Scripts, oname)
|
||||
h.Scripts = append(h.Scripts, oname)
|
||||
}
|
||||
|
||||
func (header *Header) AddPreScriptAsync(name string) {
|
||||
fname := "/static/" + name
|
||||
func (h *Header) AddPreScriptAsync(name string) {
|
||||
fname := "/s/" + name
|
||||
var oname string
|
||||
if fname[0] == '/' && fname[1] != '/' {
|
||||
file, ok := StaticFiles.Get(fname)
|
||||
@ -79,11 +79,11 @@ func (header *Header) AddPreScriptAsync(name string) {
|
||||
if oname == "" {
|
||||
oname = name
|
||||
}
|
||||
header.PreScriptsAsync = append(header.PreScriptsAsync, oname)
|
||||
h.PreScriptsAsync = append(h.PreScriptsAsync, oname)
|
||||
}
|
||||
|
||||
func (header *Header) AddScriptAsync(name string) {
|
||||
fname := "/static/" + name
|
||||
func (h *Header) AddScriptAsync(name string) {
|
||||
fname := "/s/" + name
|
||||
var oname string
|
||||
if fname[0] == '/' && fname[1] != '/' {
|
||||
file, ok := StaticFiles.Get(fname)
|
||||
@ -94,15 +94,15 @@ func (header *Header) AddScriptAsync(name string) {
|
||||
if oname == "" {
|
||||
oname = name
|
||||
}
|
||||
header.ScriptsAsync = append(header.ScriptsAsync, oname)
|
||||
h.ScriptsAsync = append(h.ScriptsAsync, oname)
|
||||
}
|
||||
|
||||
/*func (header *Header) Preload(name string) {
|
||||
header.Preload = append(header.Preload, name)
|
||||
/*func (h *Header) Preload(name string) {
|
||||
h.Preload = append(h.Preload, name)
|
||||
}*/
|
||||
|
||||
func (header *Header) AddSheet(name string) {
|
||||
fname := "/static/" + name
|
||||
func (h *Header) AddSheet(name string) {
|
||||
fname := "/s/" + name
|
||||
var oname string
|
||||
if fname[0] == '/' && fname[1] != '/' {
|
||||
file, ok := StaticFiles.Get(fname)
|
||||
@ -113,11 +113,11 @@ func (header *Header) AddSheet(name string) {
|
||||
if oname == "" {
|
||||
oname = name
|
||||
}
|
||||
header.Stylesheets = append(header.Stylesheets, oname)
|
||||
h.Stylesheets = append(h.Stylesheets, oname)
|
||||
}
|
||||
|
||||
func (header *Header) AddNotice(name string) {
|
||||
header.NoticeList = append(header.NoticeList, phrases.GetNoticePhrase(name))
|
||||
func (h *Header) AddNotice(name string) {
|
||||
h.NoticeList = append(h.NoticeList, p.GetNoticePhrase(name))
|
||||
}
|
||||
|
||||
// TODO: Add this to routes which don't use templates. E.g. Json APIs.
|
||||
@ -289,9 +289,18 @@ type ConvoListPage struct {
|
||||
Paginator
|
||||
}
|
||||
|
||||
type ConvoViewRow struct {
|
||||
*ConversationPost
|
||||
User *User
|
||||
ClassName string
|
||||
ContentLines string
|
||||
}
|
||||
|
||||
type ConvoViewPage struct {
|
||||
*Header
|
||||
Posts []*ConversationPost
|
||||
Convo *Conversation
|
||||
Posts []ConvoViewRow
|
||||
CanModify bool
|
||||
Paginator
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,9 @@ type config struct {
|
||||
DisableNoavatarRange bool
|
||||
DisableDefaultNoavatar bool
|
||||
|
||||
RefNoTrack bool
|
||||
RefNoRef bool
|
||||
|
||||
Noavatar string // ? - Move this into the settings table?
|
||||
ItemsPerPage int // ? - Move this into the settings table?
|
||||
MaxTopicTitleLength int
|
||||
|
@ -167,7 +167,7 @@ func (theme *Theme) AddThemeStaticFiles() error {
|
||||
hasher.Write(data)
|
||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||
|
||||
StaticFiles.Set("/static/"+theme.Name+path, SFile{data, gzipData, checksum,theme.Name+path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
StaticFiles.Set("/s/"+theme.Name+path, SFile{data, gzipData, checksum,theme.Name+path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||
|
||||
DebugLog("Added the '/" + theme.Name + path + "' static file for theme " + theme.Name + ".")
|
||||
return nil
|
||||
|
@ -472,7 +472,7 @@ func buildNoavatar(uid int, width int) string {
|
||||
}
|
||||
}
|
||||
if !Config.DisableDefaultNoavatar && uid < 5 {
|
||||
return "/static/n"+strconv.Itoa(uid)+"-"+strconv.Itoa(width)+".png?i=0"
|
||||
return "/s/n"+strconv.Itoa(uid)+"-"+strconv.Itoa(width)+".png?i=0"
|
||||
}
|
||||
return strings.Replace(strings.Replace(Config.Noavatar, "{id}", strconv.Itoa(uid), 1), "{width}", strconv.Itoa(width), 1)
|
||||
}
|
||||
|
@ -104,6 +104,10 @@ DisableNoavatarRange - This switch lets you disable the noavatar algorithm which
|
||||
|
||||
DisableDefaultNoavatar - This switch lets you disable the default noavatar algorithm which may intercept noavatars for increased efficiency. Default: false
|
||||
|
||||
RefNoTrack - This switch disables tracking the referrers of users who click from another site to your site and the referrers of any requests to resources from other sites as-well.
|
||||
|
||||
RefNoRef - This switch makes it so that if a user clicks on a link, then the incoming site won't know which site they're coming from.
|
||||
|
||||
NoAvatar - The default avatar to use for users when they don't have their own. The default for this may change in the near future to better utilise HTTP/2. Example: https://api.adorable.io/avatars/{width}/{id}.png
|
||||
|
||||
ItemsPerPage - The number of posts, topics, etc. you want on each page.
|
||||
|
@ -1,9 +1,9 @@
|
||||
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 3px;padding-left: 4px;clear: both;border-bottom: solid 1px #ccc;padding-right: 3px;padding-bottom: 6px;">
|
||||
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;">
|
||||
<div class="avatar_item" style="background-image: url(/uploads/avatar_1.jpg), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
||||
<div class="avatar_item" style="background-image: url(/uploads/avatar_1.jpg), url(/s/white-dot.jpg);background-position:0px -10px;background-repeat:no-repeat, repeat-y;background-size:128px;width:128px;height:100%;min-height: 128px;border-style:solid;border-color:#eaeaea;border-width:1px;"> </div>
|
||||
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">Azareal</div>
|
||||
</div>
|
||||
<div class="content_container" style="background: white;margin-left: 137px;min-height: 128px;margin-bottom: 0;margin-right: 3px;">
|
||||
<div class="content_container" style="background:white;margin-left:137px;min-height:128px;margin-bottom:0;margin-right:3px;">
|
||||
<div class="editable_block user_content" style="padding: 5px;margin-top: 3px;margin-bottom: 0;background: white;min-height: 133px;padding-bottom: 0;width: 100%;">boo</div>
|
||||
<div class="button_container" style="border-top: solid 1px #eaeaea;border-spacing: 0px;border-collapse: collapse;padding: 0;margin: 0;display: block;">
|
||||
<a style="border-right: solid 1px #eaeaea;color: #505050;font-size: 13px;padding-left: 5px;padding-right: 5px;">Edit</a>
|
||||
|
434
gen_router.go
434
gen_router.go
@ -125,6 +125,14 @@ var RouteMap = map[string]interface{}{
|
||||
"routes.AccountEditEmailTokenSubmit": routes.AccountEditEmailTokenSubmit,
|
||||
"routes.AccountLogins": routes.AccountLogins,
|
||||
"routes.LevelList": routes.LevelList,
|
||||
"routes.Convos": routes.Convos,
|
||||
"routes.ConvosCreate": routes.ConvosCreate,
|
||||
"routes.Convo": routes.Convo,
|
||||
"routes.ConvosCreateSubmit": routes.ConvosCreateSubmit,
|
||||
"routes.ConvosDeleteSubmit": routes.ConvosDeleteSubmit,
|
||||
"routes.ConvosCreateReplySubmit": routes.ConvosCreateReplySubmit,
|
||||
"routes.ConvosDeleteReplySubmit": routes.ConvosDeleteReplySubmit,
|
||||
"routes.ConvosEditReplySubmit": routes.ConvosEditReplySubmit,
|
||||
"routes.ViewProfile": routes.ViewProfile,
|
||||
"routes.BanUserSubmit": routes.BanUserSubmit,
|
||||
"routes.UnbanUser": routes.UnbanUser,
|
||||
@ -278,53 +286,61 @@ var routeMapEnum = map[string]int{
|
||||
"routes.AccountEditEmailTokenSubmit": 99,
|
||||
"routes.AccountLogins": 100,
|
||||
"routes.LevelList": 101,
|
||||
"routes.ViewProfile": 102,
|
||||
"routes.BanUserSubmit": 103,
|
||||
"routes.UnbanUser": 104,
|
||||
"routes.ActivateUser": 105,
|
||||
"routes.IPSearch": 106,
|
||||
"routes.CreateTopicSubmit": 107,
|
||||
"routes.EditTopicSubmit": 108,
|
||||
"routes.DeleteTopicSubmit": 109,
|
||||
"routes.StickTopicSubmit": 110,
|
||||
"routes.UnstickTopicSubmit": 111,
|
||||
"routes.LockTopicSubmit": 112,
|
||||
"routes.UnlockTopicSubmit": 113,
|
||||
"routes.MoveTopicSubmit": 114,
|
||||
"routes.LikeTopicSubmit": 115,
|
||||
"routes.AddAttachToTopicSubmit": 116,
|
||||
"routes.RemoveAttachFromTopicSubmit": 117,
|
||||
"routes.ViewTopic": 118,
|
||||
"routes.CreateReplySubmit": 119,
|
||||
"routes.ReplyEditSubmit": 120,
|
||||
"routes.ReplyDeleteSubmit": 121,
|
||||
"routes.ReplyLikeSubmit": 122,
|
||||
"routes.AddAttachToReplySubmit": 123,
|
||||
"routes.RemoveAttachFromReplySubmit": 124,
|
||||
"routes.ProfileReplyCreateSubmit": 125,
|
||||
"routes.ProfileReplyEditSubmit": 126,
|
||||
"routes.ProfileReplyDeleteSubmit": 127,
|
||||
"routes.PollVote": 128,
|
||||
"routes.PollResults": 129,
|
||||
"routes.AccountLogin": 130,
|
||||
"routes.AccountRegister": 131,
|
||||
"routes.AccountLogout": 132,
|
||||
"routes.AccountLoginSubmit": 133,
|
||||
"routes.AccountLoginMFAVerify": 134,
|
||||
"routes.AccountLoginMFAVerifySubmit": 135,
|
||||
"routes.AccountRegisterSubmit": 136,
|
||||
"routes.AccountPasswordReset": 137,
|
||||
"routes.AccountPasswordResetSubmit": 138,
|
||||
"routes.AccountPasswordResetToken": 139,
|
||||
"routes.AccountPasswordResetTokenSubmit": 140,
|
||||
"routes.DynamicRoute": 141,
|
||||
"routes.UploadedFile": 142,
|
||||
"routes.StaticFile": 143,
|
||||
"routes.RobotsTxt": 144,
|
||||
"routes.SitemapXml": 145,
|
||||
"routes.OpenSearchXml": 146,
|
||||
"routes.BadRoute": 147,
|
||||
"routes.HTTPSRedirect": 148,
|
||||
"routes.Convos": 102,
|
||||
"routes.ConvosCreate": 103,
|
||||
"routes.Convo": 104,
|
||||
"routes.ConvosCreateSubmit": 105,
|
||||
"routes.ConvosDeleteSubmit": 106,
|
||||
"routes.ConvosCreateReplySubmit": 107,
|
||||
"routes.ConvosDeleteReplySubmit": 108,
|
||||
"routes.ConvosEditReplySubmit": 109,
|
||||
"routes.ViewProfile": 110,
|
||||
"routes.BanUserSubmit": 111,
|
||||
"routes.UnbanUser": 112,
|
||||
"routes.ActivateUser": 113,
|
||||
"routes.IPSearch": 114,
|
||||
"routes.CreateTopicSubmit": 115,
|
||||
"routes.EditTopicSubmit": 116,
|
||||
"routes.DeleteTopicSubmit": 117,
|
||||
"routes.StickTopicSubmit": 118,
|
||||
"routes.UnstickTopicSubmit": 119,
|
||||
"routes.LockTopicSubmit": 120,
|
||||
"routes.UnlockTopicSubmit": 121,
|
||||
"routes.MoveTopicSubmit": 122,
|
||||
"routes.LikeTopicSubmit": 123,
|
||||
"routes.AddAttachToTopicSubmit": 124,
|
||||
"routes.RemoveAttachFromTopicSubmit": 125,
|
||||
"routes.ViewTopic": 126,
|
||||
"routes.CreateReplySubmit": 127,
|
||||
"routes.ReplyEditSubmit": 128,
|
||||
"routes.ReplyDeleteSubmit": 129,
|
||||
"routes.ReplyLikeSubmit": 130,
|
||||
"routes.AddAttachToReplySubmit": 131,
|
||||
"routes.RemoveAttachFromReplySubmit": 132,
|
||||
"routes.ProfileReplyCreateSubmit": 133,
|
||||
"routes.ProfileReplyEditSubmit": 134,
|
||||
"routes.ProfileReplyDeleteSubmit": 135,
|
||||
"routes.PollVote": 136,
|
||||
"routes.PollResults": 137,
|
||||
"routes.AccountLogin": 138,
|
||||
"routes.AccountRegister": 139,
|
||||
"routes.AccountLogout": 140,
|
||||
"routes.AccountLoginSubmit": 141,
|
||||
"routes.AccountLoginMFAVerify": 142,
|
||||
"routes.AccountLoginMFAVerifySubmit": 143,
|
||||
"routes.AccountRegisterSubmit": 144,
|
||||
"routes.AccountPasswordReset": 145,
|
||||
"routes.AccountPasswordResetSubmit": 146,
|
||||
"routes.AccountPasswordResetToken": 147,
|
||||
"routes.AccountPasswordResetTokenSubmit": 148,
|
||||
"routes.DynamicRoute": 149,
|
||||
"routes.UploadedFile": 150,
|
||||
"routes.StaticFile": 151,
|
||||
"routes.RobotsTxt": 152,
|
||||
"routes.SitemapXml": 153,
|
||||
"routes.OpenSearchXml": 154,
|
||||
"routes.BadRoute": 155,
|
||||
"routes.HTTPSRedirect": 156,
|
||||
}
|
||||
var reverseRouteMapEnum = map[int]string{
|
||||
0: "routes.Overview",
|
||||
@ -429,53 +445,61 @@ var reverseRouteMapEnum = map[int]string{
|
||||
99: "routes.AccountEditEmailTokenSubmit",
|
||||
100: "routes.AccountLogins",
|
||||
101: "routes.LevelList",
|
||||
102: "routes.ViewProfile",
|
||||
103: "routes.BanUserSubmit",
|
||||
104: "routes.UnbanUser",
|
||||
105: "routes.ActivateUser",
|
||||
106: "routes.IPSearch",
|
||||
107: "routes.CreateTopicSubmit",
|
||||
108: "routes.EditTopicSubmit",
|
||||
109: "routes.DeleteTopicSubmit",
|
||||
110: "routes.StickTopicSubmit",
|
||||
111: "routes.UnstickTopicSubmit",
|
||||
112: "routes.LockTopicSubmit",
|
||||
113: "routes.UnlockTopicSubmit",
|
||||
114: "routes.MoveTopicSubmit",
|
||||
115: "routes.LikeTopicSubmit",
|
||||
116: "routes.AddAttachToTopicSubmit",
|
||||
117: "routes.RemoveAttachFromTopicSubmit",
|
||||
118: "routes.ViewTopic",
|
||||
119: "routes.CreateReplySubmit",
|
||||
120: "routes.ReplyEditSubmit",
|
||||
121: "routes.ReplyDeleteSubmit",
|
||||
122: "routes.ReplyLikeSubmit",
|
||||
123: "routes.AddAttachToReplySubmit",
|
||||
124: "routes.RemoveAttachFromReplySubmit",
|
||||
125: "routes.ProfileReplyCreateSubmit",
|
||||
126: "routes.ProfileReplyEditSubmit",
|
||||
127: "routes.ProfileReplyDeleteSubmit",
|
||||
128: "routes.PollVote",
|
||||
129: "routes.PollResults",
|
||||
130: "routes.AccountLogin",
|
||||
131: "routes.AccountRegister",
|
||||
132: "routes.AccountLogout",
|
||||
133: "routes.AccountLoginSubmit",
|
||||
134: "routes.AccountLoginMFAVerify",
|
||||
135: "routes.AccountLoginMFAVerifySubmit",
|
||||
136: "routes.AccountRegisterSubmit",
|
||||
137: "routes.AccountPasswordReset",
|
||||
138: "routes.AccountPasswordResetSubmit",
|
||||
139: "routes.AccountPasswordResetToken",
|
||||
140: "routes.AccountPasswordResetTokenSubmit",
|
||||
141: "routes.DynamicRoute",
|
||||
142: "routes.UploadedFile",
|
||||
143: "routes.StaticFile",
|
||||
144: "routes.RobotsTxt",
|
||||
145: "routes.SitemapXml",
|
||||
146: "routes.OpenSearchXml",
|
||||
147: "routes.BadRoute",
|
||||
148: "routes.HTTPSRedirect",
|
||||
102: "routes.Convos",
|
||||
103: "routes.ConvosCreate",
|
||||
104: "routes.Convo",
|
||||
105: "routes.ConvosCreateSubmit",
|
||||
106: "routes.ConvosDeleteSubmit",
|
||||
107: "routes.ConvosCreateReplySubmit",
|
||||
108: "routes.ConvosDeleteReplySubmit",
|
||||
109: "routes.ConvosEditReplySubmit",
|
||||
110: "routes.ViewProfile",
|
||||
111: "routes.BanUserSubmit",
|
||||
112: "routes.UnbanUser",
|
||||
113: "routes.ActivateUser",
|
||||
114: "routes.IPSearch",
|
||||
115: "routes.CreateTopicSubmit",
|
||||
116: "routes.EditTopicSubmit",
|
||||
117: "routes.DeleteTopicSubmit",
|
||||
118: "routes.StickTopicSubmit",
|
||||
119: "routes.UnstickTopicSubmit",
|
||||
120: "routes.LockTopicSubmit",
|
||||
121: "routes.UnlockTopicSubmit",
|
||||
122: "routes.MoveTopicSubmit",
|
||||
123: "routes.LikeTopicSubmit",
|
||||
124: "routes.AddAttachToTopicSubmit",
|
||||
125: "routes.RemoveAttachFromTopicSubmit",
|
||||
126: "routes.ViewTopic",
|
||||
127: "routes.CreateReplySubmit",
|
||||
128: "routes.ReplyEditSubmit",
|
||||
129: "routes.ReplyDeleteSubmit",
|
||||
130: "routes.ReplyLikeSubmit",
|
||||
131: "routes.AddAttachToReplySubmit",
|
||||
132: "routes.RemoveAttachFromReplySubmit",
|
||||
133: "routes.ProfileReplyCreateSubmit",
|
||||
134: "routes.ProfileReplyEditSubmit",
|
||||
135: "routes.ProfileReplyDeleteSubmit",
|
||||
136: "routes.PollVote",
|
||||
137: "routes.PollResults",
|
||||
138: "routes.AccountLogin",
|
||||
139: "routes.AccountRegister",
|
||||
140: "routes.AccountLogout",
|
||||
141: "routes.AccountLoginSubmit",
|
||||
142: "routes.AccountLoginMFAVerify",
|
||||
143: "routes.AccountLoginMFAVerifySubmit",
|
||||
144: "routes.AccountRegisterSubmit",
|
||||
145: "routes.AccountPasswordReset",
|
||||
146: "routes.AccountPasswordResetSubmit",
|
||||
147: "routes.AccountPasswordResetToken",
|
||||
148: "routes.AccountPasswordResetTokenSubmit",
|
||||
149: "routes.DynamicRoute",
|
||||
150: "routes.UploadedFile",
|
||||
151: "routes.StaticFile",
|
||||
152: "routes.RobotsTxt",
|
||||
153: "routes.SitemapXml",
|
||||
154: "routes.OpenSearchXml",
|
||||
155: "routes.BadRoute",
|
||||
156: "routes.HTTPSRedirect",
|
||||
}
|
||||
var osMapEnum = map[string]int{
|
||||
"unknown": 0,
|
||||
@ -633,7 +657,7 @@ type HTTPSRedirect struct {}
|
||||
|
||||
func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
w.Header().Set("Connection", "close")
|
||||
counters.RouteViewCounter.Bump(148)
|
||||
counters.RouteViewCounter.Bump(156)
|
||||
dest := "https://" + req.Host + req.URL.String()
|
||||
http.Redirect(w, req, dest, http.StatusTemporaryRedirect)
|
||||
}
|
||||
@ -828,6 +852,11 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
h.Set("X-Frame-Options", "deny")
|
||||
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
|
||||
h.Set("X-Content-Type-Options", "nosniff")
|
||||
if c.Config.RefNoRef || !c.Site.EnableSsl {
|
||||
h.Set("Referrer-Policy","no-referrer")
|
||||
} else {
|
||||
h.Set("Referrer-Policy","strict-origin")
|
||||
}
|
||||
}
|
||||
|
||||
if c.Dev.SuperDebug {
|
||||
@ -836,8 +865,8 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
// Increment the request counter
|
||||
counters.GlobalViewCounter.Bump()
|
||||
|
||||
if prefix == "/static" {
|
||||
counters.RouteViewCounter.Bump(143)
|
||||
if prefix == "/s" { //old prefix: /static
|
||||
counters.RouteViewCounter.Bump(151)
|
||||
req.URL.Path += extraData
|
||||
routes.StaticFile(w, req)
|
||||
return
|
||||
@ -988,14 +1017,16 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
counters.LangViewCounter.Bump("none")
|
||||
}
|
||||
|
||||
referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P
|
||||
if referrer != "" {
|
||||
// ? Optimise this a little?
|
||||
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
||||
referrer = strings.Split(referrer,"/")[0]
|
||||
portless := strings.Split(referrer,":")[0]
|
||||
if portless != "localhost" && portless != "127.0.0.1" && portless != c.Site.Host {
|
||||
counters.ReferrerTracker.Bump(referrer)
|
||||
if !c.Config.RefNoTrack {
|
||||
referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P
|
||||
if referrer != "" {
|
||||
// ? Optimise this a little?
|
||||
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
||||
referrer = strings.Split(referrer,"/")[0]
|
||||
portless := strings.Split(referrer,":")[0]
|
||||
if portless != "localhost" && portless != "127.0.0.1" && portless != c.Site.Host {
|
||||
counters.ReferrerTracker.Bump(referrer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1813,9 +1844,110 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
err = routes.LevelList(w,req,user,head)
|
||||
case "/user/convos/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(102)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = routes.Convos(w,req,user,head)
|
||||
case "/user/convos/create/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(103)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = routes.ConvosCreate(w,req,user,head)
|
||||
case "/user/convo/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(104)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = routes.Convo(w,req,user,head,extraData)
|
||||
case "/user/convos/create/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(105)
|
||||
err = routes.ConvosCreateSubmit(w,req,user)
|
||||
case "/user/convos/delete/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(106)
|
||||
err = routes.ConvosDeleteSubmit(w,req,user,extraData)
|
||||
case "/user/convo/create/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(107)
|
||||
err = routes.ConvosCreateReplySubmit(w,req,user)
|
||||
case "/user/convo/delete/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(108)
|
||||
err = routes.ConvosDeleteReplySubmit(w,req,user,extraData)
|
||||
case "/user/convo/edit/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(109)
|
||||
err = routes.ConvosEditReplySubmit(w,req,user,extraData)
|
||||
default:
|
||||
req.URL.Path += extraData
|
||||
counters.RouteViewCounter.Bump(102)
|
||||
counters.RouteViewCounter.Bump(110)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -1835,7 +1967,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(103)
|
||||
counters.RouteViewCounter.Bump(111)
|
||||
err = routes.BanUserSubmit(w,req,user,extraData)
|
||||
case "/users/unban/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1848,7 +1980,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(104)
|
||||
counters.RouteViewCounter.Bump(112)
|
||||
err = routes.UnbanUser(w,req,user,extraData)
|
||||
case "/users/activate/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1861,7 +1993,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(105)
|
||||
counters.RouteViewCounter.Bump(113)
|
||||
err = routes.ActivateUser(w,req,user,extraData)
|
||||
case "/users/ips/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
@ -1869,7 +2001,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(106)
|
||||
counters.RouteViewCounter.Bump(114)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -1893,7 +2025,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(107)
|
||||
counters.RouteViewCounter.Bump(115)
|
||||
err = routes.CreateTopicSubmit(w,req,user)
|
||||
case "/topic/edit/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1906,7 +2038,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(108)
|
||||
counters.RouteViewCounter.Bump(116)
|
||||
err = routes.EditTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/delete/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1920,7 +2052,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
}
|
||||
|
||||
req.URL.Path += extraData
|
||||
counters.RouteViewCounter.Bump(109)
|
||||
counters.RouteViewCounter.Bump(117)
|
||||
err = routes.DeleteTopicSubmit(w,req,user)
|
||||
case "/topic/stick/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1933,7 +2065,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(110)
|
||||
counters.RouteViewCounter.Bump(118)
|
||||
err = routes.StickTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/unstick/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1946,7 +2078,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(111)
|
||||
counters.RouteViewCounter.Bump(119)
|
||||
err = routes.UnstickTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/lock/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1960,7 +2092,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
}
|
||||
|
||||
req.URL.Path += extraData
|
||||
counters.RouteViewCounter.Bump(112)
|
||||
counters.RouteViewCounter.Bump(120)
|
||||
err = routes.LockTopicSubmit(w,req,user)
|
||||
case "/topic/unlock/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1973,7 +2105,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(113)
|
||||
counters.RouteViewCounter.Bump(121)
|
||||
err = routes.UnlockTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/move/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1986,7 +2118,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(114)
|
||||
counters.RouteViewCounter.Bump(122)
|
||||
err = routes.MoveTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/like/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -1999,7 +2131,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(115)
|
||||
counters.RouteViewCounter.Bump(123)
|
||||
err = routes.LikeTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/attach/add/submit/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
@ -2016,7 +2148,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(116)
|
||||
counters.RouteViewCounter.Bump(124)
|
||||
err = routes.AddAttachToTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/attach/remove/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -2029,10 +2161,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(117)
|
||||
counters.RouteViewCounter.Bump(125)
|
||||
err = routes.RemoveAttachFromTopicSubmit(w,req,user,extraData)
|
||||
default:
|
||||
counters.RouteViewCounter.Bump(118)
|
||||
counters.RouteViewCounter.Bump(126)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -2056,7 +2188,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(119)
|
||||
counters.RouteViewCounter.Bump(127)
|
||||
err = routes.CreateReplySubmit(w,req,user)
|
||||
case "/reply/edit/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -2069,7 +2201,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(120)
|
||||
counters.RouteViewCounter.Bump(128)
|
||||
err = routes.ReplyEditSubmit(w,req,user,extraData)
|
||||
case "/reply/delete/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -2082,7 +2214,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(121)
|
||||
counters.RouteViewCounter.Bump(129)
|
||||
err = routes.ReplyDeleteSubmit(w,req,user,extraData)
|
||||
case "/reply/like/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -2095,7 +2227,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(122)
|
||||
counters.RouteViewCounter.Bump(130)
|
||||
err = routes.ReplyLikeSubmit(w,req,user,extraData)
|
||||
case "/reply/attach/add/submit/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
@ -2112,7 +2244,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(123)
|
||||
counters.RouteViewCounter.Bump(131)
|
||||
err = routes.AddAttachToReplySubmit(w,req,user,extraData)
|
||||
case "/reply/attach/remove/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -2125,7 +2257,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(124)
|
||||
counters.RouteViewCounter.Bump(132)
|
||||
err = routes.RemoveAttachFromReplySubmit(w,req,user,extraData)
|
||||
}
|
||||
case "/profile":
|
||||
@ -2141,7 +2273,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(125)
|
||||
counters.RouteViewCounter.Bump(133)
|
||||
err = routes.ProfileReplyCreateSubmit(w,req,user)
|
||||
case "/profile/reply/edit/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -2154,7 +2286,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(126)
|
||||
counters.RouteViewCounter.Bump(134)
|
||||
err = routes.ProfileReplyEditSubmit(w,req,user,extraData)
|
||||
case "/profile/reply/delete/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
@ -2167,7 +2299,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(127)
|
||||
counters.RouteViewCounter.Bump(135)
|
||||
err = routes.ProfileReplyDeleteSubmit(w,req,user,extraData)
|
||||
}
|
||||
case "/poll":
|
||||
@ -2183,23 +2315,23 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(128)
|
||||
counters.RouteViewCounter.Bump(136)
|
||||
err = routes.PollVote(w,req,user,extraData)
|
||||
case "/poll/results/":
|
||||
counters.RouteViewCounter.Bump(129)
|
||||
counters.RouteViewCounter.Bump(137)
|
||||
err = routes.PollResults(w,req,user,extraData)
|
||||
}
|
||||
case "/accounts":
|
||||
switch(req.URL.Path) {
|
||||
case "/accounts/login/":
|
||||
counters.RouteViewCounter.Bump(130)
|
||||
counters.RouteViewCounter.Bump(138)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = routes.AccountLogin(w,req,user,head)
|
||||
case "/accounts/create/":
|
||||
counters.RouteViewCounter.Bump(131)
|
||||
counters.RouteViewCounter.Bump(139)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -2216,7 +2348,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(132)
|
||||
counters.RouteViewCounter.Bump(140)
|
||||
err = routes.AccountLogout(w,req,user)
|
||||
case "/accounts/login/submit/":
|
||||
err = c.ParseForm(w,req,user)
|
||||
@ -2224,10 +2356,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(133)
|
||||
counters.RouteViewCounter.Bump(141)
|
||||
err = routes.AccountLoginSubmit(w,req,user)
|
||||
case "/accounts/mfa_verify/":
|
||||
counters.RouteViewCounter.Bump(134)
|
||||
counters.RouteViewCounter.Bump(142)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -2239,7 +2371,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(135)
|
||||
counters.RouteViewCounter.Bump(143)
|
||||
err = routes.AccountLoginMFAVerifySubmit(w,req,user)
|
||||
case "/accounts/create/submit/":
|
||||
err = c.ParseForm(w,req,user)
|
||||
@ -2247,10 +2379,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(136)
|
||||
counters.RouteViewCounter.Bump(144)
|
||||
err = routes.AccountRegisterSubmit(w,req,user)
|
||||
case "/accounts/password-reset/":
|
||||
counters.RouteViewCounter.Bump(137)
|
||||
counters.RouteViewCounter.Bump(145)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -2262,10 +2394,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(138)
|
||||
counters.RouteViewCounter.Bump(146)
|
||||
err = routes.AccountPasswordResetSubmit(w,req,user)
|
||||
case "/accounts/password-reset/token/":
|
||||
counters.RouteViewCounter.Bump(139)
|
||||
counters.RouteViewCounter.Bump(147)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -2277,7 +2409,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(140)
|
||||
counters.RouteViewCounter.Bump(148)
|
||||
err = routes.AccountPasswordResetTokenSubmit(w,req,user)
|
||||
}
|
||||
/*case "/sitemaps": // TODO: Count these views
|
||||
@ -2294,7 +2426,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
h.Del("Content-Type")
|
||||
h.Del("Content-Encoding")
|
||||
}
|
||||
counters.RouteViewCounter.Bump(142)
|
||||
counters.RouteViewCounter.Bump(150)
|
||||
req.URL.Path += extraData
|
||||
// TODO: Find a way to propagate errors up from this?
|
||||
r.UploadHandler(w,req) // TODO: Count these views
|
||||
@ -2304,7 +2436,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
// TODO: Add support for favicons and robots.txt files
|
||||
switch(extraData) {
|
||||
case "robots.txt":
|
||||
counters.RouteViewCounter.Bump(144)
|
||||
counters.RouteViewCounter.Bump(152)
|
||||
return routes.RobotsTxt(w,req)
|
||||
case "favicon.ico":
|
||||
gzw, ok := w.(c.GzipResponseWriter)
|
||||
@ -2314,14 +2446,14 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
h.Del("Content-Type")
|
||||
h.Del("Content-Encoding")
|
||||
}
|
||||
req.URL.Path = "/static/favicon.ico"
|
||||
req.URL.Path = "/s/favicon.ico"
|
||||
routes.StaticFile(w,req)
|
||||
return nil
|
||||
case "opensearch.xml":
|
||||
counters.RouteViewCounter.Bump(146)
|
||||
counters.RouteViewCounter.Bump(154)
|
||||
return routes.OpenSearchXml(w,req)
|
||||
/*case "sitemap.xml":
|
||||
counters.RouteViewCounter.Bump(145)
|
||||
counters.RouteViewCounter.Bump(153)
|
||||
return routes.SitemapXml(w,req)*/
|
||||
}
|
||||
return c.NotFound(w,req,nil)
|
||||
@ -2332,7 +2464,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
r.RUnlock()
|
||||
|
||||
if ok {
|
||||
counters.RouteViewCounter.Bump(141) // TODO: Be more specific about *which* dynamic route it is
|
||||
counters.RouteViewCounter.Bump(149) // TODO: Be more specific about *which* dynamic route it is
|
||||
req.URL.Path += extraData
|
||||
return handle(w,req,user)
|
||||
}
|
||||
@ -2343,7 +2475,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
} else {
|
||||
r.DumpRequest(req,"Bad Route")
|
||||
}
|
||||
counters.RouteViewCounter.Bump(147)
|
||||
counters.RouteViewCounter.Bump(155)
|
||||
return c.NotFound(w,req,nil)
|
||||
}
|
||||
return err
|
||||
|
@ -567,7 +567,7 @@ func BenchmarkRoutesSerial(b *testing.B) {
|
||||
b.Log("Plugins have already been initialised, they can't be deinitialised so these tests will run with plugins on")
|
||||
}
|
||||
static_w := httptest.NewRecorder()
|
||||
static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil))
|
||||
static_req := httptest.NewRequest("get","/s/global.js",bytes.NewReader(nil))
|
||||
static_handler := http.HandlerFunc(route_static)
|
||||
|
||||
topic_w := httptest.NewRecorder()
|
||||
@ -1134,7 +1134,7 @@ func TestStaticRoute(t *testing.T) {
|
||||
}
|
||||
|
||||
static_w := httptest.NewRecorder()
|
||||
static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil))
|
||||
static_req := httptest.NewRequest("get","/s/global.js",bytes.NewReader(nil))
|
||||
static_handler := http.HandlerFunc(route_static)
|
||||
|
||||
static_handler.ServeHTTP(static_w,static_req)
|
||||
|
@ -318,6 +318,8 @@
|
||||
"password_reset_email_sent":"An email was sent to you. Please follow the steps within.",
|
||||
"password_reset_token_token_verified":"Your password was successfully updated.",
|
||||
|
||||
"convo_dev":"Messages are currently under development. Some features may not work yet and your messages may be purged every now and then.",
|
||||
|
||||
"panel_forum_created":"The forum was successfully created.",
|
||||
"panel_forum_deleted":"The forum was successfully deleted.",
|
||||
"panel_forum_updated":"The forum was successfully updated.",
|
||||
|
4
main.go
4
main.go
@ -134,10 +134,10 @@ func storeInit() (err error) {
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
/*c.Convos, err = c.NewDefaultConversationStore(acc)
|
||||
c.Convos, err = c.NewDefaultConversationStore(acc)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}*/
|
||||
}
|
||||
|
||||
err = phrases.InitPhrases(c.Site.Language)
|
||||
if err != nil {
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
)
|
||||
|
||||
type tblColumn = qgen.DBTableColumn
|
||||
type tC = tblColumn
|
||||
type tblKey = qgen.DBTableKey
|
||||
|
||||
func init() {
|
||||
@ -35,6 +36,7 @@ func init() {
|
||||
addPatch(20, patch20)
|
||||
addPatch(21, patch21)
|
||||
addPatch(22, patch22)
|
||||
addPatch(23, patch23)
|
||||
}
|
||||
|
||||
func patch0(scanner *bufio.Scanner) (err error) {
|
||||
@ -48,8 +50,8 @@ func patch0(scanner *bufio.Scanner) (err error) {
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.CreateTable("menus", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"mid", "int", 0, false, true, ""},
|
||||
[]tC{
|
||||
tC{"mid", "int", 0, false, true, ""},
|
||||
},
|
||||
[]tblKey{
|
||||
tblKey{"mid", "primary","",false},
|
||||
@ -60,23 +62,23 @@ func patch0(scanner *bufio.Scanner) (err error) {
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.CreateTable("menu_items", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"miid", "int", 0, false, true, ""},
|
||||
tblColumn{"mid", "int", 0, false, false, ""},
|
||||
tblColumn{"name", "varchar", 200, false, false, ""},
|
||||
tblColumn{"htmlID", "varchar", 200, false, false, "''"},
|
||||
tblColumn{"cssClass", "varchar", 200, false, false, "''"},
|
||||
tblColumn{"position", "varchar", 100, false, false, ""},
|
||||
tblColumn{"path", "varchar", 200, false, false, "''"},
|
||||
tblColumn{"aria", "varchar", 200, false, false, "''"},
|
||||
tblColumn{"tooltip", "varchar", 200, false, false, "''"},
|
||||
tblColumn{"tmplName", "varchar", 200, false, false, "''"},
|
||||
tblColumn{"order", "int", 0, false, false, "0"},
|
||||
[]tC{
|
||||
tC{"miid", "int", 0, false, true, ""},
|
||||
tC{"mid", "int", 0, false, false, ""},
|
||||
tC{"name", "varchar", 200, false, false, ""},
|
||||
tC{"htmlID", "varchar", 200, false, false, "''"},
|
||||
tC{"cssClass", "varchar", 200, false, false, "''"},
|
||||
tC{"position", "varchar", 100, false, false, ""},
|
||||
tC{"path", "varchar", 200, false, false, "''"},
|
||||
tC{"aria", "varchar", 200, false, false, "''"},
|
||||
tC{"tooltip", "varchar", 200, false, false, "''"},
|
||||
tC{"tmplName", "varchar", 200, false, false, "''"},
|
||||
tC{"order", "int", 0, false, false, "0"},
|
||||
|
||||
tblColumn{"guestOnly", "boolean", 0, false, false, "0"},
|
||||
tblColumn{"memberOnly", "boolean", 0, false, false, "0"},
|
||||
tblColumn{"staffOnly", "boolean", 0, false, false, "0"},
|
||||
tblColumn{"adminOnly", "boolean", 0, false, false, "0"},
|
||||
tC{"guestOnly", "boolean", 0, false, false, "0"},
|
||||
tC{"memberOnly", "boolean", 0, false, false, "0"},
|
||||
tC{"staffOnly", "boolean", 0, false, false, "0"},
|
||||
tC{"adminOnly", "boolean", 0, false, false, "0"},
|
||||
},
|
||||
[]tblKey{
|
||||
tblKey{"miid", "primary","",false},
|
||||
@ -176,14 +178,14 @@ func patch2(scanner *bufio.Scanner) error {
|
||||
|
||||
func patch3(scanner *bufio.Scanner) error {
|
||||
return execStmt(qgen.Builder.CreateTable("registration_logs", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"rlid", "int", 0, false, true, ""},
|
||||
tblColumn{"username", "varchar", 100, false, false, ""},
|
||||
tblColumn{"email", "varchar", 100, false, false, ""},
|
||||
tblColumn{"failureReason", "varchar", 100, false, false, ""},
|
||||
tblColumn{"success", "bool", 0, false, false, "0"}, // Did this attempt succeed?
|
||||
tblColumn{"ipaddress", "varchar", 200, false, false, ""},
|
||||
tblColumn{"doneAt", "createdAt", 0, false, false, ""},
|
||||
[]tC{
|
||||
tC{"rlid", "int", 0, false, true, ""},
|
||||
tC{"username", "varchar", 100, false, false, ""},
|
||||
tC{"email", "varchar", 100, false, false, ""},
|
||||
tC{"failureReason", "varchar", 100, false, false, ""},
|
||||
tC{"success", "bool", 0, false, false, "0"}, // Did this attempt succeed?
|
||||
tC{"ipaddress", "varchar", 200, false, false, ""},
|
||||
tC{"doneAt", "createdAt", 0, false, false, ""},
|
||||
},
|
||||
[]tblKey{
|
||||
tblKey{"rlid", "primary","",false},
|
||||
@ -240,13 +242,13 @@ func patch4(scanner *bufio.Scanner) error {
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.CreateTable("pages", "utf8mb4", "utf8mb4_general_ci",
|
||||
[]tblColumn{
|
||||
tblColumn{"pid", "int", 0, false, true, ""},
|
||||
tblColumn{"name", "varchar", 200, false, false, ""},
|
||||
tblColumn{"title", "varchar", 200, false, false, ""},
|
||||
tblColumn{"body", "text", 0, false, false, ""},
|
||||
tblColumn{"allowedGroups", "text", 0, false, false, ""},
|
||||
tblColumn{"menuID", "int", 0, false, false, "-1"},
|
||||
[]tC{
|
||||
tC{"pid", "int", 0, false, true, ""},
|
||||
tC{"name", "varchar", 200, false, false, ""},
|
||||
tC{"title", "varchar", 200, false, false, ""},
|
||||
tC{"body", "text", 0, false, false, ""},
|
||||
tC{"allowedGroups", "text", 0, false, false, ""},
|
||||
tC{"menuID", "int", 0, false, false, "-1"},
|
||||
},
|
||||
[]tblKey{
|
||||
tblKey{"pid", "primary","",false},
|
||||
@ -278,18 +280,18 @@ func patch5(scanner *bufio.Scanner) error {
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.CreateTable("users_2fa_keys", "utf8mb4", "utf8mb4_general_ci",
|
||||
[]tblColumn{
|
||||
tblColumn{"uid", "int", 0, false, false, ""},
|
||||
tblColumn{"secret", "varchar", 100, false, false, ""},
|
||||
tblColumn{"scratch1", "varchar", 50, false, false, ""},
|
||||
tblColumn{"scratch2", "varchar", 50, false, false, ""},
|
||||
tblColumn{"scratch3", "varchar", 50, false, false, ""},
|
||||
tblColumn{"scratch4", "varchar", 50, false, false, ""},
|
||||
tblColumn{"scratch5", "varchar", 50, false, false, ""},
|
||||
tblColumn{"scratch6", "varchar", 50, false, false, ""},
|
||||
tblColumn{"scratch7", "varchar", 50, false, false, ""},
|
||||
tblColumn{"scratch8", "varchar", 50, false, false, ""},
|
||||
tblColumn{"createdAt", "createdAt", 0, false, false, ""},
|
||||
[]tC{
|
||||
tC{"uid", "int", 0, false, false, ""},
|
||||
tC{"secret", "varchar", 100, false, false, ""},
|
||||
tC{"scratch1", "varchar", 50, false, false, ""},
|
||||
tC{"scratch2", "varchar", 50, false, false, ""},
|
||||
tC{"scratch3", "varchar", 50, false, false, ""},
|
||||
tC{"scratch4", "varchar", 50, false, false, ""},
|
||||
tC{"scratch5", "varchar", 50, false, false, ""},
|
||||
tC{"scratch6", "varchar", 50, false, false, ""},
|
||||
tC{"scratch7", "varchar", 50, false, false, ""},
|
||||
tC{"scratch8", "varchar", 50, false, false, ""},
|
||||
tC{"createdAt", "createdAt", 0, false, false, ""},
|
||||
},
|
||||
[]tblKey{
|
||||
tblKey{"uid", "primary","",false},
|
||||
@ -308,8 +310,8 @@ func patch6(scanner *bufio.Scanner) error {
|
||||
|
||||
func patch7(scanner *bufio.Scanner) error {
|
||||
return execStmt(qgen.Builder.CreateTable("users_avatar_queue", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||
[]tC{
|
||||
tC{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||
},
|
||||
[]tblKey{
|
||||
tblKey{"uid", "primary","",false},
|
||||
@ -371,8 +373,8 @@ func patch8(scanner *bufio.Scanner) error {
|
||||
return err
|
||||
}
|
||||
return execStmt(qgen.Builder.CreateTable("updates", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"dbVersion", "int", 0, false, false, "0"},
|
||||
[]tC{
|
||||
tC{"dbVersion", "int", 0, false, false, "0"},
|
||||
},
|
||||
[]tblKey{},
|
||||
))
|
||||
@ -386,12 +388,12 @@ func patch9(scanner *bufio.Scanner) error {
|
||||
}
|
||||
|
||||
return execStmt(qgen.Builder.CreateTable("login_logs", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"lid", "int", 0, false, true, ""},
|
||||
tblColumn{"uid", "int", 0, false, false, ""},
|
||||
tblColumn{"success", "bool", 0, false, false, "0"}, // Did this attempt succeed?
|
||||
tblColumn{"ipaddress", "varchar", 200, false, false, ""},
|
||||
tblColumn{"doneAt", "createdAt", 0, false, false, ""},
|
||||
[]tC{
|
||||
tC{"lid", "int", 0, false, true, ""},
|
||||
tC{"uid", "int", 0, false, false, ""},
|
||||
tC{"success", "bool", 0, false, false, "0"}, // Did this attempt succeed?
|
||||
tC{"ipaddress", "varchar", 200, false, false, ""},
|
||||
tC{"doneAt", "createdAt", 0, false, false, ""},
|
||||
},
|
||||
[]tblKey{
|
||||
tblKey{"lid", "primary","",false},
|
||||
@ -403,11 +405,11 @@ var acc = qgen.NewAcc
|
||||
var itoa = strconv.Itoa
|
||||
|
||||
func patch10(scanner *bufio.Scanner) error {
|
||||
err := execStmt(qgen.Builder.AddColumn("topics", tblColumn{"attachCount", "int", 0, false, false, "0"}, nil))
|
||||
err := execStmt(qgen.Builder.AddColumn("topics", tC{"attachCount", "int", 0, false, false, "0"}, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = execStmt(qgen.Builder.AddColumn("topics", tblColumn{"lastReplyID", "int", 0, false, false, "0"}, nil))
|
||||
err = execStmt(qgen.Builder.AddColumn("topics", tC{"lastReplyID", "int", 0, false, false, "0"}, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -443,7 +445,7 @@ func patch10(scanner *bufio.Scanner) error {
|
||||
}
|
||||
|
||||
func patch11(scanner *bufio.Scanner) error {
|
||||
err := execStmt(qgen.Builder.AddColumn("replies", tblColumn{"attachCount", "int", 0, false, false, "0"}, nil))
|
||||
err := execStmt(qgen.Builder.AddColumn("replies", tC{"attachCount", "int", 0, false, false, "0"}, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -517,7 +519,7 @@ func patch12(scanner *bufio.Scanner) error {
|
||||
}
|
||||
|
||||
func patch13(scanner *bufio.Scanner) error {
|
||||
err := execStmt(qgen.Builder.AddColumn("widgets", tblColumn{"wid", "int", 0, false, true, ""}, &tblKey{"wid", "primary","",false}))
|
||||
err := execStmt(qgen.Builder.AddColumn("widgets", tC{"wid", "int", 0, false, true, ""}, &tblKey{"wid", "primary","",false}))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -548,18 +550,18 @@ func patch15(scanner *bufio.Scanner) error {
|
||||
|
||||
func patch16(scanner *bufio.Scanner) error {
|
||||
return execStmt(qgen.Builder.CreateTable("password_resets", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"email", "varchar", 200, false, false, ""},
|
||||
tblColumn{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||
tblColumn{"validated", "varchar", 200, false, false, ""}, // Token given once the one-use token is consumed, used to prevent multiple people consuming the same one-use token
|
||||
tblColumn{"token", "varchar", 200, false, false, ""},
|
||||
tblColumn{"createdAt", "createdAt", 0, false, false, ""},
|
||||
[]tC{
|
||||
tC{"email", "varchar", 200, false, false, ""},
|
||||
tC{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||
tC{"validated", "varchar", 200, false, false, ""}, // Token given once the one-use token is consumed, used to prevent multiple people consuming the same one-use token
|
||||
tC{"token", "varchar", 200, false, false, ""},
|
||||
tC{"createdAt", "createdAt", 0, false, false, ""},
|
||||
}, nil,
|
||||
))
|
||||
}
|
||||
|
||||
func patch17(scanner *bufio.Scanner) error {
|
||||
err := execStmt(qgen.Builder.AddColumn("attachments", tblColumn{"extra", "varchar", 200, false, false, ""}, nil))
|
||||
err := execStmt(qgen.Builder.AddColumn("attachments", tC{"extra", "varchar", 200, false, false, ""}, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -595,14 +597,14 @@ func patch17(scanner *bufio.Scanner) error {
|
||||
}
|
||||
|
||||
func patch18(scanner *bufio.Scanner) error {
|
||||
return execStmt(qgen.Builder.AddColumn("forums", tblColumn{"order", "int", 0, false, false, "0"}, nil))
|
||||
return execStmt(qgen.Builder.AddColumn("forums", tC{"order", "int", 0, false, false, "0"}, nil))
|
||||
}
|
||||
|
||||
func patch19(scanner *bufio.Scanner) error {
|
||||
return execStmt(qgen.Builder.CreateTable("memchunks", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"count", "int", 0, false, false, "0"},
|
||||
tblColumn{"createdAt", "datetime", 0, false, false, ""},
|
||||
[]tC{
|
||||
tC{"count", "int", 0, false, false, "0"},
|
||||
tC{"createdAt", "datetime", 0, false, false, ""},
|
||||
}, nil,
|
||||
))
|
||||
}
|
||||
@ -631,29 +633,82 @@ func patch20(scanner *bufio.Scanner) error {
|
||||
}
|
||||
|
||||
func patch21(scanner *bufio.Scanner) error {
|
||||
err := execStmt(qgen.Builder.AddColumn("memchunks", tblColumn{"stack", "int", 0, false, false, "0"}, nil))
|
||||
err := execStmt(qgen.Builder.AddColumn("memchunks", tC{"stack", "int", 0, false, false, "0"}, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.AddColumn("memchunks", tblColumn{"heap", "int", 0, false, false, "0"}, nil))
|
||||
err = execStmt(qgen.Builder.AddColumn("memchunks", tC{"heap", "int", 0, false, false, "0"}, nil))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.CreateTable("meta", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"name", "varchar", 200, false, false, ""},
|
||||
tblColumn{"value", "varchar", 200, false, false, ""},
|
||||
[]tC{
|
||||
tC{"name", "varchar", 200, false, false, ""},
|
||||
tC{"value", "varchar", 200, false, false, ""},
|
||||
}, nil,
|
||||
))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return execStmt(qgen.Builder.AddColumn("activity_stream", tblColumn{"createdAt", "createdAt", 0, false, false, ""}, nil))
|
||||
return execStmt(qgen.Builder.AddColumn("activity_stream", tC{"createdAt", "createdAt", 0, false, false, ""}, nil))
|
||||
}
|
||||
|
||||
func patch22(scanner *bufio.Scanner) error {
|
||||
return execStmt(qgen.Builder.AddColumn("forums", tblColumn{"tmpl", "varchar", 200, false, false, "''"}, nil))
|
||||
return execStmt(qgen.Builder.AddColumn("forums", tC{"tmpl", "varchar", 200, false, false, "''"}, nil))
|
||||
}
|
||||
|
||||
func patch23(scanner *bufio.Scanner) error {
|
||||
err := execStmt(qgen.Builder.DropTable("conversations"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = execStmt(qgen.Builder.CreateTable("conversations", "", "",
|
||||
[]tC{
|
||||
tC{"cid", "int", 0, false, true, ""},
|
||||
tC{"createdBy", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||
tC{"createdAt", "createdAt", 0, false, false, ""},
|
||||
tC{"lastReplyAt", "datetime", 0, false, false, ""},
|
||||
tC{"lastReplyBy", "int", 0, false, false, ""},
|
||||
},
|
||||
[]tblKey{
|
||||
tblKey{"cid", "primary","",false},
|
||||
},
|
||||
))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.DropTable("conversations_posts"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = execStmt(qgen.Builder.CreateTable("conversations_posts", "", "",
|
||||
[]tC{
|
||||
tC{"pid", "int", 0, false, true, ""},
|
||||
tC{"cid", "int", 0, false, false, ""},
|
||||
tC{"createdBy", "int", 0, false, false, ""},
|
||||
tC{"body", "varchar", 50, false, false, ""},
|
||||
tC{"post", "varchar", 50, false, false, "''"},
|
||||
},
|
||||
[]tblKey{
|
||||
tblKey{"pid", "primary","",false},
|
||||
},
|
||||
))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.DropTable("conversations_participants"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return execStmt(qgen.Builder.CreateTable("conversations_participants", "", "",
|
||||
[]tC{
|
||||
tC{"uid", "int", 0, false, false, ""},
|
||||
tC{"cid", "int", 0, false, false, ""},
|
||||
}, nil,
|
||||
))
|
||||
}
|
@ -83,9 +83,9 @@ function asyncGetScript(source) {
|
||||
}
|
||||
|
||||
function notifyOnScript(source) {
|
||||
source = "/static/"+source;
|
||||
source = "/s/"+source;
|
||||
return new Promise((resolve, reject) => {
|
||||
let ss = source.replace("/static/","");
|
||||
let ss = source.replace("/s/","");
|
||||
try {
|
||||
let ssp = ss.charAt(0).toUpperCase() + ss.slice(1)
|
||||
console.log("ssp:",ssp)
|
||||
@ -138,8 +138,8 @@ function loadScript(name, callback,fail) {
|
||||
let parts = value.split("; current_theme=");
|
||||
if (parts.length == 2) fname += "_"+ parts.pop().split(";").shift();
|
||||
|
||||
let url = "/static/"+fname+".js"
|
||||
let iurl = "/static/"+name+".js"
|
||||
let url = "/s/"+fname+".js"
|
||||
let iurl = "/s/"+name+".js"
|
||||
asyncGetScript(url)
|
||||
.then(callback)
|
||||
.catch((e) => {
|
||||
@ -161,7 +161,7 @@ function loadScript(name, callback,fail) {
|
||||
|
||||
/*
|
||||
function loadTmpl(name,callback) {
|
||||
let url = "/static/"+name
|
||||
let url = "/s/"+name
|
||||
let worker = new Worker(url);
|
||||
}
|
||||
*/
|
||||
|
2
public/jquery-emojiarea/emojis.js
vendored
2
public/jquery-emojiarea/emojis.js
vendored
@ -1,4 +1,4 @@
|
||||
$.emojiarea.path = '/static/smilies/emojiarea';
|
||||
$.emojiarea.path = '/s/smilies/emojiarea';
|
||||
$.emojiarea.icons = [{"name" : "<i class='icon-smile'></i>", "icons" : {':bowtie:' : 'bowtie.png',
|
||||
':smile:' : 'smile.png',
|
||||
':laughing:' : 'laughing.png',
|
||||
|
@ -654,7 +654,7 @@ func (a *MysqlAdapter) complexSelect(preBuilder *selectPrebuilder, sb *strings.B
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adapter *MysqlAdapter) SimpleLeftJoin(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (string, error) {
|
||||
func (a *MysqlAdapter) SimpleLeftJoin(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (string, error) {
|
||||
if table1 == "" {
|
||||
return "", errors.New("You need a name for the left table")
|
||||
}
|
||||
@ -668,7 +668,7 @@ func (adapter *MysqlAdapter) SimpleLeftJoin(name string, table1 string, table2 s
|
||||
return "", errors.New("No joiners found for SimpleLeftJoin")
|
||||
}
|
||||
|
||||
whereStr, err := adapter.buildJoinWhere(where)
|
||||
whereStr, err := a.buildJoinWhere(where)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -684,14 +684,14 @@ func (adapter *MysqlAdapter) SimpleLeftJoin(name string, table1 string, table2 s
|
||||
as2 = " AS `"+ thalf2[1]+"`"
|
||||
}
|
||||
|
||||
var querystr = "SELECT" + adapter.buildJoinColumns(columns) + " FROM `" + thalf1[0] + "`"+as1+" LEFT JOIN `" + thalf2[0] + "`"+as2+" ON " + adapter.buildJoiners(joiners) + whereStr + adapter.buildOrderby(orderby) + adapter.buildLimit(limit)
|
||||
q := "SELECT" + a.buildJoinColumns(columns) + " FROM `" + thalf1[0] + "`"+as1+" LEFT JOIN `" + thalf2[0] + "`"+as2+" ON " + a.buildJoiners(joiners) + whereStr + a.buildOrderby(orderby) + a.buildLimit(limit)
|
||||
|
||||
querystr = strings.TrimSpace(querystr)
|
||||
adapter.pushStatement(name, "select", querystr)
|
||||
return querystr, nil
|
||||
q = strings.TrimSpace(q)
|
||||
a.pushStatement(name, "select", q)
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (adapter *MysqlAdapter) SimpleInnerJoin(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (string, error) {
|
||||
func (a *MysqlAdapter) SimpleInnerJoin(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (string, error) {
|
||||
if table1 == "" {
|
||||
return "", errors.New("You need a name for the left table")
|
||||
}
|
||||
@ -705,16 +705,27 @@ func (adapter *MysqlAdapter) SimpleInnerJoin(name string, table1 string, table2
|
||||
return "", errors.New("No joiners found for SimpleInnerJoin")
|
||||
}
|
||||
|
||||
whereStr, err := adapter.buildJoinWhere(where)
|
||||
whereStr, err := a.buildJoinWhere(where)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var querystr = "SELECT " + adapter.buildJoinColumns(columns) + " FROM `" + table1 + "` INNER JOIN `" + table2 + "` ON " + adapter.buildJoiners(joiners) + whereStr + adapter.buildOrderby(orderby) + adapter.buildLimit(limit)
|
||||
thalf1 := strings.Split(strings.Replace(table1," as ", " AS ",-1)," AS ")
|
||||
var as1 string
|
||||
if len(thalf1) == 2 {
|
||||
as1 = " AS `"+ thalf1[1]+"`"
|
||||
}
|
||||
thalf2 := strings.Split(strings.Replace(table2," as ", " AS ",-1)," AS ")
|
||||
var as2 string
|
||||
if len(thalf2) == 2 {
|
||||
as2 = " AS `"+ thalf2[1]+"`"
|
||||
}
|
||||
|
||||
querystr = strings.TrimSpace(querystr)
|
||||
adapter.pushStatement(name, "select", querystr)
|
||||
return querystr, nil
|
||||
q := "SELECT " + a.buildJoinColumns(columns) + " FROM `" + thalf1[0] + "`"+as1+" INNER JOIN `" + thalf2[0] + "`"+as2+" ON " + a.buildJoiners(joiners) + whereStr + a.buildOrderby(orderby) + a.buildLimit(limit)
|
||||
|
||||
q = strings.TrimSpace(q)
|
||||
a.pushStatement(name, "select", q)
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (adapter *MysqlAdapter) SimpleUpdateSelect(up *updatePrebuilder) (string, error) {
|
||||
@ -767,7 +778,7 @@ func (adapter *MysqlAdapter) SimpleInsertLeftJoin(name string, ins DBInsert, sel
|
||||
return "", err
|
||||
}
|
||||
|
||||
var q = "INSERT INTO `" + ins.Table + "`(" + adapter.buildColumns(ins.Columns) + ") SELECT" + adapter.buildJoinColumns(sel.Columns) + " FROM `" + sel.Table1 + "` LEFT JOIN `" + sel.Table2 + "` ON " + adapter.buildJoiners(sel.Joiners) + whereStr + adapter.buildOrderby(sel.Orderby) + adapter.buildLimit(sel.Limit)
|
||||
q := "INSERT INTO `" + ins.Table + "`(" + adapter.buildColumns(ins.Columns) + ") SELECT" + adapter.buildJoinColumns(sel.Columns) + " FROM `" + sel.Table1 + "` LEFT JOIN `" + sel.Table2 + "` ON " + adapter.buildJoiners(sel.Joiners) + whereStr + adapter.buildOrderby(sel.Orderby) + adapter.buildLimit(sel.Limit)
|
||||
|
||||
q = strings.TrimSpace(q)
|
||||
adapter.pushStatement(name, "insert", q)
|
||||
@ -856,7 +867,7 @@ func (adapter *MysqlAdapter) SimpleInsertInnerJoin(name string, ins DBInsert, se
|
||||
return "", err
|
||||
}
|
||||
|
||||
var q = "INSERT INTO `" + ins.Table + "`(" + adapter.buildColumns(ins.Columns) + ") SELECT" + adapter.buildJoinColumns(sel.Columns) + " FROM `" + sel.Table1 + "` INNER JOIN `" + sel.Table2 + "` ON " + adapter.buildJoiners(sel.Joiners) + whereStr + adapter.buildOrderby(sel.Orderby) + adapter.buildLimit(sel.Limit)
|
||||
q := "INSERT INTO `" + ins.Table + "`(" + adapter.buildColumns(ins.Columns) + ") SELECT" + adapter.buildJoinColumns(sel.Columns) + " FROM `" + sel.Table1 + "` INNER JOIN `" + sel.Table2 + "` ON " + adapter.buildJoiners(sel.Joiners) + whereStr + adapter.buildOrderby(sel.Orderby) + adapter.buildLimit(sel.Limit)
|
||||
|
||||
q = strings.TrimSpace(q)
|
||||
adapter.pushStatement(name, "insert", q)
|
||||
@ -882,13 +893,13 @@ func (adapter *MysqlAdapter) Builder() *prebuilder {
|
||||
return &prebuilder{adapter}
|
||||
}
|
||||
|
||||
func (adapter *MysqlAdapter) Write() error {
|
||||
func (a *MysqlAdapter) Write() error {
|
||||
var stmts, body string
|
||||
for _, name := range adapter.BufferOrder {
|
||||
for _, name := range a.BufferOrder {
|
||||
if name[0] == '_' {
|
||||
continue
|
||||
}
|
||||
stmt := adapter.Buffer[name]
|
||||
stmt := a.Buffer[name]
|
||||
// ? - Table creation might be a little complex for Go to do outside a SQL file :(
|
||||
if stmt.Type == "upsert" {
|
||||
stmts += "\t" + name + " *qgen.MySQLUpsertCallback\n"
|
||||
@ -945,12 +956,12 @@ func _gen_mysql() (err error) {
|
||||
}
|
||||
|
||||
// Internal methods, not exposed in the interface
|
||||
func (adapter *MysqlAdapter) pushStatement(name string, stype string, querystr string) {
|
||||
func (a *MysqlAdapter) pushStatement(name string, stype string, querystr string) {
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
adapter.Buffer[name] = DBStmt{querystr, stype}
|
||||
adapter.BufferOrder = append(adapter.BufferOrder, name)
|
||||
a.Buffer[name] = DBStmt{querystr, stype}
|
||||
a.BufferOrder = append(a.BufferOrder, name)
|
||||
}
|
||||
|
||||
func (adapter *MysqlAdapter) stringyType(ctype string) bool {
|
||||
|
@ -593,6 +593,11 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
h.Set("X-Frame-Options", "deny")
|
||||
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
|
||||
h.Set("X-Content-Type-Options", "nosniff")
|
||||
if c.Config.RefNoRef || !c.Site.EnableSsl {
|
||||
h.Set("Referrer-Policy","no-referrer")
|
||||
} else {
|
||||
h.Set("Referrer-Policy","strict-origin")
|
||||
}
|
||||
}
|
||||
|
||||
if c.Dev.SuperDebug {
|
||||
@ -601,7 +606,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
// Increment the request counter
|
||||
counters.GlobalViewCounter.Bump()
|
||||
|
||||
if prefix == "/static" {
|
||||
if prefix == "/s" { //old prefix: /static
|
||||
counters.RouteViewCounter.Bump({{ index .AllRouteMap "routes.StaticFile" }})
|
||||
req.URL.Path += extraData
|
||||
routes.StaticFile(w, req)
|
||||
@ -753,14 +758,16 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
counters.LangViewCounter.Bump("none")
|
||||
}
|
||||
|
||||
referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P
|
||||
if referrer != "" {
|
||||
// ? Optimise this a little?
|
||||
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
||||
referrer = strings.Split(referrer,"/")[0]
|
||||
portless := strings.Split(referrer,":")[0]
|
||||
if portless != "localhost" && portless != "127.0.0.1" && portless != c.Site.Host {
|
||||
counters.ReferrerTracker.Bump(referrer)
|
||||
if !c.Config.RefNoTrack {
|
||||
referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P
|
||||
if referrer != "" {
|
||||
// ? Optimise this a little?
|
||||
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
||||
referrer = strings.Split(referrer,"/")[0]
|
||||
portless := strings.Split(referrer,":")[0]
|
||||
if portless != "localhost" && portless != "127.0.0.1" && portless != c.Site.Host {
|
||||
counters.ReferrerTracker.Bump(referrer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -840,7 +847,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||
h.Del("Content-Type")
|
||||
h.Del("Content-Encoding")
|
||||
}
|
||||
req.URL.Path = "/static/favicon.ico"
|
||||
req.URL.Path = "/s/favicon.ico"
|
||||
routes.StaticFile(w,req)
|
||||
return nil
|
||||
case "opensearch.xml":
|
||||
|
@ -49,7 +49,7 @@ func userRoutes() *RouteGroup {
|
||||
return newRouteGroup("/user/").Routes(
|
||||
View("routes.ViewProfile", "/user/").LitBefore("req.URL.Path += extraData"),
|
||||
|
||||
Set("routes.AccountEdit","/user/edit",
|
||||
Set("routes.AccountEdit", "/user/edit/",
|
||||
MView("", "/"),
|
||||
MView("Password", "/password/"),
|
||||
Action("PasswordSubmit", "/password/submit/"), // TODO: Full test this
|
||||
@ -82,14 +82,15 @@ func userRoutes() *RouteGroup {
|
||||
MView("routes.LevelList", "/user/levels/"),
|
||||
//MView("routes.LevelRankings", "/user/rankings/"),
|
||||
//MView("routes.Alerts", "/user/alerts/"),
|
||||
|
||||
/*MView("routes.Convos", "/user/convos/"),
|
||||
|
||||
MView("routes.Convos", "/user/convos/"),
|
||||
MView("routes.ConvosCreate", "/user/convos/create/"),
|
||||
MView("routes.Convo", "/user/convo/","extraData"),
|
||||
MView("routes.Convo", "/user/convo/", "extraData"),
|
||||
Action("routes.ConvosCreateSubmit", "/user/convos/create/submit/"),
|
||||
Action("routes.ConvosDeleteSubmit", "/user/convos/delete/submit/","extraData"),
|
||||
Action("routes.ConvosDeleteSubmit", "/user/convos/delete/submit/", "extraData"),
|
||||
Action("routes.ConvosCreateReplySubmit", "/user/convo/create/submit/"),
|
||||
Action("routes.ConvosDeleteReplySubmit", "/user/convo/delete/submit/"),*/
|
||||
Action("routes.ConvosDeleteReplySubmit", "/user/convo/delete/submit/","extraData"),
|
||||
Action("routes.ConvosEditReplySubmit", "/user/convo/edit/submit/", "extraData"),
|
||||
)
|
||||
}
|
||||
|
||||
@ -171,6 +172,8 @@ func accountRoutes() *RouteGroup {
|
||||
func panelRoutes() *RouteGroup {
|
||||
return newRouteGroup("/panel/").Before("SuperModOnly").NoHeader().Routes(
|
||||
View("panel.Dashboard", "/panel/"),
|
||||
//View("panel.StatsDisk", "/panel/stats/disk/"),
|
||||
|
||||
View("panel.Forums", "/panel/forums/"),
|
||||
Action("panel.ForumsCreateSubmit", "/panel/forums/create/"),
|
||||
Action("panel.ForumsDelete", "/panel/forums/delete/", "extraData"),
|
||||
|
@ -21,8 +21,8 @@ func ParseSEOURL(urlBit string) (slug string, id int, err error) {
|
||||
return halves[0], tid, err
|
||||
}
|
||||
|
||||
var slen1 = len("</static/>; rel=preload; as=script,")
|
||||
var slen2 = len("</static/>; rel=preload; as=style,")
|
||||
var slen1 = len("</s/>; rel=preload; as=script,")
|
||||
var slen2 = len("</s/>; rel=preload; as=style,")
|
||||
|
||||
func doPush(w http.ResponseWriter, header *c.Header) {
|
||||
//fmt.Println("in doPush")
|
||||
@ -32,7 +32,7 @@ func doPush(w http.ResponseWriter, header *c.Header) {
|
||||
var push = func(in []string) {
|
||||
sb.Grow((slen1 + 5) * len(in))
|
||||
for _, path := range in {
|
||||
sb.WriteString("</static/")
|
||||
sb.WriteString("</s/")
|
||||
sb.WriteString(path)
|
||||
sb.WriteString(">; rel=preload; as=script,")
|
||||
}
|
||||
@ -44,7 +44,7 @@ func doPush(w http.ResponseWriter, header *c.Header) {
|
||||
if len(header.Stylesheets) > 0 {
|
||||
sb.Grow((slen2 + 6) * len(header.Stylesheets))
|
||||
for _, path := range header.Stylesheets {
|
||||
sb.WriteString("</static/")
|
||||
sb.WriteString("</s/")
|
||||
sb.WriteString(path)
|
||||
sb.WriteString(">; rel=preload; as=style,")
|
||||
}
|
||||
@ -69,9 +69,9 @@ func doPush(w http.ResponseWriter, header *c.Header) {
|
||||
|
||||
var push = func(in []string) {
|
||||
for _, path := range in {
|
||||
//fmt.Println("pushing /static/" + path)
|
||||
//fmt.Println("pushing /s/" + path)
|
||||
// TODO: Avoid concatenating here
|
||||
err := pusher.Push("/static/"+path, nil)
|
||||
err := pusher.Push("/s/"+path, nil)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
@ -116,7 +116,7 @@ func renderTemplate3(tmplName string, hookName string, w http.ResponseWriter, r
|
||||
h.Stylesheets = nil
|
||||
c.PrepResources(&h.CurrentUser, h, h.Theme)
|
||||
for _, ss := range s {
|
||||
h.Stylesheets = append(h.Stylesheets,ss)
|
||||
h.Stylesheets = append(h.Stylesheets, ss)
|
||||
}
|
||||
|
||||
if h.CurrentUser.Loggedin {
|
||||
@ -141,4 +141,4 @@ func renderTemplate3(tmplName string, hookName string, w http.ResponseWriter, r
|
||||
}
|
||||
|
||||
// TODO: Rename renderTemplate to RenderTemplate instead of using this hack to avoid breaking things
|
||||
var RenderTemplate = renderTemplate3
|
||||
var RenderTemplate = renderTemplate3
|
||||
|
@ -7,11 +7,12 @@ import (
|
||||
"strings"
|
||||
|
||||
c "github.com/Azareal/Gosora/common"
|
||||
"github.com/Azareal/Gosora/common/phrases"
|
||||
p "github.com/Azareal/Gosora/common/phrases"
|
||||
)
|
||||
|
||||
func Convos(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
||||
accountEditHead("convos", w, r, &user, header)
|
||||
header.AddNotice("convo_dev")
|
||||
ccount := c.Convos.GetUserCount(user.ID)
|
||||
page, _ := strconv.Atoi(r.FormValue("page"))
|
||||
offset, page, lastPage := c.PageOffset(ccount, page, c.Config.ItemsPerPage)
|
||||
@ -30,9 +31,11 @@ func Convos(w http.ResponseWriter, r *http.Request, user c.User, header *c.Heade
|
||||
|
||||
func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header, scid string) c.RouteError {
|
||||
accountEditHead("convo", w, r, &user, header)
|
||||
header.AddSheet(header.Theme.Name + "/convo.css")
|
||||
header.AddNotice("convo_dev")
|
||||
cid, err := strconv.Atoi(scid)
|
||||
if err != nil {
|
||||
return c.LocalError(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
||||
return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
||||
}
|
||||
|
||||
convo, err := c.Convos.Get(cid)
|
||||
@ -50,7 +53,7 @@ func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header
|
||||
offset, page, lastPage := c.PageOffset(pcount, page, c.Config.ItemsPerPage)
|
||||
pageList := c.Paginate(page, lastPage, 5)
|
||||
|
||||
posts, err := convo.Posts(offset)
|
||||
posts, err := convo.Posts(offset, c.Config.ItemsPerPage)
|
||||
// TODO: Report a better error for no posts
|
||||
if err == sql.ErrNoRows {
|
||||
return c.NotFound(w, r, header)
|
||||
@ -58,12 +61,23 @@ func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
pi := c.Account{header, "dashboard", "convo", c.ConvoViewPage{header, posts, c.Paginator{pageList, page, lastPage}}}
|
||||
pitems := make([]c.ConvoViewRow, len(posts))
|
||||
for i, post := range posts {
|
||||
user, err := c.Users.Get(post.CreatedBy)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
pitems[i] = c.ConvoViewRow{post, user, "", "4"}
|
||||
}
|
||||
canModify := user.ID == convo.CreatedBy || user.IsSuperMod
|
||||
|
||||
pi := c.Account{header, "dashboard", "convo", c.ConvoViewPage{header, convo, pitems, canModify, c.Paginator{pageList, page, lastPage}}}
|
||||
return renderTemplate("account", w, r, header, pi)
|
||||
}
|
||||
|
||||
func ConvosCreate(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
||||
accountEditHead("create_convo", w, r, &user, header)
|
||||
header.AddNotice("convo_dev")
|
||||
recpName := ""
|
||||
pi := c.Account{header, "dashboard", "create_convo", c.ConvoCreatePage{header, recpName}}
|
||||
return renderTemplate("account", w, r, header, pi)
|
||||
@ -103,13 +117,6 @@ func ConvosCreateSubmit(w http.ResponseWriter, r *http.Request, user c.User) c.R
|
||||
return nil
|
||||
}
|
||||
|
||||
/*type ConversationPost struct {
|
||||
ID int
|
||||
CID int
|
||||
Body string
|
||||
Post string // aes, ''
|
||||
}*/
|
||||
|
||||
func ConvosDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.User, scid string) c.RouteError {
|
||||
_, ferr := c.SimpleUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
@ -117,7 +124,7 @@ func ConvosDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.User, sci
|
||||
}
|
||||
cid, err := strconv.Atoi(scid)
|
||||
if err != nil {
|
||||
return c.LocalError(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
||||
return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
||||
}
|
||||
|
||||
err = c.Convos.Delete(cid)
|
||||
@ -138,11 +145,61 @@ func ConvosCreateReplySubmit(w http.ResponseWriter, r *http.Request, user c.User
|
||||
return nil
|
||||
}
|
||||
|
||||
func ConvosDeleteReplySubmit(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
|
||||
func ConvosDeleteReplySubmit(w http.ResponseWriter, r *http.Request, user c.User, scpid string) c.RouteError {
|
||||
_, ferr := c.SimpleUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
cpid, err := strconv.Atoi(scpid)
|
||||
if err != nil {
|
||||
return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
||||
}
|
||||
|
||||
post := &c.ConversationPost{ID: cpid}
|
||||
err = post.Fetch()
|
||||
if err == sql.ErrNoRows {
|
||||
return c.NotFound(w, r, nil)
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
convo, err := c.Convos.Get(post.CID)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.NotFound(w, r, nil)
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
pcount := convo.PostsCount()
|
||||
if pcount == 0 {
|
||||
return c.NotFound(w, r, nil)
|
||||
}
|
||||
|
||||
posts, err := convo.Posts(0, c.Config.ItemsPerPage)
|
||||
// TODO: Report a better error for no posts
|
||||
if err == sql.ErrNoRows {
|
||||
return c.NotFound(w, r, nil)
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
if post.ID == posts[0].ID {
|
||||
err = c.Convos.Delete(convo.ID)
|
||||
} else {
|
||||
err = post.Delete()
|
||||
}
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/user/convo/"+strconv.Itoa(post.CID), http.StatusSeeOther)
|
||||
return nil
|
||||
}
|
||||
|
||||
func ConvosEditReplySubmit(w http.ResponseWriter, r *http.Request, user c.User, scpid string) c.RouteError {
|
||||
_, ferr := c.SimpleUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
http.Redirect(w, r, "/user/convo/id", http.StatusSeeOther)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ func ReportSubmit(w http.ResponseWriter, r *http.Request, user c.User, sitemID s
|
||||
|
||||
// TODO: Localise these titles and bodies
|
||||
var title, content string
|
||||
if itemType == "reply" {
|
||||
switch itemType {
|
||||
case "reply":
|
||||
reply, err := c.Rstore.Get(itemID)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.LocalError("We were unable to find the reported post", w, r, user)
|
||||
@ -41,7 +42,7 @@ func ReportSubmit(w http.ResponseWriter, r *http.Request, user c.User, sitemID s
|
||||
|
||||
title = "Reply: " + topic.Title
|
||||
content = reply.Content + "\n\nOriginal Post: #rid-" + strconv.Itoa(itemID)
|
||||
} else if itemType == "user-reply" {
|
||||
case "user-reply":
|
||||
userReply, err := c.Prstore.Get(itemID)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.LocalError("We weren't able to find the reported post", w, r, user)
|
||||
@ -57,7 +58,7 @@ func ReportSubmit(w http.ResponseWriter, r *http.Request, user c.User, sitemID s
|
||||
}
|
||||
title = "Profile: " + profileOwner.Name
|
||||
content = userReply.Content + "\n\nOriginal Post: @" + strconv.Itoa(userReply.ParentID)
|
||||
} else if itemType == "topic" {
|
||||
case "topic":
|
||||
topic, err := c.Topics.Get(itemID)
|
||||
if err == sql.ErrNoRows {
|
||||
return c.NotFound(w, r, nil)
|
||||
@ -66,7 +67,27 @@ func ReportSubmit(w http.ResponseWriter, r *http.Request, user c.User, sitemID s
|
||||
}
|
||||
title = "Topic: " + topic.Title
|
||||
content = topic.Content + "\n\nOriginal Post: #tid-" + strconv.Itoa(itemID)
|
||||
} else {
|
||||
case "convo-reply":
|
||||
post := &c.ConversationPost{ID: itemID}
|
||||
err := post.Fetch()
|
||||
if err == sql.ErrNoRows {
|
||||
return c.NotFound(w, r, nil)
|
||||
} else if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
post, err = c.ConvoPostProcess.OnLoad(post)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
user, err := c.Users.Get(post.CreatedBy)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
title = "Convo Post: " + user.Name
|
||||
content = post.Body + "\n\nOriginal Post: #cpid-" + strconv.Itoa(itemID)
|
||||
default:
|
||||
_, hasHook := headerLite.Hooks.VhookNeedHook("report_preassign", &itemID, &itemType)
|
||||
if hasHook {
|
||||
return nil
|
||||
|
8
schema/mssql/query_conversations.sql
Normal file
8
schema/mssql/query_conversations.sql
Normal file
@ -0,0 +1,8 @@
|
||||
CREATE TABLE [conversations] (
|
||||
[cid] int not null IDENTITY,
|
||||
[createdBy] int not null,
|
||||
[createdAt] datetime not null,
|
||||
[lastReplyAt] datetime not null,
|
||||
[lastReplyBy] int not null,
|
||||
primary key([cid])
|
||||
);
|
4
schema/mssql/query_conversations_participants.sql
Normal file
4
schema/mssql/query_conversations_participants.sql
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE TABLE [conversations_participants] (
|
||||
[uid] int not null,
|
||||
[cid] int not null
|
||||
);
|
8
schema/mssql/query_conversations_posts.sql
Normal file
8
schema/mssql/query_conversations_posts.sql
Normal file
@ -0,0 +1,8 @@
|
||||
CREATE TABLE [conversations_posts] (
|
||||
[pid] int not null IDENTITY,
|
||||
[cid] int not null,
|
||||
[createdBy] int not null,
|
||||
[body] nvarchar (50) not null,
|
||||
[post] nvarchar (50) DEFAULT '' not null,
|
||||
primary key([pid])
|
||||
);
|
8
schema/mysql/query_conversations.sql
Normal file
8
schema/mysql/query_conversations.sql
Normal file
@ -0,0 +1,8 @@
|
||||
CREATE TABLE `conversations` (
|
||||
`cid` int not null AUTO_INCREMENT,
|
||||
`createdBy` int not null,
|
||||
`createdAt` datetime not null,
|
||||
`lastReplyAt` datetime not null,
|
||||
`lastReplyBy` int not null,
|
||||
primary key(`cid`)
|
||||
);
|
4
schema/mysql/query_conversations_participants.sql
Normal file
4
schema/mysql/query_conversations_participants.sql
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE TABLE `conversations_participants` (
|
||||
`uid` int not null,
|
||||
`cid` int not null
|
||||
);
|
8
schema/mysql/query_conversations_posts.sql
Normal file
8
schema/mysql/query_conversations_posts.sql
Normal file
@ -0,0 +1,8 @@
|
||||
CREATE TABLE `conversations_posts` (
|
||||
`pid` int not null AUTO_INCREMENT,
|
||||
`cid` int not null,
|
||||
`createdBy` int not null,
|
||||
`body` varchar(50) not null,
|
||||
`post` varchar(50) DEFAULT '' not null,
|
||||
primary key(`pid`)
|
||||
);
|
8
schema/pgsql/query_conversations.sql
Normal file
8
schema/pgsql/query_conversations.sql
Normal file
@ -0,0 +1,8 @@
|
||||
CREATE TABLE "conversations" (
|
||||
`cid` serial not null,
|
||||
`createdBy` int not null,
|
||||
`createdAt` timestamp not null,
|
||||
`lastReplyAt` timestamp not null,
|
||||
`lastReplyBy` int not null,
|
||||
primary key(`cid`)
|
||||
);
|
4
schema/pgsql/query_conversations_participants.sql
Normal file
4
schema/pgsql/query_conversations_participants.sql
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE TABLE "conversations_participants" (
|
||||
`uid` int not null,
|
||||
`cid` int not null
|
||||
);
|
8
schema/pgsql/query_conversations_posts.sql
Normal file
8
schema/pgsql/query_conversations_posts.sql
Normal file
@ -0,0 +1,8 @@
|
||||
CREATE TABLE "conversations_posts" (
|
||||
`pid` serial not null,
|
||||
`cid` int not null,
|
||||
`createdBy` int not null,
|
||||
`body` varchar (50) not null,
|
||||
`post` varchar (50) DEFAULT '' not null,
|
||||
primary key(`pid`)
|
||||
);
|
@ -9,6 +9,8 @@
|
||||
<div class="rowitem passive"><a href="/user/edit/email/">{{lang "account_menu_email"}}</a></div>
|
||||
<!--<div class="rowitem passive"><a href="/user/edit/notifications/">{{lang "account_menu_notifications"}}</a> <span class="account_soon">Coming Soon</span></div>-->
|
||||
<div class="rowitem passive"><a href="/user/edit/logins/">{{lang "account_menu_logins"}}</a></div>
|
||||
<!--<div class="rowitem passive"><a href="/user/edit/penalties/">{{lang "account_menu_penalties"}}</a></div>-->
|
||||
<div class="rowitem passive"><a href="/user/convos/">{{lang "account_menu_messages"}}</a></div>
|
||||
{{/** TODO: Add an alerts page with pagination to go through alerts which either don't fit in the alerts drop-down or which have already been dismissed. Bear in mind though that dismissed alerts older than two weeks might be purged to save space and to speed up the database **/}}
|
||||
</div>
|
||||
</nav>
|
||||
|
@ -3,8 +3,4 @@
|
||||
<h1>{{lang "convo_head"}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
{{range .Posts}}
|
||||
<div class="colstack_item">
|
||||
<div class="rowitem">{{.Body}}</div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="colstack_item hash_hide">{{template "convo_row.html" . }}</div>
|
21
templates/convo_row.html
Normal file
21
templates/convo_row.html
Normal file
@ -0,0 +1,21 @@
|
||||
{{/** TODO: Temporary hack until we find a more granular way of doing this. Perhaps, a custom include function? **/}}
|
||||
{{if .Header.Theme.BgAvatars}}
|
||||
{{range .Posts}}
|
||||
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent simple {{.ClassName}}" style="background-image:url({{.User.Avatar}}),url(/s/post-avatar-bg.jpg);background-position:0px {{if le .ContentLines 5}}-1{{end}}0px;">
|
||||
<span class="editable_block user_content simple">{{.Body}}</span>
|
||||
<span class="controls">
|
||||
<a href="{{.User.Link}}" class="real_username username">{{.User.Name}}</a>
|
||||
|
||||
{{if $.CanModify}}<a href="/user/convo/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||
|
||||
<a href="/user/convo/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>{{end}}
|
||||
|
||||
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=convo-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||
|
||||
{{if .User.Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.User.Tag}}</a>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{template "convo_row_alt.html" . }}
|
||||
{{end}}
|
26
templates/convo_row_alt.html
Normal file
26
templates/convo_row_alt.html
Normal file
@ -0,0 +1,26 @@
|
||||
{{range .Posts}}
|
||||
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent comment {{.ClassName}}">
|
||||
<div class="topRow">
|
||||
<div class="userbit">
|
||||
<img src="{{.User.MicroAvatar}}" alt="Avatar" title="{{.User.Name}}'s Avatar" aria-hidden="true" />
|
||||
<span class="nameAndTitle">
|
||||
<a href="{{.User.Link}}" class="real_username username">{{.User.Name}}</a>
|
||||
{{if .User.Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.User.Tag}}</a>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<span class="controls">
|
||||
{{if $.CanModify}}
|
||||
<a href="/user/convo/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||
|
||||
<a href="/user/convo/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>
|
||||
{{end}}
|
||||
|
||||
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=convo-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="content_column">
|
||||
<span class="editable_block user_content">{{.Body}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="after_comment"></div>
|
||||
{{end}}
|
@ -1,7 +1,7 @@
|
||||
<div class="colstack_item colstack_head rowhead">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "convos_head"}}</h1>
|
||||
<h2>Create Convo</h2>
|
||||
<h2><a href="/user/convos/create/">Create Convo</a></h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="colstack_item">
|
||||
|
@ -3,16 +3,16 @@
|
||||
<head>
|
||||
<title>{{.Title}} | {{.Header.Site.Name}}</title>
|
||||
{{range .Header.Stylesheets}}
|
||||
<link href="/static/{{.}}" rel="stylesheet" type="text/css">{{end}}
|
||||
<link href="/s/{{.}}" rel="stylesheet" type="text/css">{{end}}
|
||||
{{range .Header.PreScriptsAsync}}
|
||||
<script async type="text/javascript" src="/static/{{.}}"></script>{{end}}
|
||||
<script async type="text/javascript" src="/s/{{.}}"></script>{{end}}
|
||||
<meta property="x-loggedin" content="{{.CurrentUser.Loggedin}}" />
|
||||
<script type="text/javascript" src="/static/init.js?i=8"></script>
|
||||
<script type="text/javascript" src="/s/init.js?i=9"></script>
|
||||
{{range .Header.ScriptsAsync}}
|
||||
<script async type="text/javascript" src="/static/{{.}}"></script>{{end}}
|
||||
<script type="text/javascript" src="/static/jquery-3.1.1.min.js"></script>
|
||||
<script async type="text/javascript" src="/s/{{.}}"></script>{{end}}
|
||||
<script type="text/javascript" src="/s/jquery-3.1.1.min.js"></script>
|
||||
{{range .Header.Scripts}}
|
||||
<script type="text/javascript" src="/static/{{.}}"></script>{{end}}
|
||||
<script type="text/javascript" src="/s/{{.}}"></script>{{end}}
|
||||
<meta name="viewport" content="width=device-width,initial-scale = 1.0, maximum-scale=1.0,user-scalable=no" />
|
||||
{{if .Header.MetaDesc}}<meta name="description" content="{{.Header.MetaDesc}}" />{{end}}
|
||||
{{/** TODO: Have page / forum / topic level tags and descriptions below as-well **/}}
|
||||
|
@ -3,10 +3,10 @@
|
||||
</div>
|
||||
<div id="panel_primary_themes" class="colstack_item panel_themes complex_rowlist">
|
||||
{{range .PrimaryThemes}}
|
||||
<div class="theme_row rowitem editable_parent"{{if .FullImage}} style="background-image: url('/static/{{.FullImage}}');background-position: center;background-size: 50%;background-repeat: no-repeat;"{{end}}>
|
||||
<span style="float: left;">
|
||||
<a href="/panel/themes/{{.Name}}" class="editable_block" style="font-size: 17px;">{{.FriendlyName}}</a><br />
|
||||
<small class="panel_theme_author" style="margin-left: 2px;">{{lang "panel_themes_author_prefix"}}<a href="//{{.URL}}">{{.Creator}}</a></small>
|
||||
<div class="theme_row rowitem editable_parent"{{if .FullImage}} style="background-image:url('/s/{{.FullImage}}');background-position:center;background-size:50%;background-repeat:no-repeat;"{{end}}>
|
||||
<span style="float:left;">
|
||||
<a href="/panel/themes/{{.Name}}" class="editable_block" style="font-size:17px;">{{.FriendlyName}}</a><br />
|
||||
<small class="panel_theme_author" style="margin-left:2px;">{{lang "panel_themes_author_prefix"}}<a href="//{{.URL}}">{{.Creator}}</a></small>
|
||||
</span>
|
||||
<span class="panel_floater">
|
||||
{{if .MobileFriendly}}<span class="panel_tag panel_theme_mobile" title="{{lang "panel_themes_mobile_friendly_tooltip"}}" aria-label="{{lang "panel_themes_mobile_friendly_aria"}}">📱</span>{{end}}
|
||||
@ -22,10 +22,10 @@
|
||||
</div>
|
||||
<div id="panel_variant_themes" class="colstack_item panel_themes">
|
||||
{{range .VariantThemes}}
|
||||
<div class="theme_row rowitem editable_parent"{{if .FullImage}} style="background-image: url('/static/{{.FullImage}}');background-position: center;background-size: 50%;background-repeat: no-repeat;"{{end}}>
|
||||
<div class="theme_row rowitem editable_parent"{{if .FullImage}} style="background-image:url('/s/{{.FullImage}}');background-position:center;background-size:50%;background-repeat:no-repeat;"{{end}}>
|
||||
<span style="float: left;">
|
||||
<a href="/panel/themes/{{.Name}}" class="editable_block" style="font-size: 17px;">{{.FriendlyName}}</a><br />
|
||||
<small class="panel_theme_author" style="margin-left: 2px;">{{lang "panel_themes_author_prefix"}}<a href="//{{.URL}}">{{.Creator}}</a></small>
|
||||
<a href="/panel/themes/{{.Name}}" class="editable_block" style="font-size:17px;">{{.FriendlyName}}</a><br />
|
||||
<small class="panel_theme_author" style="margin-left:2px;">{{lang "panel_themes_author_prefix"}}<a href="//{{.URL}}">{{.Creator}}</a></small>
|
||||
</span>
|
||||
<span class="panel_floater">
|
||||
{{if .MobileFriendly}}<span class="panel_tag panel_theme_mobile" title="{{lang "panel_themes_mobile_friendly_tooltip"}}" aria-label="{{lang "panel_themes_mobile_friendly_aria"}}">📱</span>{{end}}
|
||||
|
@ -27,9 +27,9 @@
|
||||
{{if not .CurrentUser.Loggedin}}<div class="rowitem passive">
|
||||
<a class="profile_menu_item">{{lang "profile_login_for_options"}}</a>
|
||||
</div>{{else}}
|
||||
<!--<div class="rowitem passive">
|
||||
<div class="rowitem passive">
|
||||
<a href="/user/convos/create/" class="profile_menu_item">{{lang "profile_send_message"}}</a>
|
||||
</div>-->
|
||||
</div>
|
||||
<!--<div class="rowitem passive">
|
||||
<a class="profile_menu_item">{{lang "profile_add_friend"}}</a>
|
||||
</div>-->
|
||||
|
@ -1,21 +1,21 @@
|
||||
{{/** TODO: Temporary hack until we find a more granular way of doing this. Perhaps, a custom include function? **/}}
|
||||
{{if .Header.Theme.BgAvatars}}
|
||||
{{range .ItemList}}
|
||||
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent simple {{.ClassName}}" style="background-image:url({{.Avatar}}),url(/static/post-avatar-bg.jpg);background-position:0px {{if le .ContentLines 5}}-1{{end}}0px;">
|
||||
<span class="editable_block user_content simple">{{.ContentHtml}}</span>
|
||||
<span class="controls">
|
||||
<a href="{{.UserLink}}" class="real_username username">{{.CreatedByName}}</a>
|
||||
{{range .ItemList}}
|
||||
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent simple {{.ClassName}}" style="background-image:url({{.Avatar}}),url(/s/post-avatar-bg.jpg);background-position:0px {{if le .ContentLines 5}}-1{{end}}0px;">
|
||||
<span class="editable_block user_content simple">{{.ContentHtml}}</span>
|
||||
<span class="controls">
|
||||
<a href="{{.UserLink}}" class="real_username username">{{.CreatedByName}}</a>
|
||||
|
||||
{{if $.CurrentUser.IsMod}}<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||
{{if $.CurrentUser.IsMod}}<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||
|
||||
<a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>{{end}}
|
||||
<a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>{{end}}
|
||||
|
||||
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||
|
||||
{{if .Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.Tag}}</a>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.Tag}}</a>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{template "profile_comments_row_alt.html" . }}
|
||||
{{end}}
|
@ -1,24 +1,24 @@
|
||||
{{range .ItemList}}
|
||||
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent comment {{.ClassName}}">
|
||||
<div class="topRow">
|
||||
<div class="userbit">
|
||||
<img src="{{.MicroAvatar}}" alt="Avatar" title="{{.CreatedByName}}'s Avatar" aria-hidden="true" />
|
||||
<span class="nameAndTitle">
|
||||
<a href="{{.UserLink}}" class="real_username username">{{.CreatedByName}}</a>
|
||||
{{if .Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.Tag}}</a>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<span class="controls">
|
||||
{{if $.CurrentUser.IsMod}}
|
||||
<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||
<a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>
|
||||
{{end}}
|
||||
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent comment {{.ClassName}}">
|
||||
<div class="topRow">
|
||||
<div class="userbit">
|
||||
<img src="{{.MicroAvatar}}" alt="Avatar" title="{{.CreatedByName}}'s Avatar" aria-hidden="true" />
|
||||
<span class="nameAndTitle">
|
||||
<a href="{{.UserLink}}" class="real_username username">{{.CreatedByName}}</a>
|
||||
{{if .Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.Tag}}</a>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="content_column">
|
||||
<span class="editable_block user_content">{{.ContentHtml}}</span>
|
||||
</div>
|
||||
<span class="controls">
|
||||
{{if $.CurrentUser.IsMod}}
|
||||
<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||
<a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>
|
||||
{{end}}
|
||||
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="after_comment"></div>
|
||||
<div class="content_column">
|
||||
<span class="editable_block user_content">{{.ContentHtml}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="after_comment"></div>
|
||||
{{end}}
|
@ -31,7 +31,7 @@
|
||||
{{end}}
|
||||
|
||||
<article {{scope "opening_post"}} itemscope itemtype="http://schema.org/CreativeWork" class="rowblock post_container top_post" aria-label="{{lang "topic.opening_post_aria"}}">
|
||||
<div class="rowitem passive editable_parent post_item {{.Topic.ClassName}}" style="background-image: url({{.Topic.Avatar}}), url(/static/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||
<div class="rowitem passive editable_parent post_item {{.Topic.ClassName}}" style="background-image:url({{.Topic.Avatar}}), url(/s/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position:0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||
<div class="hide_on_edit topic_content user_content" itemprop="text">{{.Topic.ContentHTML}}</div>
|
||||
{{if .CurrentUser.Loggedin}}<textarea name="topic_content" class="show_on_edit topic_content_input edit_source">{{.Topic.Content}}</textarea>{{end}}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="rowblock topic_reply_container">
|
||||
<div class="userinfo" aria-label="{{lang "topic.your_information"}}">
|
||||
<div class="avatar_item" style="background-image:url({{.CurrentUser.Avatar}}),url(/static/white-dot.jpg);background-position:0px -10px;"> </div>
|
||||
<div class="avatar_item" style="background-image:url({{.CurrentUser.Avatar}}),url(/s/white-dot.jpg);background-position:0px -10px;"> </div>
|
||||
<div class="user_meta">
|
||||
<a href="{{.CurrentUser.Link}}" class="the_name" rel="author">{{.CurrentUser.Name}}</a>
|
||||
{{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}}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="userinfo" aria-label="{{lang "topic.userinfo_aria"}}">
|
||||
<div class="avatar_item" style="background-image: url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
<div class="avatar_item" style="background-image:url({{.Avatar}}), url(/s/white-dot.jpg);background-position:0px -10px;"> </div>
|
||||
<div class="user_meta">
|
||||
<a href="{{.UserLink}}" class="the_name" rel="author">{{.CreatedByName}}</a>
|
||||
{{if .Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.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 .Level}}</div><div class="tag_post"></div></div>{{end}}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<article class="rowblock post_container poll" aria-level="{{lang "topic.poll_aria"}}">
|
||||
<div class="rowitem passive editable_parent post_item poll_item {{.Topic.ClassName}}" style="background-image: url({{.Topic.Avatar}}), url(/static/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||
<div class="rowitem passive editable_parent post_item poll_item {{.Topic.ClassName}}" style="background-image:url({{.Topic.Avatar}}), url(/s/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position:0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||
<div class="topic_content user_content">
|
||||
{{range .Poll.QuickOptions}}
|
||||
<div class="poll_option">
|
||||
|
@ -5,7 +5,7 @@
|
||||
<span itemprop="text">{{.ActionType}}</span>
|
||||
</article>
|
||||
{{else}}
|
||||
<article {{scope "post"}} id="post-{{.ID}}" itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item {{.ClassName}}" style="background-image: url({{.Avatar}}), url(/static/{{$.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||
<article {{scope "post"}} id="post-{{.ID}}" itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item {{.ClassName}}" style="background-image:url({{.Avatar}}), url(/s/{{$.Header.Theme.Name}}/post-avatar-bg.jpg);background-position:0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||
{{/** TODO: We might end up with <br>s in the inline editor, fix this **/}}
|
||||
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
|
||||
{{if $.CurrentUser.Loggedin}}<div class="auto_hide edit_source">{{.Content}}</div>{{end}}
|
||||
|
0
themes/cosora/public/convo.css
Normal file
0
themes/cosora/public/convo.css
Normal file
@ -17,7 +17,7 @@
|
||||
//console.log("af")
|
||||
let loggedIn = document.head.querySelector("[property='x-loggedin']").content;
|
||||
if(loggedIn) {
|
||||
if(navigator.userAgent.indexOf("Firefox") != -1) $.trumbowyg.svgPath = "/static/trumbowyg/ui/icons.svg";
|
||||
if(navigator.userAgent.indexOf("Firefox") != -1) $.trumbowyg.svgPath = "/s/trumbowyg/ui/icons.svg";
|
||||
|
||||
// Is there we way we can append instead? Maybe, an editor plugin?
|
||||
attachItemCallback = function(attachItem) {
|
||||
|
30
themes/nox/public/convo.css
Normal file
30
themes/nox/public/convo.css
Normal file
@ -0,0 +1,30 @@
|
||||
.rowitem .topRow {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
.rowitem .userbit {
|
||||
display: flex;
|
||||
}
|
||||
.rowitem .topRow .nameAndTitle {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 8px;
|
||||
}
|
||||
.nameAndTitle .real_username {
|
||||
font-size: 17px;
|
||||
line-height: 16px;
|
||||
}
|
||||
.userbit img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 24px;
|
||||
}
|
||||
.controls {
|
||||
margin-left: auto;
|
||||
}
|
||||
.controls a {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.content_column {
|
||||
margin-top: 5px;
|
||||
}
|
@ -351,6 +351,10 @@ h1, h2, h3, h4, h5 {
|
||||
.rowhead h1, .opthead h1, .colstack_head h1 {
|
||||
font-size: 21px;
|
||||
}
|
||||
.rowhead h1 + h2, .opthead h1 + h2, .colstack_right .colstack_head .rowitem h1 + h2 {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.sidebar .rowhead {
|
||||
margin-left: 18px;
|
||||
margin-top: 4px;
|
||||
|
@ -16,8 +16,6 @@
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 32px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.nameRow {
|
||||
display: flex;
|
||||
|
0
themes/shadow/public/convo.css
Normal file
0
themes/shadow/public/convo.css
Normal file
0
themes/tempra_simple/public/convo.css
Normal file
0
themes/tempra_simple/public/convo.css
Normal file
Loading…
Reference in New Issue
Block a user