Renamed setting.go to settings.go
Added the BypassGet method to SettingMap and refactored the Control Panel to use it. Refactored the query builder. More work on Cosora.
This commit is contained in:
parent
b42181c0c6
commit
8d0479f4b2
|
@ -56,7 +56,6 @@ type ForumCache interface {
|
|||
type MemoryForumStore struct {
|
||||
forums sync.Map // map[int]*Forum
|
||||
forumView atomic.Value // []*Forum
|
||||
//fids []int
|
||||
|
||||
get *sql.Stmt
|
||||
getAll *sql.Stmt
|
||||
|
|
|
@ -12,7 +12,7 @@ type HeaderVars struct {
|
|||
Stylesheets []string
|
||||
Widgets PageWidgets
|
||||
Site *site
|
||||
Settings map[string]interface{}
|
||||
Settings SettingMap
|
||||
Themes map[string]Theme // TODO: Use a slice containing every theme instead of the main map for speed
|
||||
ThemeName string
|
||||
//TemplateName string // TODO: Use this to move template calls to the router rather than duplicating them over and over and over?
|
||||
|
|
|
@ -9,10 +9,15 @@ import (
|
|||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var SettingBox atomic.Value // An atomic value pointing to a SettingBox
|
||||
|
||||
// SettingMap is a map type specifically for holding the various settings admins set to toggle features on and off or to otherwise alter Gosora's behaviour from the Control Panel
|
||||
type SettingMap map[string]interface{}
|
||||
|
||||
var SettingBox atomic.Value // An atomic value pointing to a SettingBox
|
||||
type SettingStore interface {
|
||||
ParseSetting(sname string, scontent string, stype string, sconstraint string) string
|
||||
BypassGet(name string) (*Setting, error)
|
||||
}
|
||||
|
||||
type OptionLabel struct {
|
||||
Label string
|
||||
|
@ -28,7 +33,8 @@ type Setting struct {
|
|||
}
|
||||
|
||||
type SettingStmts struct {
|
||||
getFull *sql.Stmt
|
||||
getAll *sql.Stmt
|
||||
get *sql.Stmt
|
||||
}
|
||||
|
||||
var settingStmts SettingStmts
|
||||
|
@ -37,14 +43,15 @@ func init() {
|
|||
SettingBox.Store(SettingMap(make(map[string]interface{})))
|
||||
DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||
settingStmts = SettingStmts{
|
||||
getFull: acc.Select("settings").Columns("name, content, type, constraints").Prepare(),
|
||||
getAll: acc.Select("settings").Columns("name, content, type, constraints").Prepare(),
|
||||
get: acc.Select("settings").Columns("content, type, constraints").Where("name = ?").Prepare(),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
}
|
||||
|
||||
func LoadSettings() error {
|
||||
rows, err := settingStmts.getFull.Query()
|
||||
rows, err := settingStmts.getAll.Query()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -113,3 +120,9 @@ func (sBox SettingMap) ParseSetting(sname string, scontent string, stype string,
|
|||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (sBox SettingMap) BypassGet(name string) (*Setting, error) {
|
||||
setting := &Setting{Name: name}
|
||||
err := settingStmts.get.QueryRow(name).Scan(&setting.Content, &setting.Type, &setting.Constraint)
|
||||
return setting, err
|
||||
}
|
16
gen_mssql.go
16
gen_mssql.go
|
@ -11,8 +11,6 @@ import "./common"
|
|||
type Stmts struct {
|
||||
getPassword *sql.Stmt
|
||||
getSettings *sql.Stmt
|
||||
getSetting *sql.Stmt
|
||||
getFullSetting *sql.Stmt
|
||||
isPluginActive *sql.Stmt
|
||||
getUsersOffset *sql.Stmt
|
||||
isThemeDefault *sql.Stmt
|
||||
|
@ -99,20 +97,6 @@ func _gen_mssql() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getSetting statement.")
|
||||
stmts.getSetting, err = db.Prepare("SELECT [content],[type] FROM [settings] WHERE [name] = ?1")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [content],[type] FROM [settings] WHERE [name] = ?1")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getFullSetting statement.")
|
||||
stmts.getFullSetting, err = db.Prepare("SELECT [name],[type],[constraints] FROM [settings] WHERE [name] = ?1")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [name],[type],[constraints] FROM [settings] WHERE [name] = ?1")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing isPluginActive statement.")
|
||||
stmts.isPluginActive, err = db.Prepare("SELECT [active] FROM [plugins] WHERE [uname] = ?1")
|
||||
if err != nil {
|
||||
|
|
14
gen_mysql.go
14
gen_mysql.go
|
@ -13,8 +13,6 @@ import "./common"
|
|||
type Stmts struct {
|
||||
getPassword *sql.Stmt
|
||||
getSettings *sql.Stmt
|
||||
getSetting *sql.Stmt
|
||||
getFullSetting *sql.Stmt
|
||||
isPluginActive *sql.Stmt
|
||||
getUsersOffset *sql.Stmt
|
||||
isThemeDefault *sql.Stmt
|
||||
|
@ -99,18 +97,6 @@ func _gen_mysql() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getSetting statement.")
|
||||
stmts.getSetting, err = db.Prepare("SELECT `content`,`type` FROM `settings` WHERE `name` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getFullSetting statement.")
|
||||
stmts.getFullSetting, err = db.Prepare("SELECT `name`,`type`,`constraints` FROM `settings` WHERE `name` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing isPluginActive statement.")
|
||||
stmts.isPluginActive, err = db.Prepare("SELECT `active` FROM `plugins` WHERE `uname` = ?")
|
||||
if err != nil {
|
||||
|
|
|
@ -455,7 +455,6 @@ func routePanelSettings(w http.ResponseWriter, r *http.Request, user common.User
|
|||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
//log.Print("headerVars.Settings",headerVars.Settings)
|
||||
var settingList = make(map[string]interface{})
|
||||
rows, err := stmts.getSettings.Query()
|
||||
if err != nil {
|
||||
|
@ -515,9 +514,8 @@ func routePanelSetting(w http.ResponseWriter, r *http.Request, user common.User,
|
|||
if !user.Perms.EditSettings {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
setting := common.Setting{sname, "", "", ""}
|
||||
|
||||
err := stmts.getSetting.QueryRow(setting.Name).Scan(&setting.Content, &setting.Type)
|
||||
setting, err := headerVars.Settings.BypassGet(sname)
|
||||
if err == ErrNoRows {
|
||||
return common.LocalError("The setting you want to edit doesn't exist.", w, r, user)
|
||||
} else if err != nil {
|
||||
|
@ -532,8 +530,7 @@ func routePanelSetting(w http.ResponseWriter, r *http.Request, user common.User,
|
|||
return common.LocalError("The value of this setting couldn't be converted to an integer", w, r, user)
|
||||
}
|
||||
|
||||
labels := strings.Split(llist, ",")
|
||||
for index, label := range labels {
|
||||
for index, label := range strings.Split(llist, ",") {
|
||||
itemList = append(itemList, common.OptionLabel{
|
||||
Label: label,
|
||||
Value: index + 1,
|
||||
|
@ -564,17 +561,15 @@ func routePanelSettingEdit(w http.ResponseWriter, r *http.Request, user common.U
|
|||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
var stype, sconstraints string
|
||||
scontent := r.PostFormValue("setting-value")
|
||||
|
||||
err := stmts.getFullSetting.QueryRow(sname).Scan(&sname, &stype, &sconstraints)
|
||||
setting, err := headerLite.Settings.BypassGet(sname)
|
||||
if err == ErrNoRows {
|
||||
return common.LocalError("The setting you want to edit doesn't exist.", w, r, user)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
if stype == "bool" {
|
||||
if setting.Type == "bool" {
|
||||
if scontent == "on" || scontent == "1" {
|
||||
scontent = "1"
|
||||
} else {
|
||||
|
@ -588,10 +583,11 @@ func routePanelSettingEdit(w http.ResponseWriter, r *http.Request, user common.U
|
|||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
errmsg := headerLite.Settings.ParseSetting(sname, scontent, stype, sconstraints)
|
||||
errmsg := headerLite.Settings.ParseSetting(sname, scontent, setting.Type, setting.Constraint)
|
||||
if errmsg != "" {
|
||||
return common.LocalError(errmsg, w, r, user)
|
||||
}
|
||||
// TODO: Do a reload instead?
|
||||
common.SettingBox.Store(headerLite.Settings)
|
||||
|
||||
http.Redirect(w, r, "/panel/settings/", http.StatusSeeOther)
|
||||
|
@ -649,6 +645,7 @@ func routePanelWordFiltersCreate(w http.ResponseWriter, r *http.Request, user co
|
|||
}
|
||||
|
||||
common.AddWordFilter(int(lastID), find, replacement)
|
||||
|
||||
if !isJs {
|
||||
http.Redirect(w, r, "/panel/settings/word-filters/", http.StatusSeeOther)
|
||||
} else {
|
||||
|
|
|
@ -110,100 +110,71 @@ func (build *builder) Purge(table string) (stmt *sql.Stmt, err error) {
|
|||
return build.prepare(build.adapter.Purge("_builder", table))
|
||||
}
|
||||
|
||||
func (build *builder) prepareTx(tx *sql.Tx, res string, err error) (*sql.Stmt, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
}
|
||||
|
||||
// These ones support transactions
|
||||
func (build *builder) SimpleSelectTx(tx *sql.Tx, table string, columns string, where string, orderby string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleSelect("_builder", table, columns, where, orderby, limit)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleCountTx(tx *sql.Tx, table string, where string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleCount("_builder", table, where, limit)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleLeftJoinTx(tx *sql.Tx, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleLeftJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInnerJoinTx(tx *sql.Tx, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInnerJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) CreateTableTx(tx *sql.Tx, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.CreateTable("_builder", table, charset, collation, columns, keys)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInsertTx(tx *sql.Tx, table string, columns string, fields string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInsert("_builder", table, columns, fields)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInsertSelectTx(tx *sql.Tx, ins DBInsert, sel DBSelect) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInsertSelect("_builder", ins, sel)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInsertLeftJoinTx(tx *sql.Tx, ins DBInsert, sel DBJoin) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInsertLeftJoin("_builder", ins, sel)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInsertInnerJoinTx(tx *sql.Tx, ins DBInsert, sel DBJoin) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInsertInnerJoin("_builder", ins, sel)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleUpdateTx(tx *sql.Tx, table string, set string, where string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleUpdate("_builder", table, set, where)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleDeleteTx(tx *sql.Tx, table string, where string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleDelete("_builder", table, where)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
||||
// I don't know why you need this, but here it is x.x
|
||||
func (build *builder) PurgeTx(tx *sql.Tx, table string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.Purge("_builder", table)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return tx.Prepare(res)
|
||||
return build.prepareTx(tx, res, err)
|
||||
}
|
||||
|
|
|
@ -228,10 +228,6 @@ func writeSelects(adapter qgen.Adapter) error {
|
|||
|
||||
build.Select("getSettings").Table("settings").Columns("name, content, type").Parse()
|
||||
|
||||
build.Select("getSetting").Table("settings").Columns("content, type").Where("name = ?").Parse()
|
||||
|
||||
build.Select("getFullSetting").Table("settings").Columns("name, type, constraints").Where("name = ?").Parse()
|
||||
|
||||
build.Select("isPluginActive").Table("plugins").Columns("active").Where("uname = ?").Parse()
|
||||
|
||||
//build.Select("isPluginInstalled").Table("plugins").Columns("installed").Where("uname = ?").Parse()
|
||||
|
|
|
@ -1013,12 +1013,6 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user common.User) common.R
|
|||
//case "forums":
|
||||
//case "users":
|
||||
//case "pages":
|
||||
// This might not be possible. We might need .xml paths for sitemaps
|
||||
/*case "sitemap":
|
||||
if format != "xml" {
|
||||
PreError("You can only fetch sitemaps in the XML format!",w,r)
|
||||
return
|
||||
}*/
|
||||
default:
|
||||
return common.PreErrorJS("Invalid Module", w, r)
|
||||
}
|
||||
|
|
|
@ -882,7 +882,6 @@ var forum_7 = []byte(`">></a></div>`)
|
|||
var forum_8 = []byte(`
|
||||
|
||||
<main>
|
||||
|
||||
<div id="forum_head_block" class="rowblock rowhead topic_list_title_block">
|
||||
<div class="rowitem forum_title`)
|
||||
var forum_9 = []byte(` has_opt`)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{{template "header.html" . }}
|
||||
{{template "account-menu.html" . }}
|
||||
<main class="colstack_right">
|
||||
<main class="colstack account">
|
||||
{{template "account-menu.html" . }}
|
||||
<div class="colstack_right">
|
||||
<div class="colstack_item colstack_head rowhead">
|
||||
<div class="rowitem"><h1>Edit Avatar</h1></div>
|
||||
</div>
|
||||
|
@ -9,7 +10,7 @@
|
|||
<div class="rowitem"><img src="{{.CurrentUser.Avatar}}" height="128px" max-width="128px" /></div>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="colstack_item">
|
||||
<div class="colstack_item form_item">
|
||||
<form action="/user/edit/avatar/submit/" method="post" enctype="multipart/form-data">
|
||||
<div class="formrow real_first_child">
|
||||
<div class="formitem formlabel"><a>Upload Avatar</a></div>
|
||||
|
@ -20,5 +21,6 @@
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer.html" . }}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{{template "header.html" . }}
|
||||
{{template "account-menu.html" . }}
|
||||
<main class="colstack_right">
|
||||
<main class="colstack account">
|
||||
{{template "account-menu.html" . }}
|
||||
<div class="colstack_right">
|
||||
<div class="colstack_item colstack_head rowhead">
|
||||
<div class="rowitem"><h1>Emails</h1></div>
|
||||
</div>
|
||||
|
@ -16,5 +17,6 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer.html" . }}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
{{template "header.html" . }}
|
||||
{{template "account-menu.html" . }}
|
||||
<main class="colstack_right">
|
||||
<main class="colstack account">
|
||||
{{template "account-menu.html" . }}
|
||||
<div class="colstack_right">
|
||||
<div class="colstack_item colstack_head rowhead">
|
||||
<div class="rowitem"><h1>Edit Username</h1></div>
|
||||
</div>
|
||||
<div class="colstack_item">
|
||||
<div class="colstack_item form_item">
|
||||
<form action="/user/edit/username/submit/" method="post">
|
||||
<div class="formrow real_first_child">
|
||||
<div class="formitem formlabel"><a>Current Username</a></div>
|
||||
|
@ -19,5 +20,6 @@
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer.html" . }}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
{{template "header.html" . }}
|
||||
{{template "account-menu.html" . }}
|
||||
<main class="colstack_right">
|
||||
<main class="colstack account">
|
||||
{{template "account-menu.html" . }}
|
||||
<div class="colstack_right">
|
||||
<div class="colstack_item colstack_head rowhead">
|
||||
<div class="rowitem"><h1>Edit Password</h1></div>
|
||||
</div>
|
||||
<div class="colstack_item">
|
||||
<div class="colstack_item form_item">
|
||||
<form action="/user/edit/critical/submit/" method="post">
|
||||
<div class="formrow real_first_child">
|
||||
<div class="formitem formlabel"><a>Current Password</a></div>
|
||||
|
@ -23,5 +24,6 @@
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer.html" . }}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
<div id="nextFloat" class="next_button"><a class="next_link" aria-label="Go to the next page" rel="next" href="/forum/{{.Forum.ID}}?page={{add .Page 1}}">></a></div>{{end}}
|
||||
|
||||
<main>
|
||||
|
||||
<div id="forum_head_block" class="rowblock rowhead topic_list_title_block">
|
||||
<div class="rowitem forum_title{{if ne .CurrentUser.ID 0}} has_opt{{end}}"><h1>{{.Title}}</h1>
|
||||
<div id="forum_head_block" class="rowblock rowhead topic_list_title_block">
|
||||
<div class="rowitem forum_title{{if ne .CurrentUser.ID 0}} has_opt{{end}}">
|
||||
<h1>{{.Title}}</h1>
|
||||
</div>
|
||||
{{if ne .CurrentUser.ID 0}}
|
||||
{{if .CurrentUser.Perms.CreateTopic}}
|
||||
|
@ -20,9 +20,9 @@
|
|||
{{else}}<div class="opt locked_opt" title="You don't have the permissions needed to create a topic" aria-label="You don't have the permissions needed to make a topic in this forum"><a></a></div>{{end}}
|
||||
<div style="clear: both;"></div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if ne .CurrentUser.ID 0}}
|
||||
<div class="mod_floater auto_hide">
|
||||
</div>
|
||||
{{if ne .CurrentUser.ID 0}}
|
||||
<div class="mod_floater auto_hide">
|
||||
<form method="post">
|
||||
<div class="mod_floater_head">
|
||||
<span>What do you want to do with these 18 topics?</span>
|
||||
|
@ -35,10 +35,9 @@
|
|||
<button>Run</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{if .CurrentUser.Perms.CreateTopic}}
|
||||
<div id="forum_topic_create_form" class="rowblock topic_create_form quick_create_form" style="display: none;" aria-label="Quick Topic Form">
|
||||
</div>
|
||||
{{if .CurrentUser.Perms.CreateTopic}}
|
||||
<div id="forum_topic_create_form" class="rowblock topic_create_form quick_create_form" style="display: none;" aria-label="Quick Topic Form">
|
||||
<form id="topic_create_form_form" enctype="multipart/form-data" action="/topic/create/submit/" method="post"></form>
|
||||
{{if .CurrentUser.Avatar}}<img class="little_row_avatar" src="{{.CurrentUser.Avatar}}" height="64" />{{end}}
|
||||
<input form="topic_create_form_form" id="topic_board_input" name="topic-board" value="{{.Forum.ID}}" type="hidden">
|
||||
|
@ -66,10 +65,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div id="forum_topic_list" class="rowblock topic_list">
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<div id="forum_topic_list" class="rowblock topic_list">
|
||||
{{range .ItemList}}<div class="topic_row" data-tid="{{.ID}}">
|
||||
<div class="rowitem topic_left passive datarow {{if .Sticky}}topic_sticky{{else if .IsClosed}}topic_closed{{end}}">
|
||||
<span class="selector"></span>
|
||||
|
@ -94,7 +93,6 @@
|
|||
</span>
|
||||
</div>
|
||||
</div>{{else}}<div class="rowitem passive">There aren't any topics in this forum yet.{{if .CurrentUser.Perms.CreateTopic}} <a href="/topics/create/{{.Forum.ID}}">Start one?</a>{{end}}</div>{{end}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer.html" . }}
|
||||
|
|
|
@ -1,28 +1,24 @@
|
|||
{{template "header.html" . }}
|
||||
<main>
|
||||
|
||||
<div class="rowblock rowhead">
|
||||
<div class="rowblock rowhead">
|
||||
<div class="rowitem">
|
||||
<h1>IP Search</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form action="/users/ips/" method="get" id="ip-search-form"></form>
|
||||
<div class="rowblock ip_search_block">
|
||||
</div>
|
||||
<form action="/users/ips/" method="get" id="ip-search-form"></form>
|
||||
<div class="rowblock ip_search_block">
|
||||
<div class="rowitem passive">
|
||||
<input form="ip-search-form" name="ip" class="ip_search_input" type="search" placeholder="🔍︎" {{if .IP}}value="{{.IP}}"{{end}}/>
|
||||
<input form="ip-search-form" class="ip_search_search" type="submit" value="Search" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .IP}}
|
||||
<div class="rowblock bgavatars">
|
||||
</div>
|
||||
{{if .IP}}
|
||||
<div class="rowblock bgavatars">
|
||||
{{range .ItemList}}<div class="rowitem"{{if .Avatar}} style="background-image: url('{{.Avatar}}');"{{end}}>
|
||||
<a href="{{.Link}}">{{.Name}}</a>
|
||||
</div>
|
||||
{{else}}<div class="rowitem">No users found.</div>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
</div>
|
||||
{{end}}
|
||||
</main>
|
||||
{{template "footer.html" . }}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
{{template "header.html" . }}
|
||||
<div class="rowblock rowhead">
|
||||
<main>
|
||||
<div class="rowblock rowhead">
|
||||
<div class="rowitem"><h1>Login</h1></div>
|
||||
</div>
|
||||
<div class="rowblock">
|
||||
</div>
|
||||
<div class="rowblock">
|
||||
<form action="/accounts/login/submit/" method="post">
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>Account Name</a></div>
|
||||
|
@ -17,5 +18,6 @@
|
|||
<div class="formitem" style="color: #505050; font-size: 12px; font-weight: normal; float: right;">Don't have an account?</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer.html" . }}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
{{template "header.html" . }}
|
||||
<main>
|
||||
|
||||
<div class="rowblock rowhead">
|
||||
<div class="rowblock rowhead">
|
||||
<div class="rowitem"><h1>Create Account</h1></div>
|
||||
</div>
|
||||
<div class="rowblock">
|
||||
</div>
|
||||
<div class="rowblock">
|
||||
<form action="/accounts/create/submit/" method="post">
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a id="username_label">Account Name</a></div>
|
||||
|
@ -26,7 +25,6 @@
|
|||
<div class="formitem"><button name="register-button" class="formbutton">Create Account</div></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
{{template "footer.html" . }}
|
||||
|
|
|
@ -157,7 +157,7 @@ ul {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.rowblock, .colstack_item {
|
||||
.rowblock, .colstack_head {
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid var(--header-border-color);
|
||||
border-bottom: 2px solid var(--header-border-color);
|
||||
|
@ -182,6 +182,16 @@ ul {
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.colstack {
|
||||
display: flex;
|
||||
}
|
||||
#main .colstack_left {
|
||||
width: 300px;
|
||||
}
|
||||
#main .colstack_right {
|
||||
width: calc(90% - 300px);
|
||||
}
|
||||
|
||||
.extra_little_row_avatar {
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
|
@ -735,7 +745,7 @@ select, input, textarea {
|
|||
#profile_left_pane .profileName {
|
||||
font-size: 19px;
|
||||
}
|
||||
#profile_left_pane .passiveBlock .passive {
|
||||
.rowmenu .passive {
|
||||
border: 1px solid var(--element-border-color);
|
||||
border-bottom: 2px solid var(--element-border-color);
|
||||
margin-top: 6px;
|
||||
|
@ -743,14 +753,48 @@ select, input, textarea {
|
|||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.rowmenu {
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
}
|
||||
.rowmenu .passive:hover {
|
||||
margin-left: 4px;
|
||||
}
|
||||
#profile_left_pane .passiveBlock .passive {
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
#profile_right_lane {
|
||||
width: 100%;
|
||||
margin-right: 12px;
|
||||
}
|
||||
#profile_right_lane .colstack_item {
|
||||
#profile_right_lane .colstack_item, .colstack_right .colstack_item {
|
||||
border: 1px solid var(--element-border-color);
|
||||
border-bottom: 2px solid var(--element-border-color);
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.form_item {
|
||||
display: flex;
|
||||
}
|
||||
.form_item form, .colstack_item .formrow {
|
||||
display: contents;
|
||||
}
|
||||
.colstack_right .formrow {
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
.colstack_right .formrow:first-child {
|
||||
padding-top: 16px;
|
||||
}
|
||||
.colstack_right .formrow:last-child {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
.colstack_item:not(#profile_right_lane) .formrow .formlabel {
|
||||
width: min-content;
|
||||
margin-right: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.footer {
|
||||
|
|
Loading…
Reference in New Issue