Added the menu manager and menu item editor.
Refactored the menu system. Updated the README and revamped it a tad to make it easier to understand. Also, added manual instructions for patching. Revamped the update scripts, especially on Windows. Merged the CSS and Tmpl phrase namespaces. Added lastSchema to .gitignore Added DropTable to the database adapters. Implemented DbVersion in the PgSQL Adapter. Swapped out the checkboxes for cleaner looking yes-no dropdowns. Began revamping small bits of the user logic. We now open to contributions, just open a pull request and sign the CLA. Schema has been updated, run the patcher or update script.
This commit is contained in:
parent
894e545973
commit
d0318191c9
|
@ -20,6 +20,7 @@ out/*
|
|||
*.log
|
||||
.DS_Store
|
||||
.vscode/launch.json
|
||||
schema/lastSchema.json
|
||||
config/config.go
|
||||
Gosora
|
||||
Install
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
We're not accepting contributions right now, although you're welcome to poke me about things. I'd like to put a process together at some point.
|
||||
If you want to add a contribution, you'll have to open a pull request and to sign the CLA (contributor level agreement).
|
||||
|
||||
It's mainly there to deal with any legal issues which come our way and to switch licenses without having to chase down contributors who have long stopped using the internet or are deceased or incapacitated.
|
||||
|
||||
Other uses may arise in the future, e.g. commercial licensing, although that's currently uncertain.
|
||||
|
||||
# Coding Standards
|
||||
|
||||
|
|
21
README.md
21
README.md
|
@ -31,7 +31,7 @@ Other modern features like alerts, likes, advanced dashboard with live stats (CP
|
|||
|
||||
# Dependencies
|
||||
|
||||
Go 1.9 - You will need to install this. Pick the .msi, if you want everything sorted out for you rather than having to go around updating the environment settings. https://golang.org/doc/install
|
||||
Go 1.10 - You will need to install this. Pick the .msi, if you want everything sorted out for you rather than having to go around updating the environment settings. https://golang.org/doc/install
|
||||
|
||||
MySQL Database - You will need to setup a MySQL Database somewhere. A MariaDB Database works equally well and is much faster than MySQL. You could use something like WNMP / XAMPP which have a little PHP script called PhpMyAdmin for managing MySQL databases or you could install MariaDB directly.
|
||||
|
||||
|
@ -48,6 +48,8 @@ It's entirely possible that your host might already have MySQL, so you might be
|
|||
|
||||
At some point, we'll have releases which you can download, but right now, you'll have to use the `git clone` command as mentioned down in the advanced setup section to download a copy of Gosora.
|
||||
|
||||
On Windows, you might also want to try the [GosoraBootstrapper](https://github.com/Azareal/GosoraBootstrapper), if you can't find the command prompt. It's just a matter of double-clicking on the bat file there and it'll download the rest of the files for you.
|
||||
|
||||
|
||||
# Installation Instructions
|
||||
|
||||
|
@ -61,7 +63,7 @@ Follow the instructions shown on the screen.
|
|||
|
||||
*Windows*
|
||||
|
||||
Run install.bat
|
||||
Run install.bat, e.g. double-click on it. You will also have to start-up MySQL, which if you're using Wnmp or friends is just a matter of opening that program and starting the MySQL process via it.
|
||||
|
||||
Follow the instructions shown on the screen.
|
||||
|
||||
|
@ -74,7 +76,7 @@ In the same directory you installed it, you simply have to type: ./run-linux
|
|||
|
||||
*Windows*
|
||||
|
||||
Run run.bat
|
||||
Run run.bat, e.g. double-clicking on it.
|
||||
|
||||
*Updating Dependencies*
|
||||
|
||||
|
@ -97,6 +99,8 @@ Linux is similar, however you might need to use cd and mv a bit more like in the
|
|||
|
||||
You also need to substitute the `gosora.exe` bits for `./Gosora` on Linux. For more info, you might want to take a gander inside the `./run-linux` and `./install-linux` shell files to see how they're implemented.
|
||||
|
||||
If you want to skip typing all the `go get`s, you can run `./update-deps.bat` (Windows) or `./update-deps-linux` to do that for you.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Azareal/Gosora
|
||||
|
||||
|
@ -153,6 +157,17 @@ The update system is currently under development, however if you have Git instal
|
|||
|
||||
In addition to this, you can update the dependencies without updating Gosora by running `update-deps.bat` or `./update-deps-linux` (.bat is for Windows, the other for Linux as the names would suggest).
|
||||
|
||||
If you want to manually patch Gosora rather than relying on the above scripts to do it, you'll first have to create a copy of `./schema/schema.json` named `./schema/lastSchema.json`, and then, you'll overwrite the files with the new ones.
|
||||
|
||||
After that, you'll need to run `go build ./patcher` on Windows or the following code block on Linux:
|
||||
```
|
||||
cd ./patcher
|
||||
go build -o Patcher
|
||||
mv ./Patcher ..
|
||||
```
|
||||
|
||||
Once you've done that, you just need to run `patcher.exe` (Windows) or `./Patcher` to apply the latest patches to the database, etc.
|
||||
|
||||
|
||||
# How do I install plugins?
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package common
|
||||
|
||||
import "sync"
|
||||
|
||||
type DefaultMenuItemStore struct {
|
||||
items map[int]MenuItem
|
||||
itemLock sync.RWMutex
|
||||
}
|
||||
|
||||
func NewDefaultMenuItemStore() *DefaultMenuItemStore {
|
||||
return &DefaultMenuItemStore{
|
||||
items: make(map[int]MenuItem),
|
||||
}
|
||||
}
|
||||
|
||||
func (store *DefaultMenuItemStore) Add(item MenuItem) {
|
||||
store.itemLock.Lock()
|
||||
defer store.itemLock.Unlock()
|
||||
store.items[item.ID] = item
|
||||
}
|
||||
|
||||
func (store *DefaultMenuItemStore) Get(id int) (MenuItem, error) {
|
||||
store.itemLock.RLock()
|
||||
item, ok := store.items[id]
|
||||
store.itemLock.RUnlock()
|
||||
if ok {
|
||||
return item, nil
|
||||
}
|
||||
return item, ErrNoRows
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var Menus *DefaultMenuStore
|
||||
|
||||
type DefaultMenuStore struct {
|
||||
menus map[int]*atomic.Value
|
||||
itemStore *DefaultMenuItemStore
|
||||
}
|
||||
|
||||
func NewDefaultMenuStore() *DefaultMenuStore {
|
||||
return &DefaultMenuStore{
|
||||
make(map[int]*atomic.Value),
|
||||
NewDefaultMenuItemStore(),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add actual support for multiple menus
|
||||
func (store *DefaultMenuStore) GetAllMap() (out map[int]*MenuListHolder) {
|
||||
out = make(map[int]*MenuListHolder)
|
||||
for mid, atom := range store.menus {
|
||||
out[mid] = atom.Load().(*MenuListHolder)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (store *DefaultMenuStore) Get(mid int) (*MenuListHolder, error) {
|
||||
aStore, ok := store.menus[mid]
|
||||
if ok {
|
||||
return aStore.Load().(*MenuListHolder), nil
|
||||
}
|
||||
return nil, ErrNoRows
|
||||
}
|
||||
|
||||
func (store *DefaultMenuStore) Items(mid int) (mlist MenuItemList, err error) {
|
||||
acc := qgen.Builder.Accumulator()
|
||||
err = acc.Select("menu_items").Columns("miid, name, htmlID, cssClass, position, path, aria, tooltip, order, tmplName, guestOnly, memberOnly, staffOnly, adminOnly").Where("mid = " + strconv.Itoa(mid)).Orderby("order ASC").Each(func(rows *sql.Rows) error {
|
||||
var mitem = MenuItem{MenuID: mid}
|
||||
err := rows.Scan(&mitem.ID, &mitem.Name, &mitem.HTMLID, &mitem.CSSClass, &mitem.Position, &mitem.Path, &mitem.Aria, &mitem.Tooltip, &mitem.Order, &mitem.TmplName, &mitem.GuestOnly, &mitem.MemberOnly, &mitem.SuperModOnly, &mitem.AdminOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
store.itemStore.Add(mitem)
|
||||
mlist = append(mlist, mitem)
|
||||
return nil
|
||||
})
|
||||
return mlist, err
|
||||
}
|
||||
|
||||
func (store *DefaultMenuStore) Load(mid int) error {
|
||||
mlist, err := store.Items(mid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hold := &MenuListHolder{mlist, make(map[int]menuTmpl)}
|
||||
err = hold.Preparse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var aStore = &atomic.Value{}
|
||||
aStore.Store(hold)
|
||||
store.menus[mid] = aStore
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *DefaultMenuStore) ItemStore() *DefaultMenuItemStore {
|
||||
return store.itemStore
|
||||
}
|
116
common/menus.go
116
common/menus.go
|
@ -7,31 +7,12 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var Menus *DefaultMenuStore
|
||||
|
||||
type MenuItemList []MenuItem
|
||||
|
||||
type DefaultMenuStore struct {
|
||||
menus map[int]*atomic.Value
|
||||
}
|
||||
|
||||
func NewDefaultMenuStore() *DefaultMenuStore {
|
||||
return &DefaultMenuStore{make(map[int]*atomic.Value)}
|
||||
}
|
||||
|
||||
func (store *DefaultMenuStore) Get(mid int) *MenuListHolder {
|
||||
aStore, ok := store.menus[mid]
|
||||
if ok {
|
||||
return aStore.Load().(*MenuListHolder)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type MenuListHolder struct {
|
||||
List MenuItemList
|
||||
Variations map[int]menuTmpl // 0 = Guest Menu, 1 = Member Menu, 2 = Super Mod Menu, 3 = Admin Menu
|
||||
|
@ -44,6 +25,9 @@ type menuTmpl struct {
|
|||
|
||||
type MenuItem struct {
|
||||
ID int
|
||||
MenuID int
|
||||
|
||||
Name string
|
||||
HTMLID string
|
||||
CSSClass string
|
||||
Position string
|
||||
|
@ -59,50 +43,56 @@ type MenuItem struct {
|
|||
AdminOnly bool
|
||||
}
|
||||
|
||||
func (store *DefaultMenuStore) Load(mid int) error {
|
||||
var mlist MenuItemList
|
||||
acc := qgen.Builder.Accumulator()
|
||||
err := acc.Select("menu_items").Columns("htmlID, cssClass, position, path, aria, tooltip, order, tmplName, guestOnly, memberOnly, staffOnly, adminOnly").Where("mid = " + strconv.Itoa(mid)).Orderby("order ASC").Each(func(rows *sql.Rows) error {
|
||||
var mitem = MenuItem{ID: 1}
|
||||
err := rows.Scan(&mitem.HTMLID, &mitem.CSSClass, &mitem.Position, &mitem.Path, &mitem.Aria, &mitem.Tooltip, &mitem.Order, &mitem.TmplName, &mitem.GuestOnly, &mitem.MemberOnly, &mitem.SuperModOnly, &mitem.AdminOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
type MenuItemStmts struct {
|
||||
update *sql.Stmt
|
||||
}
|
||||
mlist = append(mlist, mitem)
|
||||
return nil
|
||||
|
||||
var menuItemStmts MenuItemStmts
|
||||
|
||||
func init() {
|
||||
DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||
menuItemStmts = MenuItemStmts{
|
||||
update: acc.Update("menu_items").Set("name = ?, htmlID = ?, cssClass = ?, position = ?, path = ?, aria = ?, tooltip = ?, tmplName = ?, guestOnly = ?, memberOnly = ?, staffOnly = ?, adminOnly = ?").Where("miid = ?").Prepare(),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
if err != nil {
|
||||
}
|
||||
|
||||
func (item MenuItem) Commit() error {
|
||||
_, err := menuItemStmts.update.Exec(item.Name, item.HTMLID, item.CSSClass, item.Position, item.Path, item.Aria, item.Tooltip, item.TmplName, item.GuestOnly, item.MemberOnly, item.SuperModOnly, item.AdminOnly, item.ID)
|
||||
Menus.Load(item.MenuID)
|
||||
return err
|
||||
}
|
||||
|
||||
hold := &MenuListHolder{mlist, make(map[int]menuTmpl)}
|
||||
err = hold.Preparse()
|
||||
func (hold *MenuListHolder) LoadTmpl(name string) (menuTmpl MenuTmpl, err error) {
|
||||
data, err := ioutil.ReadFile("./templates/" + name + ".html")
|
||||
if err != nil {
|
||||
return menuTmpl, err
|
||||
}
|
||||
return hold.Parse(name, data), nil
|
||||
}
|
||||
|
||||
func (hold *MenuListHolder) LoadTmpls() (tmpls map[string]MenuTmpl, err error) {
|
||||
tmpls = make(map[string]MenuTmpl)
|
||||
var loadTmpl = func(name string) error {
|
||||
menuTmpl, err := hold.LoadTmpl(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var aStore = &atomic.Value{}
|
||||
aStore.Store(hold)
|
||||
store.menus[mid] = aStore
|
||||
tmpls[name] = menuTmpl
|
||||
return nil
|
||||
}
|
||||
err = loadTmpl("menu_item")
|
||||
if err != nil {
|
||||
return tmpls, err
|
||||
}
|
||||
err = loadTmpl("menu_alerts")
|
||||
return tmpls, err
|
||||
}
|
||||
|
||||
// TODO: Run this in main, sync ticks, when the phrase file changes (need to implement the sync for that first), and when the settings are changed
|
||||
func (hold *MenuListHolder) Preparse() error {
|
||||
var tmpls = make(map[string]MenuTmpl)
|
||||
var loadTmpl = func(name string) error {
|
||||
data, err := ioutil.ReadFile("./templates/" + name + ".html")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmpls[name] = hold.Parse(name, data)
|
||||
return nil
|
||||
}
|
||||
err := loadTmpl("menu_item")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = loadTmpl("menu_alerts")
|
||||
tmpls, err := hold.LoadTmpls()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -194,6 +184,7 @@ func (hold *MenuListHolder) Parse(name string, tmplData []byte) (menuTmpl MenuTm
|
|||
// ? We only support simple properties on MenuItem right now
|
||||
var addVariable = func(name []byte) {
|
||||
//fmt.Println("appending subBuffer: ", string(subBuffer))
|
||||
// TODO: Check if the subBuffer has any items or is empty
|
||||
textBuffer = append(textBuffer, subBuffer)
|
||||
subBuffer = nil
|
||||
|
||||
|
@ -203,13 +194,17 @@ func (hold *MenuListHolder) Parse(name string, tmplData []byte) (menuTmpl MenuTm
|
|||
renderList = append(renderList, menuRenderItem{1, len(variableBuffer) - 1})
|
||||
}
|
||||
|
||||
tmplData = bytes.Replace(tmplData, []byte("{{"), []byte("{"), -1)
|
||||
tmplData = bytes.Replace(tmplData, []byte("}}"), []byte("}}"), -1)
|
||||
for i := 0; i < len(tmplData); i++ {
|
||||
char := tmplData[i]
|
||||
if char == '{' && nextCharIs(tmplData, i, '{') {
|
||||
if char == '{' {
|
||||
//fmt.Println("found open fence")
|
||||
dotIndex, hasDot := skipUntilIfExists(tmplData, i, '.')
|
||||
if !hasDot {
|
||||
//fmt.Println("no dot, assumed template function style")
|
||||
// Template function style
|
||||
langIndex, hasChars := skipUntilCharsExist(tmplData, i+2, []byte("lang"))
|
||||
langIndex, hasChars := skipUntilCharsExist(tmplData, i+1, []byte("lang"))
|
||||
if hasChars {
|
||||
startIndex, hasStart := skipUntilIfExists(tmplData, langIndex, '"')
|
||||
endIndex, hasEnd := skipUntilIfExists(tmplData, startIndex+1, '"')
|
||||
|
@ -228,7 +223,8 @@ func (hold *MenuListHolder) Parse(name string, tmplData []byte) (menuTmpl MenuTm
|
|||
break
|
||||
}
|
||||
fenceIndex, hasFence := skipUntilIfExists(tmplData, dotIndex, '}')
|
||||
if !hasFence || !nextCharIs(tmplData, fenceIndex, '}') {
|
||||
if !hasFence {
|
||||
//fmt.Println("no end fence")
|
||||
break
|
||||
}
|
||||
addVariable(tmplData[dotIndex:fenceIndex])
|
||||
|
@ -258,11 +254,19 @@ func (hold *MenuListHolder) Scan(menuTmpls map[string]MenuTmpl, showItem func(mi
|
|||
if !showItem(mitem) {
|
||||
continue
|
||||
}
|
||||
renderBuffer, variableIndices = hold.ScanItem(menuTmpls, mitem, renderBuffer, variableIndices)
|
||||
}
|
||||
// TODO: Need more coalescing in the renderBuffer
|
||||
return renderBuffer, variableIndices
|
||||
}
|
||||
|
||||
// Note: This doesn't do a visibility check like hold.Scan() does
|
||||
func (hold *MenuListHolder) ScanItem(menuTmpls map[string]MenuTmpl, mitem MenuItem, renderBuffer [][]byte, variableIndices []int) ([][]byte, []int) {
|
||||
menuTmpl, ok := menuTmpls[mitem.TmplName]
|
||||
if !ok {
|
||||
menuTmpl = menuTmpls["menu_item"]
|
||||
}
|
||||
|
||||
//fmt.Println("menuTmpl: ", menuTmpl)
|
||||
for _, renderItem := range menuTmpl.RenderList {
|
||||
if renderItem.Type == 0 {
|
||||
|
@ -284,6 +288,10 @@ func (hold *MenuListHolder) Scan(menuTmpls map[string]MenuTmpl, showItem func(mi
|
|||
} else {
|
||||
var renderItem []byte
|
||||
switch string(variable) {
|
||||
case ".ID":
|
||||
renderItem = []byte(strconv.Itoa(mitem.ID))
|
||||
case ".Name":
|
||||
renderItem = []byte(mitem.Name)
|
||||
case ".HTMLID":
|
||||
renderItem = []byte(mitem.HTMLID)
|
||||
case ".CSSClass":
|
||||
|
@ -328,8 +336,6 @@ func (hold *MenuListHolder) Scan(menuTmpls map[string]MenuTmpl, showItem func(mi
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: Need more coalescing in the renderBuffer
|
||||
return renderBuffer, variableIndices
|
||||
}
|
||||
|
||||
|
|
|
@ -170,9 +170,7 @@ type GridElement struct {
|
|||
}
|
||||
|
||||
type PanelDashboardPage struct {
|
||||
Title string
|
||||
CurrentUser User
|
||||
Header *Header
|
||||
*Header
|
||||
Stats PanelStats
|
||||
Zone string
|
||||
GridItems []GridElement
|
||||
|
@ -255,15 +253,40 @@ type PanelAnalyticsAgentPage struct {
|
|||
}
|
||||
|
||||
type PanelThemesPage struct {
|
||||
Title string
|
||||
CurrentUser User
|
||||
Header *Header
|
||||
*Header
|
||||
Stats PanelStats
|
||||
Zone string
|
||||
PrimaryThemes []*Theme
|
||||
VariantThemes []*Theme
|
||||
}
|
||||
|
||||
type PanelMenuListItem struct {
|
||||
ID int
|
||||
ItemCount int
|
||||
}
|
||||
|
||||
type PanelMenuListPage struct {
|
||||
*Header
|
||||
Stats PanelStats
|
||||
Zone string
|
||||
ItemList []PanelMenuListItem
|
||||
}
|
||||
|
||||
type PanelMenuPage struct {
|
||||
*Header
|
||||
Stats PanelStats
|
||||
Zone string
|
||||
ID int
|
||||
ItemList []MenuItem
|
||||
}
|
||||
|
||||
type PanelMenuItemPage struct {
|
||||
*Header
|
||||
Stats PanelStats
|
||||
Zone string
|
||||
Item MenuItem
|
||||
}
|
||||
|
||||
type PanelUserPage struct {
|
||||
Title string
|
||||
CurrentUser User
|
||||
|
|
|
@ -49,7 +49,6 @@ type LanguagePack struct {
|
|||
NoticePhrases map[string]string
|
||||
PageTitles map[string]string
|
||||
TmplPhrases map[string]string
|
||||
CSSPhrases map[string]string
|
||||
|
||||
TmplIndicesToPhrases [][][]byte // [tmplID][index]phrase
|
||||
}
|
||||
|
@ -231,8 +230,8 @@ func GetTmplPhrase(name string) string {
|
|||
return res
|
||||
}
|
||||
|
||||
func GetCSSPhrases() map[string]string {
|
||||
return currentLangPack.Load().(*LanguagePack).CSSPhrases
|
||||
func GetTmplPhrases() map[string]string {
|
||||
return currentLangPack.Load().(*LanguagePack).TmplPhrases
|
||||
}
|
||||
|
||||
func getPhrasePlaceholder(prefix string, suffix string) string {
|
||||
|
|
|
@ -212,7 +212,7 @@ func (theme *Theme) LoadStaticFiles() error {
|
|||
}
|
||||
|
||||
func (theme *Theme) AddThemeStaticFiles() error {
|
||||
phraseMap := GetCSSPhrases()
|
||||
phraseMap := GetTmplPhrases()
|
||||
// TODO: Use a function instead of a closure to make this more testable? What about a function call inside the closure to take the theme variable into account?
|
||||
return filepath.Walk("./themes/"+theme.Name+"/public", func(path string, f os.FileInfo, err error) error {
|
||||
DebugLog("Attempting to add static file '" + path + "' for default theme '" + theme.Name + "'")
|
||||
|
|
|
@ -83,24 +83,25 @@ var userStmts UserStmts
|
|||
|
||||
func init() {
|
||||
DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||
var where = "uid = ?"
|
||||
userStmts = UserStmts{
|
||||
activate: acc.SimpleUpdate("users", "active = 1", "uid = ?"),
|
||||
changeGroup: acc.SimpleUpdate("users", "group = ?", "uid = ?"), // TODO: Implement user_count for users_groups here
|
||||
delete: acc.SimpleDelete("users", "uid = ?"),
|
||||
setAvatar: acc.SimpleUpdate("users", "avatar = ?", "uid = ?"),
|
||||
setUsername: acc.SimpleUpdate("users", "name = ?", "uid = ?"),
|
||||
incrementTopics: acc.SimpleUpdate("users", "topics = topics + ?", "uid = ?"),
|
||||
updateLevel: acc.SimpleUpdate("users", "level = ?", "uid = ?"),
|
||||
incrementScore: acc.SimpleUpdate("users", "score = score + ?", "uid = ?"),
|
||||
incrementPosts: acc.SimpleUpdate("users", "posts = posts + ?", "uid = ?"),
|
||||
incrementBigposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?", "uid = ?"),
|
||||
incrementMegaposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ?", "uid = ?"),
|
||||
incrementLiked: acc.SimpleUpdate("users", "liked = liked + ?, lastLiked = UTC_TIMESTAMP()", "uid = ?"),
|
||||
decrementLiked: acc.SimpleUpdate("users", "liked = liked - ?", "uid = ?"),
|
||||
activate: acc.SimpleUpdate("users", "active = 1", where),
|
||||
changeGroup: acc.SimpleUpdate("users", "group = ?", where), // TODO: Implement user_count for users_groups here
|
||||
delete: acc.SimpleDelete("users", where),
|
||||
setAvatar: acc.SimpleUpdate("users", "avatar = ?", where),
|
||||
setUsername: acc.Update("users").Set("name = ?").Where(where).Prepare(),
|
||||
incrementTopics: acc.SimpleUpdate("users", "topics = topics + ?", where),
|
||||
updateLevel: acc.SimpleUpdate("users", "level = ?", where),
|
||||
incrementScore: acc.SimpleUpdate("users", "score = score + ?", where),
|
||||
incrementPosts: acc.SimpleUpdate("users", "posts = posts + ?", where),
|
||||
incrementBigposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?", where),
|
||||
incrementMegaposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ?", where),
|
||||
incrementLiked: acc.SimpleUpdate("users", "liked = liked + ?, lastLiked = UTC_TIMESTAMP()", where),
|
||||
decrementLiked: acc.SimpleUpdate("users", "liked = liked - ?", where),
|
||||
//recalcLastLiked: acc...
|
||||
updateLastIP: acc.SimpleUpdate("users", "last_ip = ?", "uid = ?"),
|
||||
updateLastIP: acc.SimpleUpdate("users", "last_ip = ?", where),
|
||||
|
||||
setPassword: acc.SimpleUpdate("users", "password = ?, salt = ?", "uid = ?"),
|
||||
setPassword: acc.SimpleUpdate("users", "password = ?, salt = ?", where),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
|
@ -231,12 +232,17 @@ func (user *User) Delete() error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (user *User) ChangeName(username string) (err error) {
|
||||
_, err = userStmts.setUsername.Exec(username, user.ID)
|
||||
func (user *User) bindStmt(stmt *sql.Stmt, params ...interface{}) (err error) {
|
||||
params = append(params, user.ID)
|
||||
_, err = stmt.Exec(params...)
|
||||
user.CacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (user *User) ChangeName(username string) (err error) {
|
||||
return user.bindStmt(userStmts.setUsername, username)
|
||||
}
|
||||
|
||||
func (user *User) ChangeAvatar(avatar string) (err error) {
|
||||
_, err = userStmts.setAvatar.Exec(avatar, user.ID)
|
||||
user.CacheRemove()
|
||||
|
|
|
@ -134,8 +134,8 @@ func BuildWidget(dock string, header *Header) (sbody string) {
|
|||
widgets = Docks.RightOfNav
|
||||
case "topMenu":
|
||||
// 1 = id for the default menu
|
||||
mhold := Menus.Get(1)
|
||||
if mhold != nil {
|
||||
mhold, err := Menus.Get(1)
|
||||
if err == nil {
|
||||
err := mhold.Build(header.Writer, &header.CurrentUser)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
|
|
|
@ -94,7 +94,10 @@ if %errorlevel% neq 0 (
|
|||
|
||||
|
||||
echo Updating Gosora
|
||||
copy ./schema/schema.json ./schema/lastSchema.json
|
||||
cd schema
|
||||
del /Q lastSchema.json
|
||||
copy schema.json lastSchema.json
|
||||
cd ..
|
||||
git pull origin master
|
||||
if %errorlevel% neq 0 (
|
||||
pause
|
||||
|
|
480
gen_router.go
480
gen_router.go
|
@ -49,6 +49,10 @@ var RouteMap = map[string]interface{}{
|
|||
"routePanelWordFiltersDeleteSubmit": routePanelWordFiltersDeleteSubmit,
|
||||
"routePanelThemes": routePanelThemes,
|
||||
"routePanelThemesSetDefault": routePanelThemesSetDefault,
|
||||
"routePanelThemesMenus": routePanelThemesMenus,
|
||||
"routePanelThemesMenusEdit": routePanelThemesMenusEdit,
|
||||
"routePanelThemesMenuItemEdit": routePanelThemesMenuItemEdit,
|
||||
"routePanelThemesMenuItemEditSubmit": routePanelThemesMenuItemEditSubmit,
|
||||
"routePanelPlugins": routePanelPlugins,
|
||||
"routePanelPluginsActivate": routePanelPluginsActivate,
|
||||
"routePanelPluginsDeactivate": routePanelPluginsDeactivate,
|
||||
|
@ -158,81 +162,85 @@ var routeMapEnum = map[string]int{
|
|||
"routePanelWordFiltersDeleteSubmit": 27,
|
||||
"routePanelThemes": 28,
|
||||
"routePanelThemesSetDefault": 29,
|
||||
"routePanelPlugins": 30,
|
||||
"routePanelPluginsActivate": 31,
|
||||
"routePanelPluginsDeactivate": 32,
|
||||
"routePanelPluginsInstall": 33,
|
||||
"routePanelUsers": 34,
|
||||
"routePanelUsersEdit": 35,
|
||||
"routePanelUsersEditSubmit": 36,
|
||||
"routePanelAnalyticsViews": 37,
|
||||
"routePanelAnalyticsRoutes": 38,
|
||||
"routePanelAnalyticsAgents": 39,
|
||||
"routePanelAnalyticsSystems": 40,
|
||||
"routePanelAnalyticsLanguages": 41,
|
||||
"routePanelAnalyticsReferrers": 42,
|
||||
"routePanelAnalyticsRouteViews": 43,
|
||||
"routePanelAnalyticsAgentViews": 44,
|
||||
"routePanelAnalyticsForumViews": 45,
|
||||
"routePanelAnalyticsSystemViews": 46,
|
||||
"routePanelAnalyticsLanguageViews": 47,
|
||||
"routePanelAnalyticsReferrerViews": 48,
|
||||
"routePanelAnalyticsPosts": 49,
|
||||
"routePanelAnalyticsTopics": 50,
|
||||
"routePanelAnalyticsForums": 51,
|
||||
"routePanelGroups": 52,
|
||||
"routePanelGroupsEdit": 53,
|
||||
"routePanelGroupsEditPerms": 54,
|
||||
"routePanelGroupsEditSubmit": 55,
|
||||
"routePanelGroupsEditPermsSubmit": 56,
|
||||
"routePanelGroupsCreateSubmit": 57,
|
||||
"routePanelBackups": 58,
|
||||
"routePanelLogsMod": 59,
|
||||
"routePanelDebug": 60,
|
||||
"routePanelDashboard": 61,
|
||||
"routes.AccountEditCritical": 62,
|
||||
"routeAccountEditCriticalSubmit": 63,
|
||||
"routeAccountEditAvatar": 64,
|
||||
"routeAccountEditAvatarSubmit": 65,
|
||||
"routeAccountEditUsername": 66,
|
||||
"routeAccountEditUsernameSubmit": 67,
|
||||
"routeAccountEditEmail": 68,
|
||||
"routeAccountEditEmailTokenSubmit": 69,
|
||||
"routes.ViewProfile": 70,
|
||||
"routes.BanUserSubmit": 71,
|
||||
"routes.UnbanUser": 72,
|
||||
"routes.ActivateUser": 73,
|
||||
"routes.IPSearch": 74,
|
||||
"routes.CreateTopicSubmit": 75,
|
||||
"routes.EditTopicSubmit": 76,
|
||||
"routes.DeleteTopicSubmit": 77,
|
||||
"routes.StickTopicSubmit": 78,
|
||||
"routes.UnstickTopicSubmit": 79,
|
||||
"routes.LockTopicSubmit": 80,
|
||||
"routes.UnlockTopicSubmit": 81,
|
||||
"routes.MoveTopicSubmit": 82,
|
||||
"routeLikeTopicSubmit": 83,
|
||||
"routes.ViewTopic": 84,
|
||||
"routes.CreateReplySubmit": 85,
|
||||
"routes.ReplyEditSubmit": 86,
|
||||
"routes.ReplyDeleteSubmit": 87,
|
||||
"routeReplyLikeSubmit": 88,
|
||||
"routeProfileReplyCreateSubmit": 89,
|
||||
"routes.ProfileReplyEditSubmit": 90,
|
||||
"routes.ProfileReplyDeleteSubmit": 91,
|
||||
"routes.PollVote": 92,
|
||||
"routes.PollResults": 93,
|
||||
"routes.AccountLogin": 94,
|
||||
"routes.AccountRegister": 95,
|
||||
"routeLogout": 96,
|
||||
"routes.AccountLoginSubmit": 97,
|
||||
"routes.AccountRegisterSubmit": 98,
|
||||
"routeDynamic": 99,
|
||||
"routeUploads": 100,
|
||||
"routes.StaticFile": 101,
|
||||
"routes.RobotsTxt": 102,
|
||||
"routes.SitemapXml": 103,
|
||||
"BadRoute": 104,
|
||||
"routePanelThemesMenus": 30,
|
||||
"routePanelThemesMenusEdit": 31,
|
||||
"routePanelThemesMenuItemEdit": 32,
|
||||
"routePanelThemesMenuItemEditSubmit": 33,
|
||||
"routePanelPlugins": 34,
|
||||
"routePanelPluginsActivate": 35,
|
||||
"routePanelPluginsDeactivate": 36,
|
||||
"routePanelPluginsInstall": 37,
|
||||
"routePanelUsers": 38,
|
||||
"routePanelUsersEdit": 39,
|
||||
"routePanelUsersEditSubmit": 40,
|
||||
"routePanelAnalyticsViews": 41,
|
||||
"routePanelAnalyticsRoutes": 42,
|
||||
"routePanelAnalyticsAgents": 43,
|
||||
"routePanelAnalyticsSystems": 44,
|
||||
"routePanelAnalyticsLanguages": 45,
|
||||
"routePanelAnalyticsReferrers": 46,
|
||||
"routePanelAnalyticsRouteViews": 47,
|
||||
"routePanelAnalyticsAgentViews": 48,
|
||||
"routePanelAnalyticsForumViews": 49,
|
||||
"routePanelAnalyticsSystemViews": 50,
|
||||
"routePanelAnalyticsLanguageViews": 51,
|
||||
"routePanelAnalyticsReferrerViews": 52,
|
||||
"routePanelAnalyticsPosts": 53,
|
||||
"routePanelAnalyticsTopics": 54,
|
||||
"routePanelAnalyticsForums": 55,
|
||||
"routePanelGroups": 56,
|
||||
"routePanelGroupsEdit": 57,
|
||||
"routePanelGroupsEditPerms": 58,
|
||||
"routePanelGroupsEditSubmit": 59,
|
||||
"routePanelGroupsEditPermsSubmit": 60,
|
||||
"routePanelGroupsCreateSubmit": 61,
|
||||
"routePanelBackups": 62,
|
||||
"routePanelLogsMod": 63,
|
||||
"routePanelDebug": 64,
|
||||
"routePanelDashboard": 65,
|
||||
"routes.AccountEditCritical": 66,
|
||||
"routeAccountEditCriticalSubmit": 67,
|
||||
"routeAccountEditAvatar": 68,
|
||||
"routeAccountEditAvatarSubmit": 69,
|
||||
"routeAccountEditUsername": 70,
|
||||
"routeAccountEditUsernameSubmit": 71,
|
||||
"routeAccountEditEmail": 72,
|
||||
"routeAccountEditEmailTokenSubmit": 73,
|
||||
"routes.ViewProfile": 74,
|
||||
"routes.BanUserSubmit": 75,
|
||||
"routes.UnbanUser": 76,
|
||||
"routes.ActivateUser": 77,
|
||||
"routes.IPSearch": 78,
|
||||
"routes.CreateTopicSubmit": 79,
|
||||
"routes.EditTopicSubmit": 80,
|
||||
"routes.DeleteTopicSubmit": 81,
|
||||
"routes.StickTopicSubmit": 82,
|
||||
"routes.UnstickTopicSubmit": 83,
|
||||
"routes.LockTopicSubmit": 84,
|
||||
"routes.UnlockTopicSubmit": 85,
|
||||
"routes.MoveTopicSubmit": 86,
|
||||
"routeLikeTopicSubmit": 87,
|
||||
"routes.ViewTopic": 88,
|
||||
"routes.CreateReplySubmit": 89,
|
||||
"routes.ReplyEditSubmit": 90,
|
||||
"routes.ReplyDeleteSubmit": 91,
|
||||
"routeReplyLikeSubmit": 92,
|
||||
"routeProfileReplyCreateSubmit": 93,
|
||||
"routes.ProfileReplyEditSubmit": 94,
|
||||
"routes.ProfileReplyDeleteSubmit": 95,
|
||||
"routes.PollVote": 96,
|
||||
"routes.PollResults": 97,
|
||||
"routes.AccountLogin": 98,
|
||||
"routes.AccountRegister": 99,
|
||||
"routeLogout": 100,
|
||||
"routes.AccountLoginSubmit": 101,
|
||||
"routes.AccountRegisterSubmit": 102,
|
||||
"routeDynamic": 103,
|
||||
"routeUploads": 104,
|
||||
"routes.StaticFile": 105,
|
||||
"routes.RobotsTxt": 106,
|
||||
"routes.SitemapXml": 107,
|
||||
"BadRoute": 108,
|
||||
}
|
||||
var reverseRouteMapEnum = map[int]string{
|
||||
0: "routeAPI",
|
||||
|
@ -265,81 +273,85 @@ var reverseRouteMapEnum = map[int]string{
|
|||
27: "routePanelWordFiltersDeleteSubmit",
|
||||
28: "routePanelThemes",
|
||||
29: "routePanelThemesSetDefault",
|
||||
30: "routePanelPlugins",
|
||||
31: "routePanelPluginsActivate",
|
||||
32: "routePanelPluginsDeactivate",
|
||||
33: "routePanelPluginsInstall",
|
||||
34: "routePanelUsers",
|
||||
35: "routePanelUsersEdit",
|
||||
36: "routePanelUsersEditSubmit",
|
||||
37: "routePanelAnalyticsViews",
|
||||
38: "routePanelAnalyticsRoutes",
|
||||
39: "routePanelAnalyticsAgents",
|
||||
40: "routePanelAnalyticsSystems",
|
||||
41: "routePanelAnalyticsLanguages",
|
||||
42: "routePanelAnalyticsReferrers",
|
||||
43: "routePanelAnalyticsRouteViews",
|
||||
44: "routePanelAnalyticsAgentViews",
|
||||
45: "routePanelAnalyticsForumViews",
|
||||
46: "routePanelAnalyticsSystemViews",
|
||||
47: "routePanelAnalyticsLanguageViews",
|
||||
48: "routePanelAnalyticsReferrerViews",
|
||||
49: "routePanelAnalyticsPosts",
|
||||
50: "routePanelAnalyticsTopics",
|
||||
51: "routePanelAnalyticsForums",
|
||||
52: "routePanelGroups",
|
||||
53: "routePanelGroupsEdit",
|
||||
54: "routePanelGroupsEditPerms",
|
||||
55: "routePanelGroupsEditSubmit",
|
||||
56: "routePanelGroupsEditPermsSubmit",
|
||||
57: "routePanelGroupsCreateSubmit",
|
||||
58: "routePanelBackups",
|
||||
59: "routePanelLogsMod",
|
||||
60: "routePanelDebug",
|
||||
61: "routePanelDashboard",
|
||||
62: "routes.AccountEditCritical",
|
||||
63: "routeAccountEditCriticalSubmit",
|
||||
64: "routeAccountEditAvatar",
|
||||
65: "routeAccountEditAvatarSubmit",
|
||||
66: "routeAccountEditUsername",
|
||||
67: "routeAccountEditUsernameSubmit",
|
||||
68: "routeAccountEditEmail",
|
||||
69: "routeAccountEditEmailTokenSubmit",
|
||||
70: "routes.ViewProfile",
|
||||
71: "routes.BanUserSubmit",
|
||||
72: "routes.UnbanUser",
|
||||
73: "routes.ActivateUser",
|
||||
74: "routes.IPSearch",
|
||||
75: "routes.CreateTopicSubmit",
|
||||
76: "routes.EditTopicSubmit",
|
||||
77: "routes.DeleteTopicSubmit",
|
||||
78: "routes.StickTopicSubmit",
|
||||
79: "routes.UnstickTopicSubmit",
|
||||
80: "routes.LockTopicSubmit",
|
||||
81: "routes.UnlockTopicSubmit",
|
||||
82: "routes.MoveTopicSubmit",
|
||||
83: "routeLikeTopicSubmit",
|
||||
84: "routes.ViewTopic",
|
||||
85: "routes.CreateReplySubmit",
|
||||
86: "routes.ReplyEditSubmit",
|
||||
87: "routes.ReplyDeleteSubmit",
|
||||
88: "routeReplyLikeSubmit",
|
||||
89: "routeProfileReplyCreateSubmit",
|
||||
90: "routes.ProfileReplyEditSubmit",
|
||||
91: "routes.ProfileReplyDeleteSubmit",
|
||||
92: "routes.PollVote",
|
||||
93: "routes.PollResults",
|
||||
94: "routes.AccountLogin",
|
||||
95: "routes.AccountRegister",
|
||||
96: "routeLogout",
|
||||
97: "routes.AccountLoginSubmit",
|
||||
98: "routes.AccountRegisterSubmit",
|
||||
99: "routeDynamic",
|
||||
100: "routeUploads",
|
||||
101: "routes.StaticFile",
|
||||
102: "routes.RobotsTxt",
|
||||
103: "routes.SitemapXml",
|
||||
104: "BadRoute",
|
||||
30: "routePanelThemesMenus",
|
||||
31: "routePanelThemesMenusEdit",
|
||||
32: "routePanelThemesMenuItemEdit",
|
||||
33: "routePanelThemesMenuItemEditSubmit",
|
||||
34: "routePanelPlugins",
|
||||
35: "routePanelPluginsActivate",
|
||||
36: "routePanelPluginsDeactivate",
|
||||
37: "routePanelPluginsInstall",
|
||||
38: "routePanelUsers",
|
||||
39: "routePanelUsersEdit",
|
||||
40: "routePanelUsersEditSubmit",
|
||||
41: "routePanelAnalyticsViews",
|
||||
42: "routePanelAnalyticsRoutes",
|
||||
43: "routePanelAnalyticsAgents",
|
||||
44: "routePanelAnalyticsSystems",
|
||||
45: "routePanelAnalyticsLanguages",
|
||||
46: "routePanelAnalyticsReferrers",
|
||||
47: "routePanelAnalyticsRouteViews",
|
||||
48: "routePanelAnalyticsAgentViews",
|
||||
49: "routePanelAnalyticsForumViews",
|
||||
50: "routePanelAnalyticsSystemViews",
|
||||
51: "routePanelAnalyticsLanguageViews",
|
||||
52: "routePanelAnalyticsReferrerViews",
|
||||
53: "routePanelAnalyticsPosts",
|
||||
54: "routePanelAnalyticsTopics",
|
||||
55: "routePanelAnalyticsForums",
|
||||
56: "routePanelGroups",
|
||||
57: "routePanelGroupsEdit",
|
||||
58: "routePanelGroupsEditPerms",
|
||||
59: "routePanelGroupsEditSubmit",
|
||||
60: "routePanelGroupsEditPermsSubmit",
|
||||
61: "routePanelGroupsCreateSubmit",
|
||||
62: "routePanelBackups",
|
||||
63: "routePanelLogsMod",
|
||||
64: "routePanelDebug",
|
||||
65: "routePanelDashboard",
|
||||
66: "routes.AccountEditCritical",
|
||||
67: "routeAccountEditCriticalSubmit",
|
||||
68: "routeAccountEditAvatar",
|
||||
69: "routeAccountEditAvatarSubmit",
|
||||
70: "routeAccountEditUsername",
|
||||
71: "routeAccountEditUsernameSubmit",
|
||||
72: "routeAccountEditEmail",
|
||||
73: "routeAccountEditEmailTokenSubmit",
|
||||
74: "routes.ViewProfile",
|
||||
75: "routes.BanUserSubmit",
|
||||
76: "routes.UnbanUser",
|
||||
77: "routes.ActivateUser",
|
||||
78: "routes.IPSearch",
|
||||
79: "routes.CreateTopicSubmit",
|
||||
80: "routes.EditTopicSubmit",
|
||||
81: "routes.DeleteTopicSubmit",
|
||||
82: "routes.StickTopicSubmit",
|
||||
83: "routes.UnstickTopicSubmit",
|
||||
84: "routes.LockTopicSubmit",
|
||||
85: "routes.UnlockTopicSubmit",
|
||||
86: "routes.MoveTopicSubmit",
|
||||
87: "routeLikeTopicSubmit",
|
||||
88: "routes.ViewTopic",
|
||||
89: "routes.CreateReplySubmit",
|
||||
90: "routes.ReplyEditSubmit",
|
||||
91: "routes.ReplyDeleteSubmit",
|
||||
92: "routeReplyLikeSubmit",
|
||||
93: "routeProfileReplyCreateSubmit",
|
||||
94: "routes.ProfileReplyEditSubmit",
|
||||
95: "routes.ProfileReplyDeleteSubmit",
|
||||
96: "routes.PollVote",
|
||||
97: "routes.PollResults",
|
||||
98: "routes.AccountLogin",
|
||||
99: "routes.AccountRegister",
|
||||
100: "routeLogout",
|
||||
101: "routes.AccountLoginSubmit",
|
||||
102: "routes.AccountRegisterSubmit",
|
||||
103: "routeDynamic",
|
||||
104: "routeUploads",
|
||||
105: "routes.StaticFile",
|
||||
106: "routes.RobotsTxt",
|
||||
107: "routes.SitemapXml",
|
||||
108: "BadRoute",
|
||||
}
|
||||
var osMapEnum = map[string]int{
|
||||
"unknown": 0,
|
||||
|
@ -635,7 +647,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
counters.GlobalViewCounter.Bump()
|
||||
|
||||
if prefix == "/static" {
|
||||
counters.RouteViewCounter.Bump(101)
|
||||
counters.RouteViewCounter.Bump(105)
|
||||
req.URL.Path += extraData
|
||||
routes.StaticFile(w, req)
|
||||
return
|
||||
|
@ -1038,8 +1050,26 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
|
||||
counters.RouteViewCounter.Bump(29)
|
||||
err = routePanelThemesSetDefault(w,req,user,extraData)
|
||||
case "/panel/plugins/":
|
||||
case "/panel/themes/menus/":
|
||||
counters.RouteViewCounter.Bump(30)
|
||||
err = routePanelThemesMenus(w,req,user)
|
||||
case "/panel/themes/menus/edit/":
|
||||
counters.RouteViewCounter.Bump(31)
|
||||
err = routePanelThemesMenusEdit(w,req,user,extraData)
|
||||
case "/panel/themes/menus/item/edit/":
|
||||
counters.RouteViewCounter.Bump(32)
|
||||
err = routePanelThemesMenuItemEdit(w,req,user,extraData)
|
||||
case "/panel/themes/menus/item/edit/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(33)
|
||||
err = routePanelThemesMenuItemEditSubmit(w,req,user,extraData)
|
||||
case "/panel/plugins/":
|
||||
counters.RouteViewCounter.Bump(34)
|
||||
err = routePanelPlugins(w,req,user)
|
||||
case "/panel/plugins/activate/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1048,7 +1078,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(31)
|
||||
counters.RouteViewCounter.Bump(35)
|
||||
err = routePanelPluginsActivate(w,req,user,extraData)
|
||||
case "/panel/plugins/deactivate/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1057,7 +1087,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(32)
|
||||
counters.RouteViewCounter.Bump(36)
|
||||
err = routePanelPluginsDeactivate(w,req,user,extraData)
|
||||
case "/panel/plugins/install/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1066,13 +1096,13 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(33)
|
||||
counters.RouteViewCounter.Bump(37)
|
||||
err = routePanelPluginsInstall(w,req,user,extraData)
|
||||
case "/panel/users/":
|
||||
counters.RouteViewCounter.Bump(34)
|
||||
counters.RouteViewCounter.Bump(38)
|
||||
err = routePanelUsers(w,req,user)
|
||||
case "/panel/users/edit/":
|
||||
counters.RouteViewCounter.Bump(35)
|
||||
counters.RouteViewCounter.Bump(39)
|
||||
err = routePanelUsersEdit(w,req,user,extraData)
|
||||
case "/panel/users/edit/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1081,7 +1111,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(36)
|
||||
counters.RouteViewCounter.Bump(40)
|
||||
err = routePanelUsersEditSubmit(w,req,user,extraData)
|
||||
case "/panel/analytics/views/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1090,7 +1120,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(37)
|
||||
counters.RouteViewCounter.Bump(41)
|
||||
err = routePanelAnalyticsViews(w,req,user)
|
||||
case "/panel/analytics/routes/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1099,7 +1129,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(38)
|
||||
counters.RouteViewCounter.Bump(42)
|
||||
err = routePanelAnalyticsRoutes(w,req,user)
|
||||
case "/panel/analytics/agents/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1108,7 +1138,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(39)
|
||||
counters.RouteViewCounter.Bump(43)
|
||||
err = routePanelAnalyticsAgents(w,req,user)
|
||||
case "/panel/analytics/systems/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1117,7 +1147,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(40)
|
||||
counters.RouteViewCounter.Bump(44)
|
||||
err = routePanelAnalyticsSystems(w,req,user)
|
||||
case "/panel/analytics/langs/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1126,7 +1156,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(41)
|
||||
counters.RouteViewCounter.Bump(45)
|
||||
err = routePanelAnalyticsLanguages(w,req,user)
|
||||
case "/panel/analytics/referrers/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1135,25 +1165,25 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(42)
|
||||
counters.RouteViewCounter.Bump(46)
|
||||
err = routePanelAnalyticsReferrers(w,req,user)
|
||||
case "/panel/analytics/route/":
|
||||
counters.RouteViewCounter.Bump(43)
|
||||
counters.RouteViewCounter.Bump(47)
|
||||
err = routePanelAnalyticsRouteViews(w,req,user,extraData)
|
||||
case "/panel/analytics/agent/":
|
||||
counters.RouteViewCounter.Bump(44)
|
||||
counters.RouteViewCounter.Bump(48)
|
||||
err = routePanelAnalyticsAgentViews(w,req,user,extraData)
|
||||
case "/panel/analytics/forum/":
|
||||
counters.RouteViewCounter.Bump(45)
|
||||
counters.RouteViewCounter.Bump(49)
|
||||
err = routePanelAnalyticsForumViews(w,req,user,extraData)
|
||||
case "/panel/analytics/system/":
|
||||
counters.RouteViewCounter.Bump(46)
|
||||
counters.RouteViewCounter.Bump(50)
|
||||
err = routePanelAnalyticsSystemViews(w,req,user,extraData)
|
||||
case "/panel/analytics/lang/":
|
||||
counters.RouteViewCounter.Bump(47)
|
||||
counters.RouteViewCounter.Bump(51)
|
||||
err = routePanelAnalyticsLanguageViews(w,req,user,extraData)
|
||||
case "/panel/analytics/referrer/":
|
||||
counters.RouteViewCounter.Bump(48)
|
||||
counters.RouteViewCounter.Bump(52)
|
||||
err = routePanelAnalyticsReferrerViews(w,req,user,extraData)
|
||||
case "/panel/analytics/posts/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1162,7 +1192,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(49)
|
||||
counters.RouteViewCounter.Bump(53)
|
||||
err = routePanelAnalyticsPosts(w,req,user)
|
||||
case "/panel/analytics/topics/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1171,7 +1201,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(50)
|
||||
counters.RouteViewCounter.Bump(54)
|
||||
err = routePanelAnalyticsTopics(w,req,user)
|
||||
case "/panel/analytics/forums/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1180,16 +1210,16 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(51)
|
||||
counters.RouteViewCounter.Bump(55)
|
||||
err = routePanelAnalyticsForums(w,req,user)
|
||||
case "/panel/groups/":
|
||||
counters.RouteViewCounter.Bump(52)
|
||||
counters.RouteViewCounter.Bump(56)
|
||||
err = routePanelGroups(w,req,user)
|
||||
case "/panel/groups/edit/":
|
||||
counters.RouteViewCounter.Bump(53)
|
||||
counters.RouteViewCounter.Bump(57)
|
||||
err = routePanelGroupsEdit(w,req,user,extraData)
|
||||
case "/panel/groups/edit/perms/":
|
||||
counters.RouteViewCounter.Bump(54)
|
||||
counters.RouteViewCounter.Bump(58)
|
||||
err = routePanelGroupsEditPerms(w,req,user,extraData)
|
||||
case "/panel/groups/edit/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1198,7 +1228,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(55)
|
||||
counters.RouteViewCounter.Bump(59)
|
||||
err = routePanelGroupsEditSubmit(w,req,user,extraData)
|
||||
case "/panel/groups/edit/perms/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1207,7 +1237,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(56)
|
||||
counters.RouteViewCounter.Bump(60)
|
||||
err = routePanelGroupsEditPermsSubmit(w,req,user,extraData)
|
||||
case "/panel/groups/create/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1216,7 +1246,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(57)
|
||||
counters.RouteViewCounter.Bump(61)
|
||||
err = routePanelGroupsCreateSubmit(w,req,user)
|
||||
case "/panel/backups/":
|
||||
err = common.SuperAdminOnly(w,req,user)
|
||||
|
@ -1225,10 +1255,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(58)
|
||||
counters.RouteViewCounter.Bump(62)
|
||||
err = routePanelBackups(w,req,user,extraData)
|
||||
case "/panel/logs/mod/":
|
||||
counters.RouteViewCounter.Bump(59)
|
||||
counters.RouteViewCounter.Bump(63)
|
||||
err = routePanelLogsMod(w,req,user)
|
||||
case "/panel/debug/":
|
||||
err = common.AdminOnly(w,req,user)
|
||||
|
@ -1237,10 +1267,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(60)
|
||||
counters.RouteViewCounter.Bump(64)
|
||||
err = routePanelDebug(w,req,user)
|
||||
default:
|
||||
counters.RouteViewCounter.Bump(61)
|
||||
counters.RouteViewCounter.Bump(65)
|
||||
err = routePanelDashboard(w,req,user)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1255,7 +1285,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(62)
|
||||
counters.RouteViewCounter.Bump(66)
|
||||
err = routes.AccountEditCritical(w,req,user)
|
||||
case "/user/edit/critical/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1270,7 +1300,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(63)
|
||||
counters.RouteViewCounter.Bump(67)
|
||||
err = routeAccountEditCriticalSubmit(w,req,user)
|
||||
case "/user/edit/avatar/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
|
@ -1279,7 +1309,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(64)
|
||||
counters.RouteViewCounter.Bump(68)
|
||||
err = routeAccountEditAvatar(w,req,user)
|
||||
case "/user/edit/avatar/submit/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
|
@ -1299,7 +1329,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(65)
|
||||
counters.RouteViewCounter.Bump(69)
|
||||
err = routeAccountEditAvatarSubmit(w,req,user)
|
||||
case "/user/edit/username/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
|
@ -1308,7 +1338,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(66)
|
||||
counters.RouteViewCounter.Bump(70)
|
||||
err = routeAccountEditUsername(w,req,user)
|
||||
case "/user/edit/username/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1323,7 +1353,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(67)
|
||||
counters.RouteViewCounter.Bump(71)
|
||||
err = routeAccountEditUsernameSubmit(w,req,user)
|
||||
case "/user/edit/email/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
|
@ -1332,7 +1362,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(68)
|
||||
counters.RouteViewCounter.Bump(72)
|
||||
err = routeAccountEditEmail(w,req,user)
|
||||
case "/user/edit/token/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1347,11 +1377,11 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(69)
|
||||
counters.RouteViewCounter.Bump(73)
|
||||
err = routeAccountEditEmailTokenSubmit(w,req,user,extraData)
|
||||
default:
|
||||
req.URL.Path += extraData
|
||||
counters.RouteViewCounter.Bump(70)
|
||||
counters.RouteViewCounter.Bump(74)
|
||||
err = routes.ViewProfile(w,req,user)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1372,7 +1402,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(71)
|
||||
counters.RouteViewCounter.Bump(75)
|
||||
err = routes.BanUserSubmit(w,req,user,extraData)
|
||||
case "/users/unban/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1387,7 +1417,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(72)
|
||||
counters.RouteViewCounter.Bump(76)
|
||||
err = routes.UnbanUser(w,req,user,extraData)
|
||||
case "/users/activate/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1402,7 +1432,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(73)
|
||||
counters.RouteViewCounter.Bump(77)
|
||||
err = routes.ActivateUser(w,req,user,extraData)
|
||||
case "/users/ips/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
|
@ -1411,7 +1441,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(74)
|
||||
counters.RouteViewCounter.Bump(78)
|
||||
err = routes.IPSearch(w,req,user)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1437,7 +1467,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(75)
|
||||
counters.RouteViewCounter.Bump(79)
|
||||
err = routes.CreateTopicSubmit(w,req,user)
|
||||
case "/topic/edit/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1452,7 +1482,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(76)
|
||||
counters.RouteViewCounter.Bump(80)
|
||||
err = routes.EditTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/delete/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1468,7 +1498,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
req.URL.Path += extraData
|
||||
counters.RouteViewCounter.Bump(77)
|
||||
counters.RouteViewCounter.Bump(81)
|
||||
err = routes.DeleteTopicSubmit(w,req,user)
|
||||
case "/topic/stick/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1483,7 +1513,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(78)
|
||||
counters.RouteViewCounter.Bump(82)
|
||||
err = routes.StickTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/unstick/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1498,7 +1528,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(79)
|
||||
counters.RouteViewCounter.Bump(83)
|
||||
err = routes.UnstickTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/lock/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1514,7 +1544,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
req.URL.Path += extraData
|
||||
counters.RouteViewCounter.Bump(80)
|
||||
counters.RouteViewCounter.Bump(84)
|
||||
err = routes.LockTopicSubmit(w,req,user)
|
||||
case "/topic/unlock/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1529,7 +1559,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(81)
|
||||
counters.RouteViewCounter.Bump(85)
|
||||
err = routes.UnlockTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/move/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1544,7 +1574,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(82)
|
||||
counters.RouteViewCounter.Bump(86)
|
||||
err = routes.MoveTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/like/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1565,10 +1595,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(83)
|
||||
counters.RouteViewCounter.Bump(87)
|
||||
err = routeLikeTopicSubmit(w,req,user,extraData)
|
||||
default:
|
||||
counters.RouteViewCounter.Bump(84)
|
||||
counters.RouteViewCounter.Bump(88)
|
||||
err = routes.ViewTopic(w,req,user, extraData)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1594,7 +1624,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(85)
|
||||
counters.RouteViewCounter.Bump(89)
|
||||
err = routes.CreateReplySubmit(w,req,user)
|
||||
case "/reply/edit/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1609,7 +1639,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(86)
|
||||
counters.RouteViewCounter.Bump(90)
|
||||
err = routes.ReplyEditSubmit(w,req,user,extraData)
|
||||
case "/reply/delete/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1624,7 +1654,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(87)
|
||||
counters.RouteViewCounter.Bump(91)
|
||||
err = routes.ReplyDeleteSubmit(w,req,user,extraData)
|
||||
case "/reply/like/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1645,7 +1675,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(88)
|
||||
counters.RouteViewCounter.Bump(92)
|
||||
err = routeReplyLikeSubmit(w,req,user,extraData)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1666,7 +1696,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(89)
|
||||
counters.RouteViewCounter.Bump(93)
|
||||
err = routeProfileReplyCreateSubmit(w,req,user)
|
||||
case "/profile/reply/edit/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1681,7 +1711,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(90)
|
||||
counters.RouteViewCounter.Bump(94)
|
||||
err = routes.ProfileReplyEditSubmit(w,req,user,extraData)
|
||||
case "/profile/reply/delete/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1696,7 +1726,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(91)
|
||||
counters.RouteViewCounter.Bump(95)
|
||||
err = routes.ProfileReplyDeleteSubmit(w,req,user,extraData)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1717,10 +1747,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(92)
|
||||
counters.RouteViewCounter.Bump(96)
|
||||
err = routes.PollVote(w,req,user,extraData)
|
||||
case "/poll/results/":
|
||||
counters.RouteViewCounter.Bump(93)
|
||||
counters.RouteViewCounter.Bump(97)
|
||||
err = routes.PollResults(w,req,user,extraData)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1729,10 +1759,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
case "/accounts":
|
||||
switch(req.URL.Path) {
|
||||
case "/accounts/login/":
|
||||
counters.RouteViewCounter.Bump(94)
|
||||
counters.RouteViewCounter.Bump(98)
|
||||
err = routes.AccountLogin(w,req,user)
|
||||
case "/accounts/create/":
|
||||
counters.RouteViewCounter.Bump(95)
|
||||
counters.RouteViewCounter.Bump(99)
|
||||
err = routes.AccountRegister(w,req,user)
|
||||
case "/accounts/logout/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
|
@ -1747,7 +1777,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(96)
|
||||
counters.RouteViewCounter.Bump(100)
|
||||
err = routeLogout(w,req,user)
|
||||
case "/accounts/login/submit/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1756,7 +1786,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(97)
|
||||
counters.RouteViewCounter.Bump(101)
|
||||
err = routes.AccountLoginSubmit(w,req,user)
|
||||
case "/accounts/create/submit/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
|
@ -1765,7 +1795,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(98)
|
||||
counters.RouteViewCounter.Bump(102)
|
||||
err = routes.AccountRegisterSubmit(w,req,user)
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1782,7 +1812,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
common.NotFound(w,req,nil)
|
||||
return
|
||||
}
|
||||
counters.RouteViewCounter.Bump(100)
|
||||
counters.RouteViewCounter.Bump(104)
|
||||
req.URL.Path += extraData
|
||||
// TODO: Find a way to propagate errors up from this?
|
||||
router.UploadHandler(w,req) // TODO: Count these views
|
||||
|
@ -1791,14 +1821,14 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
// TODO: Add support for favicons and robots.txt files
|
||||
switch(extraData) {
|
||||
case "robots.txt":
|
||||
counters.RouteViewCounter.Bump(102)
|
||||
counters.RouteViewCounter.Bump(106)
|
||||
err = routes.RobotsTxt(w,req)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
}
|
||||
return
|
||||
/*case "sitemap.xml":
|
||||
counters.RouteViewCounter.Bump(103)
|
||||
counters.RouteViewCounter.Bump(107)
|
||||
err = routes.SitemapXml(w,req)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
|
@ -1827,7 +1857,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
router.RUnlock()
|
||||
|
||||
if ok {
|
||||
counters.RouteViewCounter.Bump(99) // TODO: Be more specific about *which* dynamic route it is
|
||||
counters.RouteViewCounter.Bump(103) // TODO: Be more specific about *which* dynamic route it is
|
||||
req.URL.Path += extraData
|
||||
err = handle(w,req,user)
|
||||
if err != nil {
|
||||
|
@ -1842,7 +1872,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
} else {
|
||||
router.DumpRequest(req,"Bad Route")
|
||||
}
|
||||
counters.RouteViewCounter.Bump(104)
|
||||
counters.RouteViewCounter.Bump(108)
|
||||
common.NotFound(w,req,nil)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,17 +2,18 @@
|
|||
package main
|
||||
|
||||
var dbTablePrimaryKeys = map[string]string{
|
||||
"users":"uid",
|
||||
"topics":"tid",
|
||||
"revisions":"reviseID",
|
||||
"polls":"pollID",
|
||||
"users_replies":"rid",
|
||||
"activity_stream":"asid",
|
||||
"word_filters":"wfid",
|
||||
"users_groups":"gid",
|
||||
"users_groups_scheduler":"uid",
|
||||
"forums":"fid",
|
||||
"users_replies":"rid",
|
||||
"topics":"tid",
|
||||
"replies":"rid",
|
||||
"attachments":"attachID",
|
||||
"revisions":"reviseID",
|
||||
"activity_stream":"asid",
|
||||
"word_filters":"wfid",
|
||||
"menus":"mid",
|
||||
"users":"uid",
|
||||
"menu_items":"miid",
|
||||
"forums":"fid",
|
||||
"attachments":"attachID",
|
||||
"polls":"pollID",
|
||||
}
|
||||
|
|
|
@ -93,6 +93,8 @@
|
|||
"panel_groups":"Group Manager",
|
||||
"panel_edit_group":"Group Editor",
|
||||
"panel_themes":"Theme Manager",
|
||||
"panel_themes_menus":"Menu Manager",
|
||||
"panel_themes_menus_edit":"Menu Editor",
|
||||
"panel_backups":"Backups",
|
||||
"panel_mod_logs":"Moderation Logs",
|
||||
"panel_admin_logs":"Administration Logs",
|
||||
|
@ -246,6 +248,66 @@
|
|||
},
|
||||
|
||||
"TmplPhrases": {
|
||||
"pipe":"|",
|
||||
|
||||
"menu_forums":"Forums",
|
||||
"menu_topics":"Topics",
|
||||
"menu_alerts":"Alerts",
|
||||
"menu_account":"Account",
|
||||
"menu_profile":"Profile",
|
||||
"menu_panel":"Panel",
|
||||
"menu_logout":"Logout",
|
||||
"menu_login":"Login",
|
||||
"menu_register":"Register",
|
||||
|
||||
"topics_click_topics_to_select":"Click the topics to select them",
|
||||
"topics_new_topic":"New Topic",
|
||||
"forum_locked":"Locked",
|
||||
"topics_replies_suffix":" replies",
|
||||
"forums_topics_suffix":" topics",
|
||||
"topics_gap_likes_suffix":" likes",
|
||||
"topics_likes_suffix":"likes",
|
||||
"topics_last":"Last",
|
||||
"topics_starter":"Starter",
|
||||
"topic_like_count_suffix":" likes",
|
||||
"topic_plus":"+",
|
||||
"topic_plus_one":"+1",
|
||||
"topic_gap_up":" up",
|
||||
"topic_level":"Level",
|
||||
"topic_edit_button_text":"Edit",
|
||||
"topic_delete_button_text":"Delete",
|
||||
"topic_ip_button_text":"IP",
|
||||
"topic_lock_button_text":"Lock",
|
||||
"topic_unlock_button_text":"Unlock",
|
||||
"topic_pin_button_text":"Pin",
|
||||
"topic_unpin_button_text":"Unpin",
|
||||
"topic_report_button_text":"Report",
|
||||
"topic_flag_button_text":"Flag",
|
||||
|
||||
"panel_rank_admins":"Admins",
|
||||
"panel_rank_mods":"Mods",
|
||||
"panel_rank_banned":"Banned",
|
||||
"panel_rank_guests":"Guests",
|
||||
"panel_rank_members":"Members",
|
||||
|
||||
"panel_preset_announcements":"Announcements",
|
||||
"panel_preset_member_only":"Member Only",
|
||||
"panel_preset_staff_only":"Staff Only",
|
||||
"panel_preset_admin_only":"Admin Only",
|
||||
"panel_preset_archive":"Archive",
|
||||
"panel_preset_public":"Public",
|
||||
"panel_active_hidden":"Hidden",
|
||||
|
||||
"panel_perms_no_access":"No Access",
|
||||
"panel_perms_read_only":"Read Only",
|
||||
"panel_perms_can_post":"Can Post",
|
||||
"panel_perms_can_moderate":"Can Moderate",
|
||||
"panel_perms_custom":"Custom",
|
||||
"panel_perms_default":"Default",
|
||||
|
||||
"panel_edit_button_text":"Edit",
|
||||
"panel_delete_button_text":"Delete",
|
||||
|
||||
"menu_forums_tooltip":"Forum List",
|
||||
"menu_forums_aria":"The Forum list",
|
||||
"menu_topics_tooltip":"Topic List",
|
||||
|
@ -639,6 +701,25 @@
|
|||
"panel_themes_default":"Default",
|
||||
"panel_themes_make_default":"Make Default",
|
||||
|
||||
"panel_themes_menus_head":"Menus",
|
||||
|
||||
"panel_themes_menus_edit_head":"Menu Editor",
|
||||
"panel_themes_menus_name":"Name",
|
||||
"panel_themes_menus_htmlid":"HTML ID",
|
||||
"panel_themes_menus_cssclass":"CSS Class",
|
||||
"panel_themes_menus_position":"Position",
|
||||
"panel_themes_menus_path":"Path",
|
||||
"panel_themes_menus_aria":"Aria",
|
||||
"panel_themes_menus_tooltip":"Tooltip",
|
||||
"panel_themes_menus_tmplname":"Template",
|
||||
"panel_themes_menus_permissions":"Who Can See",
|
||||
"panel_themes_menus_everyone": "Everyone",
|
||||
"panel_themes_menus_guestonly":"Guests",
|
||||
"panel_themes_menus_memberonly":"Members",
|
||||
"panel_themes_menus_supermodonly":"Super Mods",
|
||||
"panel_themes_menus_adminonly":"Admins",
|
||||
"panel_themes_menus_edit_update_button":"Update",
|
||||
|
||||
"panel_settings_head":"Settings",
|
||||
"panel_setting_head":"Edit Setting",
|
||||
"panel_setting_name":"Setting Name",
|
||||
|
@ -654,67 +735,5 @@
|
|||
"panel_debug_uptime_label":"Uptime",
|
||||
"panel_debug_open_database_connections_label":"Open DB Conns",
|
||||
"panel_debug_adapter_label":"Adapter"
|
||||
},
|
||||
|
||||
"CSSPhrases": {
|
||||
"pipe":"|",
|
||||
|
||||
"menu_forums":"Forums",
|
||||
"menu_topics":"Topics",
|
||||
"menu_alerts":"Alerts",
|
||||
"menu_account":"Account",
|
||||
"menu_profile":"Profile",
|
||||
"menu_panel":"Panel",
|
||||
"menu_logout":"Logout",
|
||||
"menu_login":"Login",
|
||||
"menu_register":"Register",
|
||||
|
||||
"topics_click_topics_to_select":"Click the topics to select them",
|
||||
"topics_new_topic":"New Topic",
|
||||
"forum_locked":"Locked",
|
||||
"topics_replies_suffix":" replies",
|
||||
"forums_topics_suffix":" topics",
|
||||
"topics_gap_likes_suffix":" likes",
|
||||
"topics_likes_suffix":"likes",
|
||||
"topics_last":"Last",
|
||||
"topics_starter":"Starter",
|
||||
"topic_like_count_suffix":" likes",
|
||||
"topic_plus":"+",
|
||||
"topic_plus_one":"+1",
|
||||
"topic_gap_up":" up",
|
||||
"topic_level":"Level",
|
||||
"topic_edit_button_text":"Edit",
|
||||
"topic_delete_button_text":"Delete",
|
||||
"topic_ip_button_text":"IP",
|
||||
"topic_lock_button_text":"Lock",
|
||||
"topic_unlock_button_text":"Unlock",
|
||||
"topic_pin_button_text":"Pin",
|
||||
"topic_unpin_button_text":"Unpin",
|
||||
"topic_report_button_text":"Report",
|
||||
"topic_flag_button_text":"Flag",
|
||||
|
||||
"panel_rank_admins":"Admins",
|
||||
"panel_rank_mods":"Mods",
|
||||
"panel_rank_banned":"Banned",
|
||||
"panel_rank_guests":"Guests",
|
||||
"panel_rank_members":"Members",
|
||||
|
||||
"panel_preset_announcements":"Announcements",
|
||||
"panel_preset_member_only":"Member Only",
|
||||
"panel_preset_staff_only":"Staff Only",
|
||||
"panel_preset_admin_only":"Admin Only",
|
||||
"panel_preset_archive":"Archive",
|
||||
"panel_preset_public":"Public",
|
||||
"panel_active_hidden":"Hidden",
|
||||
|
||||
"panel_perms_no_access":"No Access",
|
||||
"panel_perms_read_only":"Read Only",
|
||||
"panel_perms_can_post":"Can Post",
|
||||
"panel_perms_can_moderate":"Can Moderate",
|
||||
"panel_perms_custom":"Custom",
|
||||
"panel_perms_default":"Default",
|
||||
|
||||
"panel_edit_button_text":"Edit",
|
||||
"panel_delete_button_text":"Delete"
|
||||
}
|
||||
}
|
5
main.go
5
main.go
|
@ -78,7 +78,10 @@ func afterDBInit() (err error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
menuHold := common.Menus.Get(1)
|
||||
menuHold, err := common.Menus.Get(1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("menuHold: %+v\n", menuHold)
|
||||
var b bytes.Buffer
|
||||
menuHold.Build(&b, &common.GuestUser)
|
||||
|
|
178
panel_routes.go
178
panel_routes.go
|
@ -47,6 +47,7 @@ func routePanelDashboard(w http.ResponseWriter, r *http.Request, user common.Use
|
|||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
headerVars.Title = common.GetTitlePhrase("panel_dashboard")
|
||||
|
||||
// We won't calculate this on the spot anymore, as the system doesn't seem to like it if we do multiple fetches simultaneously. Should we constantly calculate this on a background thread? Perhaps, the watchdog to scale back heavy features under load? One plus side is that we'd get immediate CPU percentages here instead of waiting it to kick in with WebSockets
|
||||
var cpustr = "Unknown"
|
||||
|
@ -167,7 +168,7 @@ func routePanelDashboard(w http.ResponseWriter, r *http.Request, user common.Use
|
|||
gridElements = append(gridElements, common.GridElement{"dash-postsperuser", "5 posts / user / week", 14, "grid_stat stat_disabled", "", "", "Coming Soon!" /*"The average number of posts made by each active user over the past week"*/})
|
||||
}
|
||||
|
||||
pi := common.PanelDashboardPage{common.GetTitlePhrase("panel_dashboard"), user, headerVars, stats, "dashboard", gridElements}
|
||||
pi := common.PanelDashboardPage{headerVars, stats, "dashboard", gridElements}
|
||||
return panelRenderTemplate("panel_dashboard", w, r, user, &pi)
|
||||
}
|
||||
|
||||
|
@ -2288,13 +2289,14 @@ func routePanelGroupsCreateSubmit(w http.ResponseWriter, r *http.Request, user c
|
|||
}
|
||||
|
||||
func routePanelThemes(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||
header, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageThemes {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
header.Title = common.GetTitlePhrase("panel_themes")
|
||||
|
||||
var pThemeList, vThemeList []*common.Theme
|
||||
for _, theme := range common.Themes {
|
||||
|
@ -2309,7 +2311,7 @@ func routePanelThemes(w http.ResponseWriter, r *http.Request, user common.User)
|
|||
|
||||
}
|
||||
|
||||
pi := common.PanelThemesPage{common.GetTitlePhrase("panel_themes"), user, headerVars, stats, "themes", pThemeList, vThemeList}
|
||||
pi := common.PanelThemesPage{header, stats, "themes", pThemeList, vThemeList}
|
||||
return panelRenderTemplate("panel_themes", w, r, user, &pi)
|
||||
}
|
||||
|
||||
|
@ -2378,6 +2380,176 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user com
|
|||
return nil
|
||||
}
|
||||
|
||||
func routePanelThemesMenus(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
header, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageThemes {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
header.Title = common.GetTitlePhrase("panel_themes_menus")
|
||||
|
||||
var menuList []common.PanelMenuListItem
|
||||
for mid, list := range common.Menus.GetAllMap() {
|
||||
menuList = append(menuList, common.PanelMenuListItem{
|
||||
ID: mid,
|
||||
ItemCount: len(list.List),
|
||||
})
|
||||
}
|
||||
|
||||
pi := common.PanelMenuListPage{header, stats, "themes", menuList}
|
||||
return panelRenderTemplate("panel_themes_menus", w, r, user, &pi)
|
||||
}
|
||||
|
||||
func routePanelThemesMenusEdit(w http.ResponseWriter, r *http.Request, user common.User, smid string) common.RouteError {
|
||||
header, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageThemes {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
// TODO: Something like Menu #1 for the title?
|
||||
header.Title = common.GetTitlePhrase("panel_themes_menus_edit")
|
||||
|
||||
mid, err := strconv.Atoi(smid)
|
||||
if err != nil {
|
||||
return common.LocalError("Invalid integer", w, r, user)
|
||||
}
|
||||
|
||||
menuHold, err := common.Menus.Get(mid)
|
||||
if err == ErrNoRows {
|
||||
return common.NotFound(w, r, header)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
var menuList []common.MenuItem
|
||||
for _, item := range menuHold.List {
|
||||
var menuTmpls = map[string]common.MenuTmpl{
|
||||
item.TmplName: menuHold.Parse(item.Name, []byte("{{.Name}}")),
|
||||
}
|
||||
var renderBuffer [][]byte
|
||||
var variableIndices []int
|
||||
renderBuffer, _ = menuHold.ScanItem(menuTmpls, item, renderBuffer, variableIndices)
|
||||
|
||||
var out string
|
||||
for _, renderItem := range renderBuffer {
|
||||
out += string(renderItem)
|
||||
}
|
||||
item.Name = out
|
||||
if item.Name == "" {
|
||||
item.Name = "???"
|
||||
}
|
||||
menuList = append(menuList, item)
|
||||
}
|
||||
|
||||
pi := common.PanelMenuPage{header, stats, "themes", mid, menuList}
|
||||
return panelRenderTemplate("panel_themes_menus_items", w, r, user, &pi)
|
||||
}
|
||||
|
||||
func routePanelThemesMenuItemEdit(w http.ResponseWriter, r *http.Request, user common.User, sitemID string) common.RouteError {
|
||||
header, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ManageThemes {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
// TODO: Something like Menu #1 for the title?
|
||||
header.Title = common.GetTitlePhrase("panel_themes_menus_edit")
|
||||
|
||||
itemID, err := strconv.Atoi(sitemID)
|
||||
if err != nil {
|
||||
return common.LocalError("Invalid integer", w, r, user)
|
||||
}
|
||||
|
||||
menuItem, err := common.Menus.ItemStore().Get(itemID)
|
||||
if err == ErrNoRows {
|
||||
return common.NotFound(w, r, header)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
pi := common.PanelMenuItemPage{header, stats, "themes", menuItem}
|
||||
return panelRenderTemplate("panel_themes_menus_item_edit", w, r, user, &pi)
|
||||
}
|
||||
|
||||
func routePanelThemesMenuItemEditSubmit(w http.ResponseWriter, r *http.Request, user common.User, sitemID string) common.RouteError {
|
||||
_, ferr := common.SimplePanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
isJs := (r.PostFormValue("js") == "1")
|
||||
if !user.Perms.ManageThemes {
|
||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||
}
|
||||
|
||||
itemID, err := strconv.Atoi(sitemID)
|
||||
if err != nil {
|
||||
return common.LocalErrorJSQ("Invalid integer", w, r, user, isJs)
|
||||
}
|
||||
|
||||
menuItem, err := common.Menus.ItemStore().Get(itemID)
|
||||
if err == ErrNoRows {
|
||||
return common.LocalErrorJSQ("This item doesn't exist.", w, r, user, isJs)
|
||||
} else if err != nil {
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
//menuItem = menuItem.Copy() // If we switch this for a pointer, we might need this as a scratchpad
|
||||
|
||||
var getItem = func(name string) string {
|
||||
return html.EscapeString(strings.Replace(r.PostFormValue("item-"+name), "\n", "", -1))
|
||||
}
|
||||
menuItem.Name = getItem("name")
|
||||
menuItem.HTMLID = getItem("htmlid")
|
||||
menuItem.CSSClass = getItem("cssclass")
|
||||
menuItem.Position = getItem("position")
|
||||
if menuItem.Position != "left" && menuItem.Position != "right" {
|
||||
menuItem.Position = "left"
|
||||
}
|
||||
menuItem.Path = getItem("path")
|
||||
menuItem.Aria = getItem("aria")
|
||||
menuItem.Tooltip = getItem("tooltip")
|
||||
menuItem.TmplName = getItem("tmplname")
|
||||
|
||||
var perms = getItem("permissions")
|
||||
switch perms {
|
||||
case "everyone":
|
||||
menuItem.GuestOnly = false
|
||||
menuItem.MemberOnly = false
|
||||
menuItem.SuperModOnly = false
|
||||
menuItem.AdminOnly = false
|
||||
case "guest-only":
|
||||
menuItem.GuestOnly = true
|
||||
menuItem.MemberOnly = false
|
||||
menuItem.SuperModOnly = false
|
||||
menuItem.AdminOnly = false
|
||||
case "member-only":
|
||||
menuItem.GuestOnly = false
|
||||
menuItem.MemberOnly = true
|
||||
menuItem.SuperModOnly = false
|
||||
menuItem.AdminOnly = false
|
||||
case "supermod-only":
|
||||
menuItem.GuestOnly = false
|
||||
menuItem.MemberOnly = true
|
||||
menuItem.SuperModOnly = true
|
||||
menuItem.AdminOnly = false
|
||||
case "admin-only":
|
||||
menuItem.GuestOnly = false
|
||||
menuItem.MemberOnly = true
|
||||
menuItem.SuperModOnly = true
|
||||
menuItem.AdminOnly = true
|
||||
}
|
||||
|
||||
err = menuItem.Commit()
|
||||
if err != nil {
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
return panelSuccessRedirect("/panel/themes/menus/item/edit/"+strconv.Itoa(itemID), w, r, isJs)
|
||||
}
|
||||
|
||||
func routePanelBackups(w http.ResponseWriter, r *http.Request, user common.User, backupURL string) common.RouteError {
|
||||
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
|
|
|
@ -26,6 +26,7 @@ func main() {
|
|||
fmt.Println(r)
|
||||
debug.PrintStack()
|
||||
pressAnyKey(scanner)
|
||||
log.Fatal("")
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
@ -73,6 +74,7 @@ type SchemaFile struct {
|
|||
}
|
||||
|
||||
func patcher(scanner *bufio.Scanner) error {
|
||||
fmt.Println("Loading the schema file")
|
||||
data, err := ioutil.ReadFile("./schema/lastSchema.json")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -84,6 +86,8 @@ func patcher(scanner *bufio.Scanner) error {
|
|||
return err
|
||||
}
|
||||
_ = schemaFile
|
||||
|
||||
fmt.Println("Applying the patches")
|
||||
return patch0(scanner)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,18 @@ import (
|
|||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
func patch0(scanner *bufio.Scanner) error {
|
||||
err := execStmt(qgen.Builder.CreateTable("menus", "", "",
|
||||
func patch0(scanner *bufio.Scanner) (err error) {
|
||||
err = execStmt(qgen.Builder.DropTable("menus"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.DropTable("menu_items"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = execStmt(qgen.Builder.CreateTable("menus", "", "",
|
||||
[]qgen.DBTableColumn{
|
||||
qgen.DBTableColumn{"mid", "int", 0, false, true, ""},
|
||||
},
|
||||
|
@ -22,7 +32,9 @@ func patch0(scanner *bufio.Scanner) error {
|
|||
|
||||
err = execStmt(qgen.Builder.CreateTable("menu_items", "", "",
|
||||
[]qgen.DBTableColumn{
|
||||
qgen.DBTableColumn{"miid", "int", 0, false, true, ""},
|
||||
qgen.DBTableColumn{"mid", "int", 0, false, false, ""},
|
||||
qgen.DBTableColumn{"name", "varchar", 200, false, false, ""},
|
||||
qgen.DBTableColumn{"htmlID", "varchar", 200, false, false, "''"},
|
||||
qgen.DBTableColumn{"cssClass", "varchar", 200, false, false, "''"},
|
||||
qgen.DBTableColumn{"position", "varchar", 100, false, false, ""},
|
||||
|
@ -37,7 +49,9 @@ func patch0(scanner *bufio.Scanner) error {
|
|||
qgen.DBTableColumn{"staffOnly", "boolean", 0, false, false, "0"},
|
||||
qgen.DBTableColumn{"adminOnly", "boolean", 0, false, false, "0"},
|
||||
},
|
||||
[]qgen.DBTableKey{},
|
||||
[]qgen.DBTableKey{
|
||||
qgen.DBTableKey{"miid", "primary"},
|
||||
},
|
||||
))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -49,7 +63,7 @@ func patch0(scanner *bufio.Scanner) error {
|
|||
}
|
||||
|
||||
var order int
|
||||
var mOrder = "mid, htmlID, cssClass, position, path, aria, tooltip, guestOnly, memberOnly, staffOnly, adminOnly"
|
||||
var mOrder = "mid, name, htmlID, cssClass, position, path, aria, tooltip, guestOnly, memberOnly, staffOnly, adminOnly"
|
||||
var addMenuItem = func(data map[string]interface{}) error {
|
||||
cols, values := qgen.InterfaceMapToInsertStrings(data, mOrder)
|
||||
err := execStmt(qgen.Builder.SimpleInsert("menu_items", cols+", order", values+","+strconv.Itoa(order)))
|
||||
|
@ -57,12 +71,12 @@ func patch0(scanner *bufio.Scanner) error {
|
|||
return err
|
||||
}
|
||||
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "htmlID": "menu_forums", "position": "left", "path": "/forums/", "aria": "{lang.menu_forums_aria}", "tooltip": "{lang.menu_forums_tooltip}"})
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_forums}", "htmlID": "menu_forums", "position": "left", "path": "/forums/", "aria": "{lang.menu_forums_aria}", "tooltip": "{lang.menu_forums_tooltip}"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "htmlID": "menu_topics", "cssClass": "menu_topics", "position": "left", "path": "/topics/", "aria": "{lang.menu_topics_aria}", "tooltip": "{lang.menu_topics_tooltip}"})
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_topics}", "htmlID": "menu_topics", "cssClass": "menu_topics", "position": "left", "path": "/topics/", "aria": "{lang.menu_topics_aria}", "tooltip": "{lang.menu_topics_tooltip}"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -72,35 +86,39 @@ func patch0(scanner *bufio.Scanner) error {
|
|||
return err
|
||||
}
|
||||
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_account", "position": "left", "path": "/user/edit/critical/", "aria": "{lang.menu_account_aria}", "tooltip": "{lang.menu_account_tooltip}", "memberOnly": true})
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_account}", "cssClass": "menu_account", "position": "left", "path": "/user/edit/critical/", "aria": "{lang.menu_account_aria}", "tooltip": "{lang.menu_account_tooltip}", "memberOnly": true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_profile", "position": "left", "path": "{me.Link}", "aria": "{lang.menu_profile_aria}", "tooltip": "{lang.menu_profile_tooltip}", "memberOnly": true})
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_profile}", "cssClass": "menu_profile", "position": "left", "path": "{me.Link}", "aria": "{lang.menu_profile_aria}", "tooltip": "{lang.menu_profile_tooltip}", "memberOnly": true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_panel menu_account", "position": "left", "path": "/panel/", "aria": "{lang.menu_panel_aria}", "tooltip": "{lang.menu_panel_tooltip}", "memberOnly": true, "staffOnly": true})
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_panel}", "cssClass": "menu_panel menu_account", "position": "left", "path": "/panel/", "aria": "{lang.menu_panel_aria}", "tooltip": "{lang.menu_panel_tooltip}", "memberOnly": true, "staffOnly": true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_logout", "position": "left", "path": "/accounts/logout/?session={me.Session}", "aria": "{lang.menu_logout_aria}", "tooltip": "{lang.menu_logout_tooltip}", "memberOnly": true})
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_logout}", "cssClass": "menu_logout", "position": "left", "path": "/accounts/logout/?session={me.Session}", "aria": "{lang.menu_logout_aria}", "tooltip": "{lang.menu_logout_tooltip}", "memberOnly": true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_register", "position": "left", "path": "/accounts/create/", "aria": "{lang.menu_register_aria}", "tooltip": "{lang.menu_register_tooltip}", "guestOnly": true})
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_register}", "cssClass": "menu_register", "position": "left", "path": "/accounts/create/", "aria": "{lang.menu_register_aria}", "tooltip": "{lang.menu_register_tooltip}", "guestOnly": true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_login", "position": "left", "path": "/accounts/login/", "aria": "{lang.menu_login_aria}", "tooltip": "{lang.menu_login_tooltip}", "guestOnly": true})
|
||||
err = addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_login}", "cssClass": "menu_login", "position": "left", "path": "/accounts/login/", "aria": "{lang.menu_login_aria}", "tooltip": "{lang.menu_login_tooltip}", "guestOnly": true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func patch1(scanner *bufio.Scanner) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -96,6 +96,10 @@ func (build *builder) SimpleInnerJoin(table1 string, table2 string, columns stri
|
|||
return build.prepare(build.adapter.SimpleInnerJoin("_builder", table1, table2, columns, joiners, where, orderby, limit))
|
||||
}
|
||||
|
||||
func (build *builder) DropTable(table string) (stmt *sql.Stmt, err error) {
|
||||
return build.prepare(build.adapter.DropTable("_builder", table))
|
||||
}
|
||||
|
||||
func (build *builder) CreateTable(table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (stmt *sql.Stmt, err error) {
|
||||
return build.prepare(build.adapter.CreateTable("_builder", table, charset, collation, columns, keys))
|
||||
}
|
||||
|
|
|
@ -44,6 +44,18 @@ func (adapter *MssqlAdapter) DbVersion() string {
|
|||
return "SELECT CONCAT(SERVERPROPERTY('productversion'), SERVERPROPERTY ('productlevel'), SERVERPROPERTY ('edition'))"
|
||||
}
|
||||
|
||||
func (adapter *MssqlAdapter) DropTable(name string, table string) (string, error) {
|
||||
if name == "" {
|
||||
return "", errors.New("You need a name for this statement")
|
||||
}
|
||||
if table == "" {
|
||||
return "", errors.New("You need a name for this table")
|
||||
}
|
||||
querystr := "DROP TABLE IF EXISTS [" + table + "];"
|
||||
adapter.pushStatement(name, "drop-table", querystr)
|
||||
return querystr, nil
|
||||
}
|
||||
|
||||
// TODO: Convert any remaining stringy types to nvarchar
|
||||
// We may need to change the CreateTable API to better suit Mssql and the other database drivers which are coming up
|
||||
func (adapter *MssqlAdapter) CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error) {
|
||||
|
|
|
@ -61,6 +61,18 @@ func (adapter *MysqlAdapter) DbVersion() string {
|
|||
return "SELECT VERSION()"
|
||||
}
|
||||
|
||||
func (adapter *MysqlAdapter) DropTable(name string, table string) (string, error) {
|
||||
if name == "" {
|
||||
return "", errors.New("You need a name for this statement")
|
||||
}
|
||||
if table == "" {
|
||||
return "", errors.New("You need a name for this table")
|
||||
}
|
||||
querystr := "DROP TABLE IF EXISTS `" + table + "`;"
|
||||
adapter.pushStatement(name, "drop-table", querystr)
|
||||
return querystr, nil
|
||||
}
|
||||
|
||||
func (adapter *MysqlAdapter) CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error) {
|
||||
if name == "" {
|
||||
return "", errors.New("You need a name for this statement")
|
||||
|
|
|
@ -38,9 +38,20 @@ func (adapter *PgsqlAdapter) BuildConn(config map[string]string) (*sql.DB, error
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// TODO: Implement this
|
||||
func (adapter *PgsqlAdapter) DbVersion() string {
|
||||
return ""
|
||||
return "SELECT version()"
|
||||
}
|
||||
|
||||
func (adapter *PgsqlAdapter) DropTable(name string, table string) (string, error) {
|
||||
if name == "" {
|
||||
return "", errors.New("You need a name for this statement")
|
||||
}
|
||||
if table == "" {
|
||||
return "", errors.New("You need a name for this table")
|
||||
}
|
||||
querystr := "DROP TABLE IF EXISTS \"" + table + "\";"
|
||||
adapter.pushStatement(name, "drop-table", querystr)
|
||||
return querystr, nil
|
||||
}
|
||||
|
||||
// TODO: Implement this
|
||||
|
|
|
@ -98,11 +98,13 @@ type DBStmt struct {
|
|||
Type string // create-table, insert, update, delete
|
||||
}
|
||||
|
||||
// TODO: Add the DropTable, TableExists, AddColumn, ColumnExists, and RemoveColumn methods
|
||||
type Adapter interface {
|
||||
GetName() string
|
||||
BuildConn(config map[string]string) (*sql.DB, error)
|
||||
DbVersion() string
|
||||
|
||||
DropTable(name string, table string) (string, error)
|
||||
CreateTable(name string, table string, charset string, collation string, columns []DBTableColumn, keys []DBTableKey) (string, error)
|
||||
SimpleInsert(name string, table string, columns string, fields string) (string, error)
|
||||
SimpleUpdate(name string, table string, set string, where string) (string, error)
|
||||
|
|
|
@ -210,47 +210,34 @@ func seedTables(adapter qgen.Adapter) error {
|
|||
|
||||
qgen.Install.SimpleInsert("replies", "tid, content, parsed_content, createdAt, createdBy, lastUpdated, lastEdit, lastEditBy, ipaddress", "1,'A reply!','A reply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0,'::1'")
|
||||
|
||||
/*
|
||||
Quick Reminder of the HTML layout, so I don't need to flip back and forth between menu_item.html, etc.
|
||||
|
||||
{{range .MenuItems}}
|
||||
<li id="menu_{{.ID}}" class="menu_{{.Position}}"><a href="{{.Path}}" aria-label="{{.Aria}}" title="{{.Tooltip}}"></a></li>
|
||||
{{end}}
|
||||
|
||||
qgen.DBTableColumn{"guestOnly", "boolean", 1, false, false, "0"},
|
||||
qgen.DBTableColumn{"memberOnly", "boolean", 1, false, false, "0"},
|
||||
qgen.DBTableColumn{"staffOnly", "boolean", 1, false, false, "0"},
|
||||
qgen.DBTableColumn{"adminOnly", "boolean", 1, false, false, "0"},
|
||||
*/
|
||||
|
||||
qgen.Install.SimpleInsert("menus", "", "")
|
||||
|
||||
// Go maps have a random iteration order, so we have to do this, otherwise the schema files will become unstable and harder to audit
|
||||
var order = 0
|
||||
var mOrder = "mid, htmlID, cssClass, position, path, aria, tooltip, guestOnly, memberOnly, staffOnly, adminOnly"
|
||||
var mOrder = "mid, name, htmlID, cssClass, position, path, aria, tooltip, guestOnly, memberOnly, staffOnly, adminOnly"
|
||||
var addMenuItem = func(data map[string]interface{}) {
|
||||
cols, values := qgen.InterfaceMapToInsertStrings(data, mOrder)
|
||||
qgen.Install.SimpleInsert("menu_items", cols+", order", values+","+strconv.Itoa(order))
|
||||
order++
|
||||
}
|
||||
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "htmlID": "menu_forums", "position": "left", "path": "/forums/", "aria": "{lang.menu_forums_aria}", "tooltip": "{lang.menu_forums_tooltip}"})
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_forums}", "htmlID": "menu_forums", "position": "left", "path": "/forums/", "aria": "{lang.menu_forums_aria}", "tooltip": "{lang.menu_forums_tooltip}"})
|
||||
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "htmlID": "menu_topics", "cssClass": "menu_topics", "position": "left", "path": "/topics/", "aria": "{lang.menu_topics_aria}", "tooltip": "{lang.menu_topics_tooltip}"})
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_topics}", "htmlID": "menu_topics", "cssClass": "menu_topics", "position": "left", "path": "/topics/", "aria": "{lang.menu_topics_aria}", "tooltip": "{lang.menu_topics_tooltip}"})
|
||||
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "htmlID": "general_alerts", "cssClass": "menu_alerts", "position": "right", "tmplName": "menu_alerts"})
|
||||
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_account", "position": "left", "path": "/user/edit/critical/", "aria": "{lang.menu_account_aria}", "tooltip": "{lang.menu_account_tooltip}", "memberOnly": true})
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_account}", "cssClass": "menu_account", "position": "left", "path": "/user/edit/critical/", "aria": "{lang.menu_account_aria}", "tooltip": "{lang.menu_account_tooltip}", "memberOnly": true})
|
||||
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_profile", "position": "left", "path": "{me.Link}", "aria": "{lang.menu_profile_aria}", "tooltip": "{lang.menu_profile_tooltip}", "memberOnly": true})
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_profile}", "cssClass": "menu_profile", "position": "left", "path": "{me.Link}", "aria": "{lang.menu_profile_aria}", "tooltip": "{lang.menu_profile_tooltip}", "memberOnly": true})
|
||||
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_panel menu_account", "position": "left", "path": "/panel/", "aria": "{lang.menu_panel_aria}", "tooltip": "{lang.menu_panel_tooltip}", "memberOnly": true, "staffOnly": true})
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_panel}", "cssClass": "menu_panel menu_account", "position": "left", "path": "/panel/", "aria": "{lang.menu_panel_aria}", "tooltip": "{lang.menu_panel_tooltip}", "memberOnly": true, "staffOnly": true})
|
||||
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_logout", "position": "left", "path": "/accounts/logout/?session={me.Session}", "aria": "{lang.menu_logout_aria}", "tooltip": "{lang.menu_logout_tooltip}", "memberOnly": true})
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_logout}", "cssClass": "menu_logout", "position": "left", "path": "/accounts/logout/?session={me.Session}", "aria": "{lang.menu_logout_aria}", "tooltip": "{lang.menu_logout_tooltip}", "memberOnly": true})
|
||||
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_register", "position": "left", "path": "/accounts/create/", "aria": "{lang.menu_register_aria}", "tooltip": "{lang.menu_register_tooltip}", "guestOnly": true})
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_register}", "cssClass": "menu_register", "position": "left", "path": "/accounts/create/", "aria": "{lang.menu_register_aria}", "tooltip": "{lang.menu_register_tooltip}", "guestOnly": true})
|
||||
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "cssClass": "menu_login", "position": "left", "path": "/accounts/login/", "aria": "{lang.menu_login_aria}", "tooltip": "{lang.menu_login_tooltip}", "guestOnly": true})
|
||||
addMenuItem(map[string]interface{}{"mid": 1, "name": "{lang.menu_login}", "cssClass": "menu_login", "position": "left", "path": "/accounts/login/", "aria": "{lang.menu_login_aria}", "tooltip": "{lang.menu_login_tooltip}", "guestOnly": true})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -390,6 +390,7 @@ func createTables(adapter qgen.Adapter) error {
|
|||
|
||||
qgen.Install.CreateTable("menu_items", "", "",
|
||||
[]qgen.DBTableColumn{
|
||||
qgen.DBTableColumn{"miid", "int", 0, false, true, ""},
|
||||
qgen.DBTableColumn{"mid", "int", 0, false, false, ""},
|
||||
qgen.DBTableColumn{"htmlID", "varchar", 200, false, false, "''"},
|
||||
qgen.DBTableColumn{"cssClass", "varchar", 200, false, false, "''"},
|
||||
|
@ -405,7 +406,9 @@ func createTables(adapter qgen.Adapter) error {
|
|||
qgen.DBTableColumn{"staffOnly", "boolean", 0, false, false, "0"},
|
||||
qgen.DBTableColumn{"adminOnly", "boolean", 0, false, false, "0"},
|
||||
},
|
||||
[]qgen.DBTableKey{},
|
||||
[]qgen.DBTableKey{
|
||||
qgen.DBTableKey{"miid", "primary"},
|
||||
},
|
||||
)
|
||||
|
||||
/*
|
||||
|
|
|
@ -153,6 +153,10 @@ func buildPanelRoutes() {
|
|||
|
||||
View("routePanelThemes", "/panel/themes/"),
|
||||
Action("routePanelThemesSetDefault", "/panel/themes/default/", "extraData"),
|
||||
View("routePanelThemesMenus", "/panel/themes/menus/"),
|
||||
View("routePanelThemesMenusEdit", "/panel/themes/menus/edit/", "extraData"),
|
||||
View("routePanelThemesMenuItemEdit", "/panel/themes/menus/item/edit/", "extraData"),
|
||||
Action("routePanelThemesMenuItemEditSubmit", "/panel/themes/menus/item/edit/submit/", "extraData"),
|
||||
|
||||
View("routePanelPlugins", "/panel/plugins/"),
|
||||
Action("routePanelPluginsActivate", "/panel/plugins/activate/", "extraData"),
|
||||
|
|
|
@ -29,12 +29,12 @@ INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (6,2,'{"View
|
|||
INSERT INTO [topics] ([title],[content],[parsed_content],[createdAt],[lastReplyAt],[lastReplyBy],[createdBy],[parentID],[ipaddress]) VALUES ('Test Topic','A topic automatically generated by the software.','A topic automatically generated by the software.',GETUTCDATE(),GETUTCDATE(),1,1,2,'::1');
|
||||
INSERT INTO [replies] ([tid],[content],[parsed_content],[createdAt],[createdBy],[lastUpdated],[lastEdit],[lastEditBy],[ipaddress]) VALUES (1,'A reply!','A reply!',GETUTCDATE(),1,GETUTCDATE(),0,0,'::1');
|
||||
INSERT INTO [menus] () VALUES ();
|
||||
INSERT INTO [menu_items] ([mid],[htmlID],[position],[path],[aria],[tooltip],[order]) VALUES (1,'menu_forums','left','/forums/','{lang.menu_forums_aria}','{lang.menu_forums_tooltip}',0);
|
||||
INSERT INTO [menu_items] ([mid],[htmlID],[cssClass],[position],[path],[aria],[tooltip],[order]) VALUES (1,'menu_topics','menu_topics','left','/topics/','{lang.menu_topics_aria}','{lang.menu_topics_tooltip}',1);
|
||||
INSERT INTO [menu_items] ([mid],[name],[htmlID],[position],[path],[aria],[tooltip],[order]) VALUES (1,'{lang.menu_forums}','menu_forums','left','/forums/','{lang.menu_forums_aria}','{lang.menu_forums_tooltip}',0);
|
||||
INSERT INTO [menu_items] ([mid],[name],[htmlID],[cssClass],[position],[path],[aria],[tooltip],[order]) VALUES (1,'{lang.menu_topics}','menu_topics','menu_topics','left','/topics/','{lang.menu_topics_aria}','{lang.menu_topics_tooltip}',1);
|
||||
INSERT INTO [menu_items] ([mid],[htmlID],[cssClass],[position],[tmplName],[order]) VALUES (1,'general_alerts','menu_alerts','right','menu_alerts',2);
|
||||
INSERT INTO [menu_items] ([mid],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'menu_account','left','/user/edit/critical/','{lang.menu_account_aria}','{lang.menu_account_tooltip}',1,3);
|
||||
INSERT INTO [menu_items] ([mid],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'menu_profile','left','{me.Link}','{lang.menu_profile_aria}','{lang.menu_profile_tooltip}',1,4);
|
||||
INSERT INTO [menu_items] ([mid],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[staffOnly],[order]) VALUES (1,'menu_panel menu_account','left','/panel/','{lang.menu_panel_aria}','{lang.menu_panel_tooltip}',1,1,5);
|
||||
INSERT INTO [menu_items] ([mid],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'menu_logout','left','/accounts/logout/?session={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6);
|
||||
INSERT INTO [menu_items] ([mid],[cssClass],[position],[path],[aria],[tooltip],[guestOnly],[order]) VALUES (1,'menu_register','left','/accounts/create/','{lang.menu_register_aria}','{lang.menu_register_tooltip}',1,7);
|
||||
INSERT INTO [menu_items] ([mid],[cssClass],[position],[path],[aria],[tooltip],[guestOnly],[order]) VALUES (1,'menu_login','left','/accounts/login/','{lang.menu_login_aria}','{lang.menu_login_tooltip}',1,8);
|
||||
INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'{lang.menu_account}','menu_account','left','/user/edit/critical/','{lang.menu_account_aria}','{lang.menu_account_tooltip}',1,3);
|
||||
INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'{lang.menu_profile}','menu_profile','left','{me.Link}','{lang.menu_profile_aria}','{lang.menu_profile_tooltip}',1,4);
|
||||
INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[staffOnly],[order]) VALUES (1,'{lang.menu_panel}','menu_panel menu_account','left','/panel/','{lang.menu_panel_aria}','{lang.menu_panel_tooltip}',1,1,5);
|
||||
INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[memberOnly],[order]) VALUES (1,'{lang.menu_logout}','menu_logout','left','/accounts/logout/?session={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6);
|
||||
INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[guestOnly],[order]) VALUES (1,'{lang.menu_register}','menu_register','left','/accounts/create/','{lang.menu_register_aria}','{lang.menu_register_tooltip}',1,7);
|
||||
INSERT INTO [menu_items] ([mid],[name],[cssClass],[position],[path],[aria],[tooltip],[guestOnly],[order]) VALUES (1,'{lang.menu_login}','menu_login','left','/accounts/login/','{lang.menu_login_aria}','{lang.menu_login_tooltip}',1,8);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
CREATE TABLE [menu_items] (
|
||||
[miid] int not null IDENTITY,
|
||||
[mid] int not null,
|
||||
[htmlID] nvarchar (200) DEFAULT '' not null,
|
||||
[cssClass] nvarchar (200) DEFAULT '' not null,
|
||||
|
@ -11,5 +12,6 @@ CREATE TABLE [menu_items] (
|
|||
[guestOnly] bit DEFAULT 0 not null,
|
||||
[memberOnly] bit DEFAULT 0 not null,
|
||||
[staffOnly] bit DEFAULT 0 not null,
|
||||
[adminOnly] bit DEFAULT 0 not null
|
||||
[adminOnly] bit DEFAULT 0 not null,
|
||||
primary key([miid])
|
||||
);
|
|
@ -29,12 +29,12 @@ INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (6,2,'{"ViewT
|
|||
INSERT INTO `topics`(`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`lastReplyBy`,`createdBy`,`parentID`,`ipaddress`) VALUES ('Test Topic','A topic automatically generated by the software.','A topic automatically generated by the software.',UTC_TIMESTAMP(),UTC_TIMESTAMP(),1,1,2,'::1');
|
||||
INSERT INTO `replies`(`tid`,`content`,`parsed_content`,`createdAt`,`createdBy`,`lastUpdated`,`lastEdit`,`lastEditBy`,`ipaddress`) VALUES (1,'A reply!','A reply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0,'::1');
|
||||
INSERT INTO `menus`() VALUES ();
|
||||
INSERT INTO `menu_items`(`mid`,`htmlID`,`position`,`path`,`aria`,`tooltip`,`order`) VALUES (1,'menu_forums','left','/forums/','{lang.menu_forums_aria}','{lang.menu_forums_tooltip}',0);
|
||||
INSERT INTO `menu_items`(`mid`,`htmlID`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`order`) VALUES (1,'menu_topics','menu_topics','left','/topics/','{lang.menu_topics_aria}','{lang.menu_topics_tooltip}',1);
|
||||
INSERT INTO `menu_items`(`mid`,`name`,`htmlID`,`position`,`path`,`aria`,`tooltip`,`order`) VALUES (1,'{lang.menu_forums}','menu_forums','left','/forums/','{lang.menu_forums_aria}','{lang.menu_forums_tooltip}',0);
|
||||
INSERT INTO `menu_items`(`mid`,`name`,`htmlID`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`order`) VALUES (1,'{lang.menu_topics}','menu_topics','menu_topics','left','/topics/','{lang.menu_topics_aria}','{lang.menu_topics_tooltip}',1);
|
||||
INSERT INTO `menu_items`(`mid`,`htmlID`,`cssClass`,`position`,`tmplName`,`order`) VALUES (1,'general_alerts','menu_alerts','right','menu_alerts',2);
|
||||
INSERT INTO `menu_items`(`mid`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'menu_account','left','/user/edit/critical/','{lang.menu_account_aria}','{lang.menu_account_tooltip}',1,3);
|
||||
INSERT INTO `menu_items`(`mid`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'menu_profile','left','{me.Link}','{lang.menu_profile_aria}','{lang.menu_profile_tooltip}',1,4);
|
||||
INSERT INTO `menu_items`(`mid`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`staffOnly`,`order`) VALUES (1,'menu_panel menu_account','left','/panel/','{lang.menu_panel_aria}','{lang.menu_panel_tooltip}',1,1,5);
|
||||
INSERT INTO `menu_items`(`mid`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'menu_logout','left','/accounts/logout/?session={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6);
|
||||
INSERT INTO `menu_items`(`mid`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`guestOnly`,`order`) VALUES (1,'menu_register','left','/accounts/create/','{lang.menu_register_aria}','{lang.menu_register_tooltip}',1,7);
|
||||
INSERT INTO `menu_items`(`mid`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`guestOnly`,`order`) VALUES (1,'menu_login','left','/accounts/login/','{lang.menu_login_aria}','{lang.menu_login_tooltip}',1,8);
|
||||
INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'{lang.menu_account}','menu_account','left','/user/edit/critical/','{lang.menu_account_aria}','{lang.menu_account_tooltip}',1,3);
|
||||
INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'{lang.menu_profile}','menu_profile','left','{me.Link}','{lang.menu_profile_aria}','{lang.menu_profile_tooltip}',1,4);
|
||||
INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`staffOnly`,`order`) VALUES (1,'{lang.menu_panel}','menu_panel menu_account','left','/panel/','{lang.menu_panel_aria}','{lang.menu_panel_tooltip}',1,1,5);
|
||||
INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`memberOnly`,`order`) VALUES (1,'{lang.menu_logout}','menu_logout','left','/accounts/logout/?session={me.Session}','{lang.menu_logout_aria}','{lang.menu_logout_tooltip}',1,6);
|
||||
INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`guestOnly`,`order`) VALUES (1,'{lang.menu_register}','menu_register','left','/accounts/create/','{lang.menu_register_aria}','{lang.menu_register_tooltip}',1,7);
|
||||
INSERT INTO `menu_items`(`mid`,`name`,`cssClass`,`position`,`path`,`aria`,`tooltip`,`guestOnly`,`order`) VALUES (1,'{lang.menu_login}','menu_login','left','/accounts/login/','{lang.menu_login_aria}','{lang.menu_login_tooltip}',1,8);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
CREATE TABLE `menu_items` (
|
||||
`miid` int not null AUTO_INCREMENT,
|
||||
`mid` int not null,
|
||||
`htmlID` varchar(200) DEFAULT '' not null,
|
||||
`cssClass` varchar(200) DEFAULT '' not null,
|
||||
|
@ -11,5 +12,6 @@ CREATE TABLE `menu_items` (
|
|||
`guestOnly` boolean DEFAULT 0 not null,
|
||||
`memberOnly` boolean DEFAULT 0 not null,
|
||||
`staffOnly` boolean DEFAULT 0 not null,
|
||||
`adminOnly` boolean DEFAULT 0 not null
|
||||
`adminOnly` boolean DEFAULT 0 not null,
|
||||
primary key(`miid`)
|
||||
);
|
|
@ -1,4 +1,5 @@
|
|||
CREATE TABLE `menu_items` (
|
||||
`miid` serial not null,
|
||||
`mid` int not null,
|
||||
`htmlID` varchar (200) DEFAULT '' not null,
|
||||
`cssClass` varchar (200) DEFAULT '' not null,
|
||||
|
@ -11,5 +12,6 @@ CREATE TABLE `menu_items` (
|
|||
`guestOnly` boolean DEFAULT 0 not null,
|
||||
`memberOnly` boolean DEFAULT 0 not null,
|
||||
`staffOnly` boolean DEFAULT 0 not null,
|
||||
`adminOnly` boolean DEFAULT 0 not null
|
||||
`adminOnly` boolean DEFAULT 0 not null,
|
||||
primary key(`miid`)
|
||||
);
|
|
@ -1 +1 @@
|
|||
<li id="{{.HTMLID}}" class="menu_{{.Position}} {{.CSSClass}}"><a href="{{.Path}}" aria-label="{{.Aria}}" title="{{.Tooltip}}"></a></li>
|
||||
<li id="{{.HTMLID}}" class="menu_{{.Position}} {{.CSSClass}}"><a href="{{.Path}}" aria-label="{{.Aria}}" title="{{.Tooltip}}">{{.Name}}</a></li>
|
|
@ -24,7 +24,12 @@
|
|||
{{else if eq .Something.Type "bool"}}
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
|
||||
<div class="formitem"><input name="setting-value" type="checkbox"{{if eq .Something.Content "1"}} checked{{end}} /></div>
|
||||
<div class="formitem">
|
||||
<select name="setting-value">
|
||||
<option{{if eq .Something.Content "1"}} selected{{end}} value="1">{{lang "option_yes"}}</option>
|
||||
<option{{if eq .Something.Content "0"}} selected{{end}} value="0">{{lang "option_no"}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{template "header.html" . }}
|
||||
<div class="colstack panel_stack">
|
||||
|
||||
<nav class="colstack_left" aria-label="The control panel menu">
|
||||
<nav class="colstack_left" aria-label="Theme manager menu">
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem"><a href="/panel/themes/">Theme Manager</a></div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
{{template "header.html" . }}
|
||||
<div class="colstack panel_stack">
|
||||
|
||||
<nav class="colstack_left" aria-label="Theme manager menu">
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem"><a href="/panel/themes/">Theme Manager</a></div>
|
||||
</div>
|
||||
<div class="colstack_item rowmenu">
|
||||
<div class="rowitem passive"><a href="/panel/themes/menus/">Menus</a></div>
|
||||
</div>
|
||||
<div class="colstack_item rowmenu">
|
||||
<div class="rowitem passive"><a href="#">Widgets</a></div>
|
||||
</div>
|
||||
{{template "panel-inner-menu.html" . }}
|
||||
</nav>
|
||||
|
||||
<main class="colstack_right">
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem"><h1>{{lang "panel_themes_menus_head"}}</h1></div>
|
||||
</div>
|
||||
<div id="panel_settings" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/themes/menus/edit/{{.ID}}" class="editable_block panel_upshift">#{{.ID}}</a>
|
||||
<a class="panel_compacttext to_right">{{.ItemCount}} items</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
{{template "footer.html" . }}
|
|
@ -0,0 +1,80 @@
|
|||
{{template "header.html" . }}
|
||||
<div class="colstack panel_stack">
|
||||
|
||||
{{/** TODO: Set the order based on the order here **/}}
|
||||
{{/** TODO: Write the backend code and JS code for saving this menu **/}}
|
||||
<nav class="colstack_left" aria-label="Theme manager menu">
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem"><a href="/panel/themes/">Theme Manager</a></div>
|
||||
</div>
|
||||
<div class="colstack_item rowmenu">
|
||||
<div class="rowitem passive"><a href="/panel/themes/menus/">Menus</a></div>
|
||||
</div>
|
||||
<div class="colstack_item rowmenu">
|
||||
<div class="rowitem passive"><a href="#">Widgets</a></div>
|
||||
</div>
|
||||
{{template "panel-inner-menu.html" . }}
|
||||
</nav>
|
||||
<main class="colstack_right">
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem"><h1>{{lang "panel_themes_menus_edit_head"}}</h1></div>
|
||||
</div>
|
||||
<form action="/panel/themes/menus/item/edit/submit/{{.Item.ID}}?session={{.CurrentUser.Session}}" method="post">
|
||||
<div id="panel_themes_menu_item_edit" class="colstack_item">
|
||||
{{/** TODO: Let an admin move a menu item from one menu to another? **/}}
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_name"}}</a></div>
|
||||
<div class="formitem"><input name="item-name" type="text" value="{{.Item.Name}}" /></div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_htmlid"}}</a></div>
|
||||
<div class="formitem"><input name="item-htmlid" type="text" value="{{.Item.HTMLID}}" /></div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_cssclass"}}</a></div>
|
||||
<div class="formitem"><input name="item-cssclass" type="text" value="{{.Item.CSSClass}}" /></div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_position"}}</a></div>
|
||||
<div class="formitem">
|
||||
<select name="item-position">
|
||||
<option{{if eq .Item.Position "left"}} selected{{end}} value="left">left</option>
|
||||
<option{{if eq .Item.Position "right"}} selected{{end}} value="right">right</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_path"}}</a></div>
|
||||
<div class="formitem"><input name="item-path" type="text" value="{{.Item.Path}}" /></div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_aria"}}</a></div>
|
||||
<div class="formitem"><input name="item-aria" type="text" value="{{.Item.Aria}}" /></div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_tooltip"}}</a></div>
|
||||
<div class="formitem"><input name="item-tooltip" type="text" value="{{.Item.Tooltip}}" /></div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_tmplname"}}</a></div>
|
||||
<div class="formitem"><input name="item-tmplname" type="text" value="{{.Item.TmplName}}" /></div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem formlabel"><a>{{lang "panel_themes_menus_permissions"}}</a></div>
|
||||
<div class="formitem"><select name="item-permissions">
|
||||
<option value="everyone">{{lang "panel_themes_menus_everyone" }}</option>
|
||||
<option{{if .Item.GuestOnly}} selected{{end}} value="guest-only">{{lang "panel_themes_menus_guestonly"}}</option>
|
||||
<option{{if .Item.MemberOnly}} selected{{end}} value="member-only">{{lang "panel_themes_menus_memberonly"}}</option>
|
||||
<option{{if .Item.SuperModOnly}} selected{{end}} value="supermod-only">{{lang "panel_themes_menus_supermodonly"}}</option>
|
||||
<option{{if .Item.AdminOnly}} selected{{end}} value="admin-only">{{lang "panel_themes_menus_adminonly"}}</option>
|
||||
</select></div>
|
||||
</div>
|
||||
<div class="formrow">
|
||||
<div class="formitem"><button name="panel-button" class="formbutton">{{lang "panel_themes_menus_edit_update_button"}}</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
|
||||
</div>
|
||||
{{template "footer.html" . }}
|
|
@ -0,0 +1,29 @@
|
|||
{{template "header.html" . }}
|
||||
<div class="colstack panel_stack">
|
||||
<nav class="colstack_left" aria-label="Theme manager menu">
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem"><a href="/panel/themes/">Theme Manager</a></div>
|
||||
</div>
|
||||
<div class="colstack_item rowmenu">
|
||||
<div class="rowitem passive"><a href="/panel/themes/menus/">Menus</a></div>
|
||||
</div>
|
||||
<div class="colstack_item rowmenu">
|
||||
<div class="rowitem passive"><a href="#">Widgets</a></div>
|
||||
</div>
|
||||
{{template "panel-inner-menu.html" . }}
|
||||
</nav>
|
||||
<main class="colstack_right">
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem"><h1>{{lang "panel_themes_menus_head"}}</h1></div>
|
||||
</div>
|
||||
<div id="panel_settings" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/themes/menus/item/edit/{{.ID}}" class="editable_block panel_upshift">{{.Name}}</a>
|
||||
<a class="panel_compacttext to_right">...</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
{{template "footer.html" . }}
|
|
@ -104,18 +104,12 @@ li {
|
|||
content: "\f03a";
|
||||
margin-right: 6px;
|
||||
}
|
||||
#menu_forums a:after {
|
||||
content: "{{index .Phrases "menu_forums"}}";
|
||||
}
|
||||
.menu_topics a:before {
|
||||
margin-right: 4px;
|
||||
content: "\f27b";
|
||||
position: relative;
|
||||
top: -2px;
|
||||
}
|
||||
.menu_topics a:after {
|
||||
content: "{{index .Phrases "menu_topics"}}";
|
||||
}
|
||||
.menu_alerts {
|
||||
color: var(--primary-link-color);
|
||||
display: flex;
|
||||
|
@ -146,9 +140,6 @@ li {
|
|||
content: "\f2c3";
|
||||
margin-right: 6px;
|
||||
}
|
||||
.menu_account a:after {
|
||||
content: "{{index .Phrases "menu_account"}}";
|
||||
}
|
||||
.menu_profile a:before {
|
||||
content: "\f2c0";
|
||||
margin-right: 5px;
|
||||
|
@ -156,29 +147,14 @@ li {
|
|||
top: -1px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.menu_profile a:after {
|
||||
content: "{{index .Phrases "menu_profile"}}";
|
||||
}
|
||||
.menu_panel a:before {
|
||||
margin-right: 6px;
|
||||
content: "\f108";
|
||||
}
|
||||
.menu_panel a:after {
|
||||
content: "{{index .Phrases "menu_panel"}}";
|
||||
}
|
||||
.menu_logout a:before {
|
||||
content: "\f08b";
|
||||
margin-right: 3px;
|
||||
}
|
||||
.menu_logout a:after {
|
||||
content: "{{index .Phrases "menu_logout"}}";
|
||||
}
|
||||
.menu_login a:after {
|
||||
content: "{{index .Phrases "menu_login"}}";
|
||||
}
|
||||
.menu_register a:after {
|
||||
content: "{{index .Phrases "menu_register"}}";
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
|
|
|
@ -72,31 +72,6 @@ li {
|
|||
padding-top: 13px;
|
||||
}
|
||||
|
||||
#menu_forums a:after {
|
||||
content: "{{index .Phrases "menu_forums"}}";
|
||||
}
|
||||
.menu_topics a:after {
|
||||
content: "{{index .Phrases "menu_topics"}}";
|
||||
}
|
||||
.menu_account a:after {
|
||||
content: "{{index .Phrases "menu_account"}}";
|
||||
}
|
||||
.menu_profile a:after {
|
||||
content: "{{index .Phrases "menu_profile"}}";
|
||||
}
|
||||
.menu_panel a:after {
|
||||
content: "{{index .Phrases "menu_panel"}}";
|
||||
}
|
||||
.menu_logout a:after {
|
||||
content: "{{index .Phrases "menu_logout"}}";
|
||||
}
|
||||
.menu_login a:after {
|
||||
content: "{{index .Phrases "menu_login"}}";
|
||||
}
|
||||
.menu_register a:after {
|
||||
content: "{{index .Phrases "menu_register"}}";
|
||||
}
|
||||
|
||||
.alert_bell {
|
||||
float: right;
|
||||
}
|
||||
|
|
|
@ -61,31 +61,6 @@ li a {
|
|||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#menu_forums a:after {
|
||||
content: "{{index .Phrases "menu_forums"}}";
|
||||
}
|
||||
.menu_topics a:after {
|
||||
content: "{{index .Phrases "menu_topics"}}";
|
||||
}
|
||||
.menu_account a:after {
|
||||
content: "{{index .Phrases "menu_account"}}";
|
||||
}
|
||||
.menu_profile a:after {
|
||||
content: "{{index .Phrases "menu_profile"}}";
|
||||
}
|
||||
.menu_panel a:after {
|
||||
content: "{{index .Phrases "menu_panel"}}";
|
||||
}
|
||||
.menu_logout a:after {
|
||||
content: "{{index .Phrases "menu_logout"}}";
|
||||
}
|
||||
.menu_login a:after {
|
||||
content: "{{index .Phrases "menu_login"}}";
|
||||
}
|
||||
.menu_register a:after {
|
||||
content: "{{index .Phrases "menu_register"}}";
|
||||
}
|
||||
|
||||
.alert_bell:before {
|
||||
content: '🔔︎';
|
||||
}
|
||||
|
|
|
@ -53,31 +53,6 @@ li a {
|
|||
padding-left: 3px;
|
||||
}
|
||||
|
||||
#menu_forums a:after {
|
||||
content: "{{index .Phrases "menu_forums"}}";
|
||||
}
|
||||
.menu_topics a:after {
|
||||
content: "{{index .Phrases "menu_topics"}}";
|
||||
}
|
||||
.menu_account a:after {
|
||||
content: "{{index .Phrases "menu_account"}}";
|
||||
}
|
||||
.menu_profile a:after {
|
||||
content: "{{index .Phrases "menu_profile"}}";
|
||||
}
|
||||
.menu_panel a:after {
|
||||
content: "{{index .Phrases "menu_panel"}}";
|
||||
}
|
||||
.menu_logout a:after {
|
||||
content: "{{index .Phrases "menu_logout"}}";
|
||||
}
|
||||
.menu_login a:after {
|
||||
content: "{{index .Phrases "menu_login"}}";
|
||||
}
|
||||
.menu_register a:after {
|
||||
content: "{{index .Phrases "menu_register"}}";
|
||||
}
|
||||
|
||||
.alert_bell:before {
|
||||
content: '🔔︎';
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue