Begin work on making the analytics panes somewhat usable when having JavaScript disabled.
Very minor refactoring here and there across the software. Save some allocations here and there.
This commit is contained in:
parent
7b09a3aff5
commit
4d9dc76392
|
@ -18,10 +18,11 @@ type DefaultActivityStream struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultActivityStream(acc *qgen.Accumulator) (*DefaultActivityStream, error) {
|
func NewDefaultActivityStream(acc *qgen.Accumulator) (*DefaultActivityStream, error) {
|
||||||
|
as := "activity_stream"
|
||||||
return &DefaultActivityStream{
|
return &DefaultActivityStream{
|
||||||
add: acc.Insert("activity_stream").Columns("actor, targetUser, event, elementType, elementID, createdAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(),
|
add: acc.Insert(as).Columns("actor, targetUser, event, elementType, elementID, createdAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(),
|
||||||
get: acc.Select("activity_stream").Columns("actor, targetUser, event, elementType, elementID, createdAt").Where("asid = ?").Prepare(),
|
get: acc.Select(as).Columns("actor, targetUser, event, elementType, elementID, createdAt").Where("asid = ?").Prepare(),
|
||||||
count: acc.Count("activity_stream").Prepare(),
|
count: acc.Count(as).Prepare(),
|
||||||
}, acc.FirstError()
|
}, acc.FirstError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -224,8 +224,7 @@ func notifyWatchers(asid int) {
|
||||||
}
|
}
|
||||||
uids = append(uids, uid)
|
uids = append(uids, uid)
|
||||||
}
|
}
|
||||||
err = rows.Err()
|
if err = rows.Err(); err != nil {
|
||||||
if err != nil {
|
|
||||||
LogError(err)
|
LogError(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Gosora Authentication Interface
|
* Gosora Authentication Interface
|
||||||
* Copyright Azareal 2017 - 2019
|
* Copyright Azareal 2017 - 2020
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package common
|
package common
|
||||||
|
@ -145,6 +145,7 @@ func (auth *DefaultAuth) ValidateMFAToken(mfaToken string, uid int) error {
|
||||||
if ok {
|
if ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, scratch := range mfaItem.Scratch {
|
for i, scratch := range mfaItem.Scratch {
|
||||||
if subtle.ConstantTimeCompare([]byte(scratch), []byte(mfaToken)) == 1 {
|
if subtle.ConstantTimeCompare([]byte(scratch), []byte(mfaToken)) == 1 {
|
||||||
err = mfaItem.BurnScratch(i)
|
err = mfaItem.BurnScratch(i)
|
||||||
|
@ -155,6 +156,7 @@ func (auth *DefaultAuth) ValidateMFAToken(mfaToken string, uid int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrWrongMFAToken
|
return ErrWrongMFAToken
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,10 @@ type MemoryForumPermsStore struct {
|
||||||
|
|
||||||
func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
|
func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
|
||||||
acc := qgen.NewAcc()
|
acc := qgen.NewAcc()
|
||||||
|
fp := "forums_permissions"
|
||||||
return &MemoryForumPermsStore{
|
return &MemoryForumPermsStore{
|
||||||
getByForum: acc.Select("forums_permissions").Columns("gid, permissions").Where("fid = ?").Orderby("gid ASC").Prepare(),
|
getByForum: acc.Select(fp).Columns("gid, permissions").Where("fid = ?").Orderby("gid ASC").Prepare(),
|
||||||
getByForumGroup: acc.Select("forums_permissions").Columns("permissions").Where("fid = ? AND gid = ?").Prepare(),
|
getByForumGroup: acc.Select(fp).Columns("permissions").Where("fid = ? AND gid = ?").Prepare(),
|
||||||
|
|
||||||
evenForums: make(map[int]map[int]*ForumPerms),
|
evenForums: make(map[int]map[int]*ForumPerms),
|
||||||
oddForums: make(map[int]map[int]*ForumPerms),
|
oddForums: make(map[int]map[int]*ForumPerms),
|
||||||
|
|
|
@ -138,8 +138,9 @@ func (s *MemoryPollCache) RemoveUnsafe(id int) error {
|
||||||
|
|
||||||
// Flush removes all the polls from the cache, useful for tests.
|
// Flush removes all the polls from the cache, useful for tests.
|
||||||
func (s *MemoryPollCache) Flush() {
|
func (s *MemoryPollCache) Flush() {
|
||||||
|
m := make(map[int]*Poll)
|
||||||
s.Lock()
|
s.Lock()
|
||||||
s.items = make(map[int]*Poll)
|
s.items = m
|
||||||
s.length = 0
|
s.length = 0
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,11 @@ var settingStmts SettingStmts
|
||||||
func init() {
|
func init() {
|
||||||
SettingBox.Store(SettingMap(make(map[string]interface{})))
|
SettingBox.Store(SettingMap(make(map[string]interface{})))
|
||||||
DbInits.Add(func(acc *qgen.Accumulator) error {
|
DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||||
|
s := "settings"
|
||||||
settingStmts = SettingStmts{
|
settingStmts = SettingStmts{
|
||||||
getAll: acc.Select("settings").Columns("name, content, type, constraints").Prepare(),
|
getAll: acc.Select(s).Columns("name, content, type, constraints").Prepare(),
|
||||||
get: acc.Select("settings").Columns("content, type, constraints").Where("name = ?").Prepare(),
|
get: acc.Select(s).Columns("content, type, constraints").Where("name = ?").Prepare(),
|
||||||
update: acc.Update("settings").Set("content = ?").Where("name = ?").Prepare(),
|
update: acc.Update(s).Set("content = ?").Where("name = ?").Prepare(),
|
||||||
}
|
}
|
||||||
return acc.FirstError()
|
return acc.FirstError()
|
||||||
})
|
})
|
||||||
|
@ -67,8 +68,8 @@ func LoadSettings() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, setting := range settings {
|
for _, s := range settings {
|
||||||
err = sBox.ParseSetting(setting.Name, setting.Content, setting.Type, setting.Constraint)
|
err = sBox.ParseSetting(s.Name, s.Content, s.Type, s.Constraint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -80,7 +81,7 @@ func LoadSettings() error {
|
||||||
|
|
||||||
// TODO: Add better support for HTML attributes (html-attribute). E.g. Meta descriptions.
|
// TODO: Add better support for HTML attributes (html-attribute). E.g. Meta descriptions.
|
||||||
func (sBox SettingMap) ParseSetting(sname string, scontent string, stype string, constraint string) (err error) {
|
func (sBox SettingMap) ParseSetting(sname string, scontent string, stype string, constraint string) (err error) {
|
||||||
var ssBox = map[string]interface{}(sBox)
|
ssBox := map[string]interface{}(sBox)
|
||||||
switch stype {
|
switch stype {
|
||||||
case "bool":
|
case "bool":
|
||||||
ssBox[sname] = (scontent == "1")
|
ssBox[sname] = (scontent == "1")
|
||||||
|
|
|
@ -88,7 +88,7 @@ func (tList *DefaultTopicList) Tick() error {
|
||||||
canSee[i] = byte(item)
|
canSee[i] = byte(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
var canSeeInt = make([]int, len(canSee))
|
canSeeInt := make([]int, len(canSee))
|
||||||
copy(canSeeInt, group.CanSee)
|
copy(canSeeInt, group.CanSee)
|
||||||
sCanSee := string(canSee)
|
sCanSee := string(canSee)
|
||||||
permTree[sCanSee] = canSeeInt
|
permTree[sCanSee] = canSeeInt
|
||||||
|
@ -161,7 +161,7 @@ func (tList *DefaultTopicList) GetListByCanSee(canSee []int, page int, orderby s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var inSlice = func(haystack []int, needle int) bool {
|
inSlice := func(haystack []int, needle int) bool {
|
||||||
for _, item := range haystack {
|
for _, item := range haystack {
|
||||||
if needle == item {
|
if needle == item {
|
||||||
return true
|
return true
|
||||||
|
@ -200,7 +200,7 @@ func (tList *DefaultTopicList) GetList(page int, orderby string, filterIDs []int
|
||||||
return nil, nil, Paginator{nil, 1, 1}, err
|
return nil, nil, Paginator{nil, 1, 1}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var inSlice = func(haystack []int, needle int) bool {
|
inSlice := func(haystack []int, needle int) bool {
|
||||||
for _, item := range haystack {
|
for _, item := range haystack {
|
||||||
if needle == item {
|
if needle == item {
|
||||||
return true
|
return true
|
||||||
|
@ -282,43 +282,43 @@ func (tList *DefaultTopicList) getList(page int, orderby string, argList []inter
|
||||||
reqUserList := make(map[int]bool)
|
reqUserList := make(map[int]bool)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
// TODO: Embed Topic structs in TopicsRow to make it easier for us to reuse this work in the topic cache
|
// TODO: Embed Topic structs in TopicsRow to make it easier for us to reuse this work in the topic cache
|
||||||
topic := TopicsRow{}
|
t := TopicsRow{}
|
||||||
err := rows.Scan(&topic.ID, &topic.Title, &topic.Content, &topic.CreatedBy, &topic.IsClosed, &topic.Sticky, &topic.CreatedAt, &topic.LastReplyAt, &topic.LastReplyBy, &topic.LastReplyID, &topic.ParentID, &topic.ViewCount, &topic.PostCount, &topic.LikeCount, &topic.AttachCount, &topic.Poll, &topic.Data)
|
err := rows.Scan(&t.ID, &t.Title, &t.Content, &t.CreatedBy, &t.IsClosed, &t.Sticky, &t.CreatedAt, &t.LastReplyAt, &t.LastReplyBy, &t.LastReplyID, &t.ParentID, &t.ViewCount, &t.PostCount, &t.LikeCount, &t.AttachCount, &t.Poll, &t.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Paginator{nil, 1, 1}, err
|
return nil, Paginator{nil, 1, 1}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), topic.ID)
|
t.Link = BuildTopicURL(NameToSlug(t.Title), t.ID)
|
||||||
// TODO: Pass forum to something like topicItem.Forum and use that instead of these two properties? Could be more flexible.
|
// TODO: Pass forum to something like topicItem.Forum and use that instead of these two properties? Could be more flexible.
|
||||||
forum := Forums.DirtyGet(topic.ParentID)
|
forum := Forums.DirtyGet(t.ParentID)
|
||||||
topic.ForumName = forum.Name
|
t.ForumName = forum.Name
|
||||||
topic.ForumLink = forum.Link
|
t.ForumLink = forum.Link
|
||||||
|
|
||||||
// TODO: Create a specialised function with a bit less overhead for getting the last page for a post count
|
// TODO: Create a specialised function with a bit less overhead for getting the last page for a post count
|
||||||
_, _, lastPage := PageOffset(topic.PostCount, 1, Config.ItemsPerPage)
|
_, _, lastPage := PageOffset(t.PostCount, 1, Config.ItemsPerPage)
|
||||||
topic.LastPage = lastPage
|
t.LastPage = lastPage
|
||||||
|
|
||||||
// TODO: Rename this Vhook to better reflect moving the topic list from /routes/ to /common/
|
// TODO: Rename this Vhook to better reflect moving the topic list from /routes/ to /common/
|
||||||
GetHookTable().Vhook("topics_topic_row_assign", &topic, &forum)
|
GetHookTable().Vhook("topics_topic_row_assign", &t, &forum)
|
||||||
topicList = append(topicList, &topic)
|
topicList = append(topicList, &t)
|
||||||
reqUserList[topic.CreatedBy] = true
|
reqUserList[t.CreatedBy] = true
|
||||||
reqUserList[topic.LastReplyBy] = true
|
reqUserList[t.LastReplyBy] = true
|
||||||
|
|
||||||
//log.Print("rlen: ", rlen)
|
//log.Print("rlen: ", rlen)
|
||||||
//log.Print("rcap: ", rcap)
|
//log.Print("rcap: ", rcap)
|
||||||
//log.Print("topic.PostCount: ", topic.PostCount)
|
//log.Print("topic.PostCount: ", t.PostCount)
|
||||||
//log.Print("topic.PostCount == 2 && rlen < rcap: ", topic.PostCount == 2 && rlen < rcap)
|
//log.Print("topic.PostCount == 2 && rlen < rcap: ", topic.PostCount == 2 && rlen < rcap)
|
||||||
|
|
||||||
// Avoid the extra queries on topic list pages, if we already have what we want...
|
// Avoid the extra queries on topic list pages, if we already have what we want...
|
||||||
var hRids = false
|
hRids := false
|
||||||
if tcache != nil {
|
if tcache != nil {
|
||||||
if t, err := tcache.Get(topic.ID); err == nil {
|
if t, err := tcache.Get(t.ID); err == nil {
|
||||||
hRids = len(t.Rids) != 0
|
hRids = len(t.Rids) != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if topic.PostCount == 2 && rlen < rcap && !hRids && page < 5 {
|
if t.PostCount == 2 && rlen < rcap && !hRids && page < 5 {
|
||||||
rids, err := GetRidsForTopic(topic.ID, 0)
|
rids, err := GetRidsForTopic(t.ID, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, Paginator{nil, 1, 1}, err
|
return nil, Paginator{nil, 1, 1}, err
|
||||||
}
|
}
|
||||||
|
@ -329,12 +329,12 @@ func (tList *DefaultTopicList) getList(page int, orderby string, argList []inter
|
||||||
}
|
}
|
||||||
_, _ = Rstore.Get(rids[0])
|
_, _ = Rstore.Get(rids[0])
|
||||||
rlen++
|
rlen++
|
||||||
topic.Rids = []int{rids[0]}
|
t.Rids = []int{rids[0]}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tcache != nil {
|
if tcache != nil {
|
||||||
if _, err := tcache.Get(topic.ID); err == sql.ErrNoRows {
|
if _, err := tcache.Get(t.ID); err == sql.ErrNoRows {
|
||||||
_ = tcache.Set(topic.Topic())
|
_ = tcache.Set(t.Topic())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,7 +344,7 @@ func (tList *DefaultTopicList) getList(page int, orderby string, argList []inter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the user ID map to a slice, then bulk load the users
|
// Convert the user ID map to a slice, then bulk load the users
|
||||||
var idSlice = make([]int, len(reqUserList))
|
idSlice := make([]int, len(reqUserList))
|
||||||
var i int
|
var i int
|
||||||
for userID := range reqUserList {
|
for userID := range reqUserList {
|
||||||
idSlice[i] = userID
|
idSlice[i] = userID
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright Azareal 2017 - 2019 */
|
/* Copyright Azareal 2017 - 2020 */
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -223,6 +223,7 @@ func (h *WsHubImpl) UserCount() (count int) {
|
||||||
h.evenUserLock.RLock()
|
h.evenUserLock.RLock()
|
||||||
count += len(h.evenOnlineUsers)
|
count += len(h.evenOnlineUsers)
|
||||||
h.evenUserLock.RUnlock()
|
h.evenUserLock.RUnlock()
|
||||||
|
|
||||||
h.oddUserLock.RLock()
|
h.oddUserLock.RLock()
|
||||||
count += len(h.oddOnlineUsers)
|
count += len(h.oddOnlineUsers)
|
||||||
h.oddUserLock.RUnlock()
|
h.oddUserLock.RUnlock()
|
||||||
|
@ -236,6 +237,7 @@ func (h *WsHubImpl) HasUser(uid int) (exists bool) {
|
||||||
if exists {
|
if exists {
|
||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
|
|
||||||
h.oddUserLock.RLock()
|
h.oddUserLock.RLock()
|
||||||
_, exists = h.oddOnlineUsers[uid]
|
_, exists = h.oddOnlineUsers[uid]
|
||||||
h.oddUserLock.RUnlock()
|
h.oddUserLock.RUnlock()
|
||||||
|
|
|
@ -100,6 +100,7 @@ func (u *WSUser) AddSocket(conn *websocket.Conn, page string) {
|
||||||
|
|
||||||
func (u *WSUser) RemoveSocket(conn *websocket.Conn) {
|
func (u *WSUser) RemoveSocket(conn *websocket.Conn) {
|
||||||
u.Lock()
|
u.Lock()
|
||||||
|
defer u.Unlock()
|
||||||
if len(u.Sockets) < 6 {
|
if len(u.Sockets) < 6 {
|
||||||
for i, socket := range u.Sockets {
|
for i, socket := range u.Sockets {
|
||||||
if socket == nil {
|
if socket == nil {
|
||||||
|
@ -107,7 +108,6 @@ func (u *WSUser) RemoveSocket(conn *websocket.Conn) {
|
||||||
}
|
}
|
||||||
if socket.conn == conn {
|
if socket.conn == conn {
|
||||||
u.Sockets[i] = nil
|
u.Sockets[i] = nil
|
||||||
u.Unlock()
|
|
||||||
//fmt.Printf("%+v\n", wsUser.Sockets)
|
//fmt.Printf("%+v\n", wsUser.Sockets)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -123,8 +123,6 @@ func (u *WSUser) RemoveSocket(conn *websocket.Conn) {
|
||||||
}
|
}
|
||||||
u.Sockets = append(u.Sockets[:key], u.Sockets[key+1:]...)
|
u.Sockets = append(u.Sockets[:key], u.Sockets[key+1:]...)
|
||||||
//fmt.Printf("%+v\n", u.Sockets)
|
//fmt.Printf("%+v\n", u.Sockets)
|
||||||
|
|
||||||
u.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *WSUser) SetPageForSocket(conn *websocket.Conn, page string) error {
|
func (u *WSUser) SetPageForSocket(conn *websocket.Conn, page string) error {
|
||||||
|
|
|
@ -87,8 +87,8 @@ type Member struct {
|
||||||
User c.User
|
User c.User
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrebuildTmplList(user c.User, header *c.Header) c.CTmpl {
|
func PrebuildTmplList(user c.User, h *c.Header) c.CTmpl {
|
||||||
var guildList = []*Guild{
|
guildList := []*Guild{
|
||||||
&Guild{
|
&Guild{
|
||||||
ID: 1,
|
ID: 1,
|
||||||
Name: "lol",
|
Name: "lol",
|
||||||
|
@ -104,7 +104,7 @@ func PrebuildTmplList(user c.User, header *c.Header) c.CTmpl {
|
||||||
Forums: []*c.Forum{c.Forums.DirtyGet(1)},
|
Forums: []*c.Forum{c.Forums.DirtyGet(1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
listPage := ListPage{"Guild List", user, header, guildList}
|
listPage := ListPage{"Guild List", user, h, guildList}
|
||||||
return c.CTmpl{"guilds_guild_list", "guilds_guild_list.html", "templates/", "guilds.ListPage", listPage, []string{"./extend/guilds/lib"}}
|
return c.CTmpl{"guilds_guild_list", "guilds_guild_list.html", "templates/", "guilds.ListPage", listPage, []string{"./extend/guilds/lib"}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -879,7 +879,7 @@ function mainInit(){
|
||||||
for(let i = 0; i < elems.length; i++) {
|
for(let i = 0; i < elems.length; i++) {
|
||||||
let elem = elems[i];
|
let elem = elems[i];
|
||||||
if(elem.nodeName=="SELECT") {
|
if(elem.nodeName=="SELECT") {
|
||||||
s += elem.name + "=" + elem.options[elem.selectedIndex].getAttribute("val") + "&";
|
s += elem.name + "=" + elem.options[elem.selectedIndex].getAttribute("value") + "&";
|
||||||
}
|
}
|
||||||
// TODO: Implement other element types...
|
// TODO: Implement other element types...
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ type RouteSubset struct {
|
||||||
|
|
||||||
func (set *RouteSubset) Before(lines ...string) *RouteSubset {
|
func (set *RouteSubset) Before(lines ...string) *RouteSubset {
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
for _, route := range set.RouteList {
|
for _, r := range set.RouteList {
|
||||||
route.RunBefore = append(route.RunBefore, Runnable{line, false})
|
r.RunBefore = append(r.RunBefore, Runnable{line, false})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return set
|
return set
|
||||||
|
@ -15,8 +15,8 @@ func (set *RouteSubset) Before(lines ...string) *RouteSubset {
|
||||||
|
|
||||||
func (set *RouteSubset) LitBefore(lines ...string) *RouteSubset {
|
func (set *RouteSubset) LitBefore(lines ...string) *RouteSubset {
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
for _, route := range set.RouteList {
|
for _, r := range set.RouteList {
|
||||||
route.RunBefore = append(route.RunBefore, Runnable{line, true})
|
r.RunBefore = append(r.RunBefore, Runnable{line, true})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return set
|
return set
|
||||||
|
|
|
@ -103,7 +103,7 @@ func SettingEditSubmit(w http.ResponseWriter, r *http.Request, user c.User, snam
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
scontent := c.SanitiseBody(r.PostFormValue("setting-value"))
|
scontent := c.SanitiseBody(r.PostFormValue("value"))
|
||||||
rerr := headerLite.Settings.Update(sname, scontent)
|
rerr := headerLite.Settings.Update(sname, scontent)
|
||||||
if rerr != nil {
|
if rerr != nil {
|
||||||
return rerr
|
return rerr
|
||||||
|
|
|
@ -20,9 +20,7 @@
|
||||||
<div class="rowitem rowmsg" style="white-space:pre-wrap;">{{lang "account_mfa_scratch_explanation"}}</div>
|
<div class="rowitem rowmsg" style="white-space:pre-wrap;">{{lang "account_mfa_scratch_explanation"}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_mfa_scratches" class="colstack_item rowlist">
|
<div id="panel_mfa_scratches" class="colstack_item rowlist">
|
||||||
{{range .Something}}
|
{{range .Something}}<div class="rowitem">{{.}}</div>{{end}}
|
||||||
<div class="rowitem">{{.}}</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
<div class="formitem formlabel"><a>Visibility</a></div>
|
<div class="formitem formlabel"><a>Visibility</a></div>
|
||||||
<div class="formitem">
|
<div class="formitem">
|
||||||
<select name="group_privacy">
|
<select name="group_privacy">
|
||||||
<option val="0">Public</option>
|
<option value=0>Public</option>
|
||||||
<option val="1">Protected</option>
|
<option value=1>Protected</option>
|
||||||
<option val="2">Private</option>
|
<option value=2>Private</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
<div class="rowitem">
|
<div class="rowitem">
|
||||||
<h1>{{lang "panel_statistics_active_memory_head"}}</h1>
|
<h1>{{lang "panel_statistics_active_memory_head"}}</h1>
|
||||||
<select form="timeRangeForm" class="typeSelector to_right autoSubmitRedirect" name="mtype">
|
<select form="timeRangeForm" class="typeSelector to_right autoSubmitRedirect" name="mtype">
|
||||||
<option val="0"{{if eq .MemType 0}} selected{{end}}>{{lang "panel_statistics_memory_type_total"}}</option>
|
<option value="0"{{if eq .MemType 0}} selected{{end}}>{{lang "panel_statistics_memory_type_total"}}</option>
|
||||||
<option val="1"{{if eq .MemType 1}} selected{{end}}>{{lang "panel_statistics_memory_type_stack"}}</option>
|
<option value="1"{{if eq .MemType 1}} selected{{end}}>{{lang "panel_statistics_memory_type_stack"}}</option>
|
||||||
<option val="2"{{if eq .MemType 2}} selected{{end}}>{{lang "panel_statistics_memory_type_heap"}}</option>
|
<option value="2"{{if eq .MemType 2}} selected{{end}}>{{lang "panel_statistics_memory_type_heap"}}</option>
|
||||||
</select>
|
</select>
|
||||||
|
<noscript><input form="timeRangeForm" type="submit" /></noscript>
|
||||||
{{template "panel_analytics_time_range_month.html" . }}
|
{{template "panel_analytics_time_range_month.html" . }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
<div class="rowitem">
|
<div class="rowitem">
|
||||||
<h1>{{lang "panel_statistics_referrers_head"}}</h1>
|
<h1>{{lang "panel_statistics_referrers_head"}}</h1>
|
||||||
<select form="timeRangeForm" class="spamSelector to_right autoSubmitRedirect" name="spam">
|
<select form="timeRangeForm" class="spamSelector to_right autoSubmitRedirect" name="spam">
|
||||||
<option val="0"{{if not .ShowSpam}} selected{{end}}>{{lang "panel_statistics_spam_hide"}}</option>
|
<option value="0"{{if not .ShowSpam}} selected{{end}}>{{lang "panel_statistics_spam_hide"}}</option>
|
||||||
<option val="1"{{if .ShowSpam}} selected{{end}}>{{lang "panel_statistics_spam_show"}}</option>
|
<option value="1"{{if .ShowSpam}} selected{{end}}>{{lang "panel_statistics_spam_show"}}</option>
|
||||||
</select>
|
</select>
|
||||||
|
<noscript><input form="timeRangeForm" type="submit" /></noscript>
|
||||||
{{template "panel_analytics_time_range.html" . }}
|
{{template "panel_analytics_time_range.html" . }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
<select form="timeRangeForm" class="timeRangeSelector to_right autoSubmitRedirect" name="timeRange">
|
<select form="timeRangeForm" class="timeRangeSelector to_right autoSubmitRedirect" name="timeRange">
|
||||||
<option val="one-year"{{if eq .TimeRange "one-year"}} selected{{end}}>{{lang "panel_statistics_time_range_one_year"}}</option>
|
<option value="one-year"{{if eq .TimeRange "one-year"}} selected{{end}}>{{lang "panel_statistics_time_range_one_year"}}</option>
|
||||||
<option val="three-months"{{if eq .TimeRange "three-months"}} selected{{end}}>{{lang "panel_statistics_time_range_three_months"}}</option>
|
<option value="three-months"{{if eq .TimeRange "three-months"}} selected{{end}}>{{lang "panel_statistics_time_range_three_months"}}</option>
|
||||||
<option val="one-month"{{if eq .TimeRange "one-month"}} selected{{end}}>{{lang "panel_statistics_time_range_one_month"}}</option>
|
<option value="one-month"{{if eq .TimeRange "one-month"}} selected{{end}}>{{lang "panel_statistics_time_range_one_month"}}</option>
|
||||||
<option val="one-week"{{if eq .TimeRange "one-week"}} selected{{end}}>{{lang "panel_statistics_time_range_one_week"}}</option>
|
<option value="one-week"{{if eq .TimeRange "one-week"}} selected{{end}}>{{lang "panel_statistics_time_range_one_week"}}</option>
|
||||||
<option val="two-days"{{if eq .TimeRange "two-days"}} selected{{end}}>{{lang "panel_statistics_time_range_two_days"}}</option>
|
<option value="two-days"{{if eq .TimeRange "two-days"}} selected{{end}}>{{lang "panel_statistics_time_range_two_days"}}</option>
|
||||||
<option val="one-day"{{if eq .TimeRange "one-day"}} selected{{end}}>{{lang "panel_statistics_time_range_one_day"}}</option>
|
<option value="one-day"{{if eq .TimeRange "one-day"}} selected{{end}}>{{lang "panel_statistics_time_range_one_day"}}</option>
|
||||||
<option val="twelve-hours"{{if eq .TimeRange "twelve-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_twelve_hours"}}</option>
|
<option value="twelve-hours"{{if eq .TimeRange "twelve-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_twelve_hours"}}</option>
|
||||||
<option val="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_six_hours"}}</option>
|
<option value="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_six_hours"}}</option>
|
||||||
</select>
|
</select>
|
||||||
|
<noscript><input form="timeRangeForm" type="submit" /></noscript>
|
|
@ -1,8 +1,9 @@
|
||||||
<select form="timeRangeForm" class="timeRangeSelector to_right autoSubmitRedirect" name="timeRange">
|
<select form="timeRangeForm" class="timeRangeSelector to_right autoSubmitRedirect" name="timeRange">
|
||||||
<option val="one-month"{{if eq .TimeRange "one-month"}} selected{{end}}>{{lang "panel_statistics_time_range_one_month"}}</option>
|
<option value="one-month"{{if eq .TimeRange "one-month"}} selected{{end}}>{{lang "panel_statistics_time_range_one_month"}}</option>
|
||||||
<option val="one-week"{{if eq .TimeRange "one-week"}} selected{{end}}>{{lang "panel_statistics_time_range_one_week"}}</option>
|
<option value="one-week"{{if eq .TimeRange "one-week"}} selected{{end}}>{{lang "panel_statistics_time_range_one_week"}}</option>
|
||||||
<option val="two-days"{{if eq .TimeRange "two-days"}} selected{{end}}>{{lang "panel_statistics_time_range_two_days"}}</option>
|
<option value="two-days"{{if eq .TimeRange "two-days"}} selected{{end}}>{{lang "panel_statistics_time_range_two_days"}}</option>
|
||||||
<option val="one-day"{{if eq .TimeRange "one-day"}} selected{{end}}>{{lang "panel_statistics_time_range_one_day"}}</option>
|
<option value="one-day"{{if eq .TimeRange "one-day"}} selected{{end}}>{{lang "panel_statistics_time_range_one_day"}}</option>
|
||||||
<option val="twelve-hours"{{if eq .TimeRange "twelve-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_twelve_hours"}}</option>
|
<option value="twelve-hours"{{if eq .TimeRange "twelve-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_twelve_hours"}}</option>
|
||||||
<option val="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_six_hours"}}</option>
|
<option value="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_six_hours"}}</option>
|
||||||
</select>
|
</select>
|
||||||
|
<noscript><input form="timeRangeForm" type="submit" /></noscript>
|
|
@ -7,7 +7,7 @@
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
|
||||||
<div class="formitem">
|
<div class="formitem">
|
||||||
<select name="setting-value">
|
<select name="value">
|
||||||
{{range .ItemList}}<option{{if .Selected}} selected{{end}} value="{{.Value}}">{{.Label}}</option>{{end}}
|
{{range .ItemList}}<option{{if .Selected}} selected{{end}} value="{{.Value}}">{{.Label}}</option>{{end}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,19 +16,19 @@
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
|
||||||
<div class="formitem">
|
<div class="formitem">
|
||||||
<select name="setting-value">
|
<select name="value">
|
||||||
<option{{if eq .Setting.Content "1"}} selected{{end}} value="1">{{lang "option_yes"}}</option>
|
<option{{if eq .Setting.Content "1"}} selected{{end}} value=1>{{lang "option_yes"}}</option>
|
||||||
<option{{if eq .Setting.Content "0"}} selected{{end}} value="0">{{lang "option_no"}}</option>
|
<option{{if eq .Setting.Content "0"}} selected{{end}} value=0>{{lang "option_no"}}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{else if eq .Setting.Type "textarea"}}
|
{{else if eq .Setting.Type "textarea"}}
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem"><textarea name="setting-value">{{.Setting.Content}}</textarea></div>
|
<div class="formitem"><textarea name="value">{{.Setting.Content}}</textarea></div>
|
||||||
</div>
|
</div>
|
||||||
{{else}}<div class="formrow">
|
{{else}}<div class="formrow">
|
||||||
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
|
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
|
||||||
<div class="formitem"><input name="setting-value" type="text" value="{{.Setting.Content}}" /></div>
|
<div class="formitem"><input name="value" type="text" value="{{.Setting.Content}}"/></div>
|
||||||
</div>{{end}}
|
</div>{{end}}
|
||||||
<div class="formrow form_button_row">
|
<div class="formrow form_button_row">
|
||||||
<div class="formitem"><button name="panel-button" class="formbutton">{{lang "panel_setting_update_button"}}</button></div>
|
<div class="formitem"><button name="panel-button" class="formbutton">{{lang "panel_setting_update_button"}}</button></div>
|
||||||
|
|
|
@ -121,5 +121,4 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{{template "footer.html" . }}
|
{{template "footer.html" . }}
|
|
@ -1,9 +1,13 @@
|
||||||
<div class="rowblock topic_reply_container">
|
<div class="rowblock topic_reply_container">
|
||||||
<div class="userinfo" aria-label="{{lang "topic.your_information"}}">
|
<div class="userinfo" aria-label="{{lang "topic.your_information"}}">
|
||||||
<div class="avatar_item" style="background-image:url({{.CurrentUser.Avatar}}),url(/s/white-dot.jpg);background-position:0px -10px;"> </div>
|
<div class="avatar_item" style="background-image:url({{.CurrentUser.Avatar}}),url(/s/white-dot.jpg);"> </div>
|
||||||
<div class="user_meta">
|
<div class="user_meta">
|
||||||
<a href="{{.CurrentUser.Link}}" class="the_name" rel="author">{{.CurrentUser.Name}}</a>
|
<a href="{{.CurrentUser.Link}}" class="the_name" rel="author">{{.CurrentUser.Name}}</a>
|
||||||
{{if .CurrentUser.Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.CurrentUser.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">{{level .CurrentUser.Level}}</div><div class="tag_post"></div></div>{{end}}
|
<div class="tag_block">
|
||||||
|
<div class="tag_pre"></div>
|
||||||
|
{{if .CurrentUser.Tag}}<div class="post_tag">{{.CurrentUser.Tag}}</div>{{else}}<div class="post_tag post_level">{{level .CurrentUser.Level}}</div>{{end}}
|
||||||
|
<div class="tag_post"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock topic_reply_form quick_create_form" aria-label="{{lang "topic.reply_aria"}}">
|
<div class="rowblock topic_reply_form quick_create_form" aria-label="{{lang "topic.reply_aria"}}">
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<div class="userinfo" aria-label="{{lang "topic.userinfo_aria"}}">
|
<div class="userinfo" aria-label="{{lang "topic.userinfo_aria"}}">
|
||||||
<div class="avatar_item" style="background-image:url({{.Avatar}}), url(/s/white-dot.jpg);background-position:0px -10px;"> </div>
|
<div class="avatar_item" style="background-image:url({{.Avatar}}),url(/s/white-dot.jpg);"> </div>
|
||||||
<div class="user_meta">
|
<div class="user_meta">
|
||||||
<a href="{{.UserLink}}" class="the_name" rel="author">{{.CreatedByName}}</a>
|
<a href="{{.UserLink}}" class="the_name" rel="author">{{.CreatedByName}}</a>
|
||||||
{{if .Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">{{level .Level}}</div><div class="tag_post"></div></div>{{end}}
|
<div class="tag_block">
|
||||||
|
<div class="tag_pre"></div>
|
||||||
|
{{if .Tag}}<div class="post_tag">{{.Tag}}</div>{{else}}<div class="post_tag post_level">{{level .Level}}</div>{{end}}
|
||||||
|
<div class="tag_post"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1059,6 +1059,7 @@ blockquote:first-child {
|
||||||
width: 84px;
|
width: 84px;
|
||||||
height: 84px;
|
height: 84px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
background-position: 0px -10px;
|
||||||
background-size: 120px;
|
background-size: 120px;
|
||||||
}
|
}
|
||||||
.the_name, .userinfo .tag_block {
|
.the_name, .userinfo .tag_block {
|
||||||
|
|
|
@ -837,6 +837,7 @@ blockquote:first-child {
|
||||||
border-radius: 36px;
|
border-radius: 36px;
|
||||||
height: 58px;
|
height: 58px;
|
||||||
width: 58px;
|
width: 58px;
|
||||||
|
background-position: 0px -10px;
|
||||||
background-size: 78px;
|
background-size: 78px;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
|
Loading…
Reference in New Issue