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:
Azareal 2019-10-28 09:13:24 +10:00
parent 7b09a3aff5
commit 4d9dc76392
35 changed files with 126 additions and 110 deletions

View File

@ -18,10 +18,11 @@ type DefaultActivityStream struct {
}
func NewDefaultActivityStream(acc *qgen.Accumulator) (*DefaultActivityStream, error) {
as := "activity_stream"
return &DefaultActivityStream{
add: acc.Insert("activity_stream").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(),
count: acc.Count("activity_stream").Prepare(),
add: acc.Insert(as).Columns("actor, targetUser, event, elementType, elementID, createdAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(),
get: acc.Select(as).Columns("actor, targetUser, event, elementType, elementID, createdAt").Where("asid = ?").Prepare(),
count: acc.Count(as).Prepare(),
}, acc.FirstError()
}

View File

@ -224,8 +224,7 @@ func notifyWatchers(asid int) {
}
uids = append(uids, uid)
}
err = rows.Err()
if err != nil {
if err = rows.Err(); err != nil {
LogError(err)
return
}

View File

@ -1,7 +1,7 @@
/*
*
* Gosora Authentication Interface
* Copyright Azareal 2017 - 2019
* Copyright Azareal 2017 - 2020
*
*/
package common
@ -145,6 +145,7 @@ func (auth *DefaultAuth) ValidateMFAToken(mfaToken string, uid int) error {
if ok {
return nil
}
for i, scratch := range mfaItem.Scratch {
if subtle.ConstantTimeCompare([]byte(scratch), []byte(mfaToken)) == 1 {
err = mfaItem.BurnScratch(i)
@ -155,6 +156,7 @@ func (auth *DefaultAuth) ValidateMFAToken(mfaToken string, uid int) error {
return nil
}
}
return ErrWrongMFAToken
}

View File

@ -34,9 +34,10 @@ type MemoryForumPermsStore struct {
func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
acc := qgen.NewAcc()
fp := "forums_permissions"
return &MemoryForumPermsStore{
getByForum: acc.Select("forums_permissions").Columns("gid, permissions").Where("fid = ?").Orderby("gid ASC").Prepare(),
getByForumGroup: acc.Select("forums_permissions").Columns("permissions").Where("fid = ? AND gid = ?").Prepare(),
getByForum: acc.Select(fp).Columns("gid, permissions").Where("fid = ?").Orderby("gid ASC").Prepare(),
getByForumGroup: acc.Select(fp).Columns("permissions").Where("fid = ? AND gid = ?").Prepare(),
evenForums: make(map[int]map[int]*ForumPerms),
oddForums: make(map[int]map[int]*ForumPerms),

View File

@ -138,8 +138,9 @@ func (s *MemoryPollCache) RemoveUnsafe(id int) error {
// Flush removes all the polls from the cache, useful for tests.
func (s *MemoryPollCache) Flush() {
m := make(map[int]*Poll)
s.Lock()
s.items = make(map[int]*Poll)
s.items = m
s.length = 0
s.Unlock()
}

View File

@ -45,10 +45,11 @@ var settingStmts SettingStmts
func init() {
SettingBox.Store(SettingMap(make(map[string]interface{})))
DbInits.Add(func(acc *qgen.Accumulator) error {
s := "settings"
settingStmts = SettingStmts{
getAll: acc.Select("settings").Columns("name, content, type, constraints").Prepare(),
get: acc.Select("settings").Columns("content, type, constraints").Where("name = ?").Prepare(),
update: acc.Update("settings").Set("content = ?").Where("name = ?").Prepare(),
getAll: acc.Select(s).Columns("name, content, type, constraints").Prepare(),
get: acc.Select(s).Columns("content, type, constraints").Where("name = ?").Prepare(),
update: acc.Update(s).Set("content = ?").Where("name = ?").Prepare(),
}
return acc.FirstError()
})
@ -67,8 +68,8 @@ func LoadSettings() error {
return err
}
for _, setting := range settings {
err = sBox.ParseSetting(setting.Name, setting.Content, setting.Type, setting.Constraint)
for _, s := range settings {
err = sBox.ParseSetting(s.Name, s.Content, s.Type, s.Constraint)
if err != nil {
return err
}
@ -80,7 +81,7 @@ func LoadSettings() error {
// 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) {
var ssBox = map[string]interface{}(sBox)
ssBox := map[string]interface{}(sBox)
switch stype {
case "bool":
ssBox[sname] = (scontent == "1")

View File

@ -88,7 +88,7 @@ func (tList *DefaultTopicList) Tick() error {
canSee[i] = byte(item)
}
var canSeeInt = make([]int, len(canSee))
canSeeInt := make([]int, len(canSee))
copy(canSeeInt, group.CanSee)
sCanSee := string(canSee)
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 {
if needle == item {
return true
@ -200,7 +200,7 @@ func (tList *DefaultTopicList) GetList(page int, orderby string, filterIDs []int
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 {
if needle == item {
return true
@ -282,43 +282,43 @@ func (tList *DefaultTopicList) getList(page int, orderby string, argList []inter
reqUserList := make(map[int]bool)
for rows.Next() {
// TODO: Embed Topic structs in TopicsRow to make it easier for us to reuse this work in the topic cache
topic := 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)
t := TopicsRow{}
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 {
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.
forum := Forums.DirtyGet(topic.ParentID)
topic.ForumName = forum.Name
topic.ForumLink = forum.Link
forum := Forums.DirtyGet(t.ParentID)
t.ForumName = forum.Name
t.ForumLink = forum.Link
// 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)
topic.LastPage = lastPage
_, _, lastPage := PageOffset(t.PostCount, 1, Config.ItemsPerPage)
t.LastPage = lastPage
// TODO: Rename this Vhook to better reflect moving the topic list from /routes/ to /common/
GetHookTable().Vhook("topics_topic_row_assign", &topic, &forum)
topicList = append(topicList, &topic)
reqUserList[topic.CreatedBy] = true
reqUserList[topic.LastReplyBy] = true
GetHookTable().Vhook("topics_topic_row_assign", &t, &forum)
topicList = append(topicList, &t)
reqUserList[t.CreatedBy] = true
reqUserList[t.LastReplyBy] = true
//log.Print("rlen: ", rlen)
//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)
// Avoid the extra queries on topic list pages, if we already have what we want...
var hRids = false
hRids := false
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
}
}
if topic.PostCount == 2 && rlen < rcap && !hRids && page < 5 {
rids, err := GetRidsForTopic(topic.ID, 0)
if t.PostCount == 2 && rlen < rcap && !hRids && page < 5 {
rids, err := GetRidsForTopic(t.ID, 0)
if err != nil {
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])
rlen++
topic.Rids = []int{rids[0]}
t.Rids = []int{rids[0]}
}
if tcache != nil {
if _, err := tcache.Get(topic.ID); err == sql.ErrNoRows {
_ = tcache.Set(topic.Topic())
if _, err := tcache.Get(t.ID); err == sql.ErrNoRows {
_ = 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
var idSlice = make([]int, len(reqUserList))
idSlice := make([]int, len(reqUserList))
var i int
for userID := range reqUserList {
idSlice[i] = userID

View File

@ -1,4 +1,4 @@
/* Copyright Azareal 2017 - 2019 */
/* Copyright Azareal 2017 - 2020 */
package common
import (

View File

@ -223,6 +223,7 @@ func (h *WsHubImpl) UserCount() (count int) {
h.evenUserLock.RLock()
count += len(h.evenOnlineUsers)
h.evenUserLock.RUnlock()
h.oddUserLock.RLock()
count += len(h.oddOnlineUsers)
h.oddUserLock.RUnlock()
@ -236,6 +237,7 @@ func (h *WsHubImpl) HasUser(uid int) (exists bool) {
if exists {
return exists
}
h.oddUserLock.RLock()
_, exists = h.oddOnlineUsers[uid]
h.oddUserLock.RUnlock()

View File

@ -100,6 +100,7 @@ func (u *WSUser) AddSocket(conn *websocket.Conn, page string) {
func (u *WSUser) RemoveSocket(conn *websocket.Conn) {
u.Lock()
defer u.Unlock()
if len(u.Sockets) < 6 {
for i, socket := range u.Sockets {
if socket == nil {
@ -107,7 +108,6 @@ func (u *WSUser) RemoveSocket(conn *websocket.Conn) {
}
if socket.conn == conn {
u.Sockets[i] = nil
u.Unlock()
//fmt.Printf("%+v\n", wsUser.Sockets)
return
}
@ -123,8 +123,6 @@ func (u *WSUser) RemoveSocket(conn *websocket.Conn) {
}
u.Sockets = append(u.Sockets[:key], u.Sockets[key+1:]...)
//fmt.Printf("%+v\n", u.Sockets)
u.Unlock()
}
func (u *WSUser) SetPageForSocket(conn *websocket.Conn, page string) error {

View File

@ -87,8 +87,8 @@ type Member struct {
User c.User
}
func PrebuildTmplList(user c.User, header *c.Header) c.CTmpl {
var guildList = []*Guild{
func PrebuildTmplList(user c.User, h *c.Header) c.CTmpl {
guildList := []*Guild{
&Guild{
ID: 1,
Name: "lol",
@ -104,7 +104,7 @@ func PrebuildTmplList(user c.User, header *c.Header) c.CTmpl {
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"}}
}

View File

@ -879,7 +879,7 @@ function mainInit(){
for(let i = 0; i < elems.length; i++) {
let elem = elems[i];
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...
}

View File

@ -6,8 +6,8 @@ type RouteSubset struct {
func (set *RouteSubset) Before(lines ...string) *RouteSubset {
for _, line := range lines {
for _, route := range set.RouteList {
route.RunBefore = append(route.RunBefore, Runnable{line, false})
for _, r := range set.RouteList {
r.RunBefore = append(r.RunBefore, Runnable{line, false})
}
}
return set
@ -15,8 +15,8 @@ func (set *RouteSubset) Before(lines ...string) *RouteSubset {
func (set *RouteSubset) LitBefore(lines ...string) *RouteSubset {
for _, line := range lines {
for _, route := range set.RouteList {
route.RunBefore = append(route.RunBefore, Runnable{line, true})
for _, r := range set.RouteList {
r.RunBefore = append(r.RunBefore, Runnable{line, true})
}
}
return set

View File

@ -103,7 +103,7 @@ func SettingEditSubmit(w http.ResponseWriter, r *http.Request, user c.User, snam
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)
if rerr != nil {
return rerr

View File

@ -20,9 +20,7 @@
<div class="rowitem rowmsg" style="white-space:pre-wrap;">{{lang "account_mfa_scratch_explanation"}}</div>
</div>
<div id="panel_mfa_scratches" class="colstack_item rowlist">
{{range .Something}}
<div class="rowitem">{{.}}</div>
{{end}}
{{range .Something}}<div class="rowitem">{{.}}</div>{{end}}
</div>
</main>
</div>

View File

@ -18,9 +18,9 @@
<div class="formitem formlabel"><a>Visibility</a></div>
<div class="formitem">
<select name="group_privacy">
<option val="0">Public</option>
<option val="1">Protected</option>
<option val="2">Private</option>
<option value=0>Public</option>
<option value=1>Protected</option>
<option value=2>Private</option>
</select>
</div>
</div>

View File

@ -2,10 +2,11 @@
<div class="rowitem">
<h1>{{lang "panel_statistics_active_memory_head"}}</h1>
<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 val="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="0"{{if eq .MemType 0}} selected{{end}}>{{lang "panel_statistics_memory_type_total"}}</option>
<option value="1"{{if eq .MemType 1}} selected{{end}}>{{lang "panel_statistics_memory_type_stack"}}</option>
<option value="2"{{if eq .MemType 2}} selected{{end}}>{{lang "panel_statistics_memory_type_heap"}}</option>
</select>
<noscript><input form="timeRangeForm" type="submit" /></noscript>
{{template "panel_analytics_time_range_month.html" . }}
</div>
</div>

View File

@ -2,9 +2,10 @@
<div class="rowitem">
<h1>{{lang "panel_statistics_referrers_head"}}</h1>
<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 val="1"{{if .ShowSpam}} selected{{end}}>{{lang "panel_statistics_spam_show"}}</option>
<option value="0"{{if not .ShowSpam}} selected{{end}}>{{lang "panel_statistics_spam_hide"}}</option>
<option value="1"{{if .ShowSpam}} selected{{end}}>{{lang "panel_statistics_spam_show"}}</option>
</select>
<noscript><input form="timeRangeForm" type="submit" /></noscript>
{{template "panel_analytics_time_range.html" . }}
</div>
</div>

View File

@ -1,10 +1,11 @@
<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 val="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 val="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 val="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 val="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_six_hours"}}</option>
<option value="one-year"{{if eq .TimeRange "one-year"}} selected{{end}}>{{lang "panel_statistics_time_range_one_year"}}</option>
<option value="three-months"{{if eq .TimeRange "three-months"}} selected{{end}}>{{lang "panel_statistics_time_range_three_months"}}</option>
<option value="one-month"{{if eq .TimeRange "one-month"}} selected{{end}}>{{lang "panel_statistics_time_range_one_month"}}</option>
<option value="one-week"{{if eq .TimeRange "one-week"}} selected{{end}}>{{lang "panel_statistics_time_range_one_week"}}</option>
<option value="two-days"{{if eq .TimeRange "two-days"}} selected{{end}}>{{lang "panel_statistics_time_range_two_days"}}</option>
<option value="one-day"{{if eq .TimeRange "one-day"}} selected{{end}}>{{lang "panel_statistics_time_range_one_day"}}</option>
<option value="twelve-hours"{{if eq .TimeRange "twelve-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_twelve_hours"}}</option>
<option value="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_six_hours"}}</option>
</select>
<noscript><input form="timeRangeForm" type="submit" /></noscript>

View File

@ -1,8 +1,9 @@
<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 val="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 val="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 val="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_six_hours"}}</option>
<option value="one-month"{{if eq .TimeRange "one-month"}} selected{{end}}>{{lang "panel_statistics_time_range_one_month"}}</option>
<option value="one-week"{{if eq .TimeRange "one-week"}} selected{{end}}>{{lang "panel_statistics_time_range_one_week"}}</option>
<option value="two-days"{{if eq .TimeRange "two-days"}} selected{{end}}>{{lang "panel_statistics_time_range_two_days"}}</option>
<option value="one-day"{{if eq .TimeRange "one-day"}} selected{{end}}>{{lang "panel_statistics_time_range_one_day"}}</option>
<option value="twelve-hours"{{if eq .TimeRange "twelve-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_twelve_hours"}}</option>
<option value="six-hours"{{if eq .TimeRange "six-hours"}} selected{{end}}>{{lang "panel_statistics_time_range_six_hours"}}</option>
</select>
<noscript><input form="timeRangeForm" type="submit" /></noscript>

View File

@ -7,7 +7,7 @@
<div class="formrow">
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
<div class="formitem">
<select name="setting-value">
<select name="value">
{{range .ItemList}}<option{{if .Selected}} selected{{end}} value="{{.Value}}">{{.Label}}</option>{{end}}
</select>
</div>
@ -16,19 +16,19 @@
<div class="formrow">
<div class="formitem formlabel"><a>{{lang "panel_setting_value"}}</a></div>
<div class="formitem">
<select name="setting-value">
<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>
<select name="value">
<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>
</select>
</div>
</div>
{{else if eq .Setting.Type "textarea"}}
<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>
{{else}}<div class="formrow">
<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 class="formrow form_button_row">
<div class="formitem"><button name="panel-button" class="formbutton">{{lang "panel_setting_update_button"}}</button></div>

View File

@ -121,5 +121,4 @@
{{end}}
</main>
{{template "footer.html" . }}

View File

@ -1,9 +1,13 @@
<div class="rowblock topic_reply_container">
<div class="userinfo" aria-label="{{lang "topic.your_information"}}">
<div class="avatar_item" style="background-image:url({{.CurrentUser.Avatar}}),url(/s/white-dot.jpg);background-position:0px -10px;">&nbsp;</div>
<div class="avatar_item" style="background-image:url({{.CurrentUser.Avatar}}),url(/s/white-dot.jpg);">&nbsp;</div>
<div class="user_meta">
<a href="{{.CurrentUser.Link}}" class="the_name" rel="author">{{.CurrentUser.Name}}</a>
{{if .CurrentUser.Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.CurrentUser.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">{{level .CurrentUser.Level}}</div><div class="tag_post"></div></div>{{end}}
<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 class="rowblock topic_reply_form quick_create_form" aria-label="{{lang "topic.reply_aria"}}">

View File

@ -1,7 +1,11 @@
<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;">&nbsp;</div>
<div class="avatar_item" style="background-image:url({{.Avatar}}),url(/s/white-dot.jpg);">&nbsp;</div>
<div class="user_meta">
<a href="{{.UserLink}}" class="the_name" rel="author">{{.CreatedByName}}</a>
{{if .Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">{{level .Level}}</div><div class="tag_post"></div></div>{{end}}
<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>

View File

@ -1059,6 +1059,7 @@ blockquote:first-child {
width: 84px;
height: 84px;
margin-bottom: 12px;
background-position: 0px -10px;
background-size: 120px;
}
.the_name, .userinfo .tag_block {

View File

@ -837,6 +837,7 @@ blockquote:first-child {
border-radius: 36px;
height: 58px;
width: 58px;
background-position: 0px -10px;
background-size: 78px;
margin-left: auto;
margin-right: auto;