diff --git a/common/pages.go b/common/pages.go index f58b9bf5..87a0fc72 100644 --- a/common/pages.go +++ b/common/pages.go @@ -282,25 +282,25 @@ type ResetPage struct { /* WIP for dyntmpl */ type Panel struct { *BasePanelPage - HTMLID string + HTMLID string ClassNames string - TmplName string - Inner nobreak + TmplName string + Inner nobreak } type PanelAnalytics struct { *BasePanelPage FormAction string - TmplName string - Inner nobreak + TmplName string + Inner nobreak } -type PanelAnalyticsStd struct{ +type PanelAnalyticsStd struct { Graph PanelTimeGraph ViewItems []PanelAnalyticsItem TimeRange string Unit string TimeType string } -type PanelAnalyticsStdUnit struct{ +type PanelAnalyticsStdUnit struct { Graph PanelTimeGraph ViewItems []PanelAnalyticsItemUnit TimeRange string @@ -334,7 +334,7 @@ type PanelPage struct { type GridElement struct { ID string - Href string + Href string Body string Order int // For future use Class string @@ -387,7 +387,7 @@ type PanelAnalyticsItem struct { type PanelAnalyticsItemUnit struct { Time int64 Count int64 - Unit string + Unit string } type PanelAnalyticsPage struct { @@ -591,6 +591,10 @@ type PanelDebugPage struct { Goroutines int CPUs int MemStats runtime.MemStats + + TCache int + UCache int + TopicListThaw bool } type PageSimple struct { diff --git a/common/phrases/phrases.go b/common/phrases/phrases.go index e5625aba..c03a2b3b 100644 --- a/common/phrases/phrases.go +++ b/common/phrases/phrases.go @@ -99,6 +99,23 @@ func InitPhrases(lang string) error { // [prefix][name]phrase langPack.TmplPhrasesPrefixes = make(map[string]map[string]string) + var conMap = make(map[string]string) // Cache phrase strings so we can de-dupe items to reduce memory use. There appear to be some minor improvements with this, although we would need a more thorough check to be sure. + for name, phrase := range langPack.TmplPhrases { + _, ok := conMap[phrase] + if !ok { + conMap[phrase] = phrase + } + cItem := conMap[phrase] + prefix := strings.Split(name, ".")[0] + _, ok = langPack.TmplPhrasesPrefixes[prefix] + if !ok { + langPack.TmplPhrasesPrefixes[prefix] = make(map[string]string) + } + langPack.TmplPhrasesPrefixes[prefix][name] = cItem + } + + // [prefix][name]phrase + /*langPack.TmplPhrasesPrefixes = make(map[string]map[string]string) for name, phrase := range langPack.TmplPhrases { prefix := strings.Split(name, ".")[0] _, ok := langPack.TmplPhrasesPrefixes[prefix] @@ -106,7 +123,7 @@ func InitPhrases(lang string) error { langPack.TmplPhrasesPrefixes[prefix] = make(map[string]string) } langPack.TmplPhrasesPrefixes[prefix][name] = phrase - } + }*/ langPack.TmplIndicesToPhrases = make([][][]byte, len(langTmplIndicesToNames)) for tmplID, phraseNames := range langTmplIndicesToNames { diff --git a/common/template_init.go b/common/template_init.go index 5c909ca0..7dbc846b 100644 --- a/common/template_init.go +++ b/common/template_init.go @@ -1,6 +1,7 @@ package common import ( + "fmt" "html/template" "io" "log" @@ -301,7 +302,7 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string tmpls.AddStd("account", "common.Account", accountPage) basePage := &BasePanelPage{header, PanelStats{}, "dashboard", ReportForumID} - tmpls.AddStd("panel", "common.Panel", Panel{basePage, "panel_dashboard_right","","panel_dashboard", inter}) + tmpls.AddStd("panel", "common.Panel", Panel{basePage, "panel_dashboard_right", "", "panel_dashboard", inter}) //tmpls.AddStd("panel_analytics", "common.PanelAnalytics", Panel{basePage, "panel_dashboard_right","panel_dashboard", inter}) var writeTemplate = func(name string, content interface{}) { @@ -688,6 +689,22 @@ func initDefaultTmplFuncMap() { return template.HTML(phrases.GetLevelPhrase(level)) } + fmap["bunit"] = func(byteInt interface{}) interface{} { + var byteFloat float64 + var unit string + switch bytes := byteInt.(type) { + case int: + byteFloat, unit = ConvertByteUnit(float64(bytes)) + case int64: + byteFloat, unit = ConvertByteUnit(float64(bytes)) + case uint64: + byteFloat, unit = ConvertByteUnit(float64(bytes)) + default: + panic("bytes is not an int, int64 or uint64") + } + return fmt.Sprintf("%.1f", byteFloat) + unit + } + fmap["abstime"] = func(timeInt interface{}) interface{} { time, ok := timeInt.(time.Time) if !ok { diff --git a/common/templates/templates.go b/common/templates/templates.go index 0602e650..1e6bf87e 100644 --- a/common/templates/templates.go +++ b/common/templates/templates.go @@ -74,7 +74,7 @@ type CTemplateSet struct { logger *log.Logger loggerf *os.File - lang string + lang string } func NewCTemplateSet(in string) *CTemplateSet { @@ -108,6 +108,7 @@ func NewCTemplateSet(in string) *CTemplateSet { "lang": true, //"langf":true, "level": true, + "bunit": true, "abstime": true, "reltime": true, "scope": true, @@ -117,7 +118,7 @@ func NewCTemplateSet(in string) *CTemplateSet { }, logger: log.New(f, "", log.LstdFlags), loggerf: f, - lang:in, + lang: in, } } @@ -443,13 +444,13 @@ func (c *CTemplateSet) compile(name string, content string, expects string, expe } if c.lang == "normal" { - fout += "// nolint\nfunc Template_" + fname + "(tmpl_" + fname + "_i interface{}, w io.Writer) error {\n" - fout += `tmpl_` + fname + `_vars, ok := tmpl_` + fname + `_i.(` + expects + `) + fout += "// nolint\nfunc Template_" + fname + "(tmpl_" + fname + "_i interface{}, w io.Writer) error {\n" + fout += `tmpl_` + fname + `_vars, ok := tmpl_` + fname + `_i.(` + expects + `) if !ok { return errors.New("invalid page struct value") } ` - fout += `var iw http.ResponseWriter + fout += `var iw http.ResponseWriter gzw, ok := w.(common.GzipResponseWriter) if ok { iw = gzw.ResponseWriter @@ -1116,6 +1117,17 @@ ArgLoop: litString("phrases.GetLevelPhrase("+leftParam+")", false) c.importMap[langPkg] = langPkg break ArgLoop + case "bunit": + // TODO: Implement bunit literals + leftOperand := node.Args[pos+1].String() + if len(leftOperand) == 0 { + panic("The leftoperand for function buint cannot be left blank") + } + leftParam, _ := c.compileIfVarSub(con, leftOperand) + out = "{\nbyteFloat, unit := common.ConvertByteUnit(float64(" + leftParam + "))\n" + out += "w.Write(fmt.Sprintf(\"%.1f\", byteFloat) + unit)\n" + literal = true + break ArgLoop case "abstime": // TODO: Implement level literals leftOperand := node.Args[pos+1].String() @@ -1407,7 +1419,7 @@ func (c *CTemplateSet) retCall(name string, params ...interface{}) { c.detail("returned from " + name + " => (" + pstr + ")") } -func buildUserExprs(holder string) ([]string,[]string) { +func buildUserExprs(holder string) ([]string, []string) { var userExprs = []string{ holder + ".CurrentUser.Loggedin", holder + ".CurrentUser.IsSuperMod", @@ -1825,4 +1837,4 @@ func (c *CTemplateSet) error(args ...interface{}) { func (c *CTemplateSet) critical(args ...interface{}) { c.logger.Println(args...) -} \ No newline at end of file +} diff --git a/common/topic_cache.go b/common/topic_cache.go index 40aadcdd..1549a732 100644 --- a/common/topic_cache.go +++ b/common/topic_cache.go @@ -125,37 +125,37 @@ func (mts *MemoryTopicCache) Remove(id int) error { } // RemoveUnsafe is the unsafe version of Remove. THIS METHOD IS NOT THREAD-SAFE. -func (mts *MemoryTopicCache) RemoveUnsafe(id int) error { - _, ok := mts.items[id] +func (s *MemoryTopicCache) RemoveUnsafe(id int) error { + _, ok := s.items[id] if !ok { return ErrNoRows } - delete(mts.items, id) - atomic.AddInt64(&mts.length, -1) + delete(s.items, id) + atomic.AddInt64(&s.length, -1) return nil } // Flush removes all the topics from the cache, useful for tests. -func (mts *MemoryTopicCache) Flush() { - mts.Lock() - mts.items = make(map[int]*Topic) - mts.length = 0 - mts.Unlock() +func (s *MemoryTopicCache) Flush() { + s.Lock() + s.items = make(map[int]*Topic) + s.length = 0 + s.Unlock() } // ! Is this concurrent? // Length returns the number of topics in the memory cache -func (mts *MemoryTopicCache) Length() int { - return int(mts.length) +func (s *MemoryTopicCache) Length() int { + return int(s.length) } // SetCapacity sets the maximum number of topics which this cache can hold -func (mts *MemoryTopicCache) SetCapacity(capacity int) { +func (s *MemoryTopicCache) SetCapacity(capacity int) { // Ints are moved in a single instruction, so this should be thread-safe - mts.capacity = capacity + s.capacity = capacity } // GetCapacity returns the maximum number of topics this cache can hold -func (mts *MemoryTopicCache) GetCapacity() int { - return mts.capacity +func (s *MemoryTopicCache) GetCapacity() int { + return s.capacity } diff --git a/langs/english.json b/langs/english.json index eaf999ec..3e48ea91 100644 --- a/langs/english.json +++ b/langs/english.json @@ -589,7 +589,7 @@ "forums_no_forums":"You don't have access to any forums.", "topic.opening_post_aria":"The opening post for this topic", - "topic.status_closed_aria":"This topic has been locked", + "topic.status_closed_aria":"This topic is locked", "topic.title_input_aria":"Topic Title Input", "topic.update_button":"Update", "topic.userinfo_aria":"The information on the poster", diff --git a/routes/panel/debug.go b/routes/panel/debug.go index fa112320..d21e4b28 100644 --- a/routes/panel/debug.go +++ b/routes/panel/debug.go @@ -41,6 +41,17 @@ func Debug(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError { var memStats runtime.MemStats runtime.ReadMemStats(&memStats) - pi := c.PanelDebugPage{basePage, goVersion, dbVersion, uptime, openConnCount, qgen.Builder.GetAdapter().GetName(), goroutines, cpus, memStats} - return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage,"panel_dashboard_right","","panel_debug", pi}) + var tlen, ulen int + tcache := c.Topics.GetCache() + if tcache != nil { + tlen = tcache.Length() + } + ucache := c.Users.GetCache() + if ucache != nil { + ulen = ucache.Length() + } + topicListThawed := c.TopicListThaw.Thawed() + + pi := c.PanelDebugPage{basePage, goVersion, dbVersion, uptime, openConnCount, qgen.Builder.GetAdapter().GetName(), goroutines, cpus, memStats, tlen, ulen, topicListThawed} + return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "panel_dashboard_right", "debug_page", "panel_debug", pi}) } diff --git a/templates/panel_debug.html b/templates/panel_debug.html index e40994d8..41b006db 100644 --- a/templates/panel_debug.html +++ b/templates/panel_debug.html @@ -9,7 +9,7 @@
{{.Uptime}}
{{.GoVersion}}
{{.DBVersion}}
- +
{{lang "panel_debug_open_database_connections_label"}}
{{lang "panel_debug_adapter_label"}}
@@ -20,27 +20,73 @@
{{.DBAdapter}}
?
+
{{lang "panel_debug_goroutine_count_label"}}
{{lang "panel_debug_cpu_count_label"}}
-
HeapAlloc
+
???
{{.Goroutines}}
{{.CPUs}}
-
{{.MemStats.HeapAlloc}}
+
?
+ +
+

Memory Statistics

+
+
+
Sys
HeapSys
+
HeapAlloc
+ +
{{.MemStats.Sys}} ({{bunit .MemStats.Sys}})
+
{{.MemStats.HeapSys}} ({{bunit .MemStats.HeapSys}})
+
{{.MemStats.HeapAlloc}} ({{bunit .MemStats.HeapAlloc}})
+ +
HeapIdle
HeapObjects
- -
{{.MemStats.HeapSys}}
-
{{.MemStats.HeapIdle}}
-
{{.MemStats.HeapObjects}}
- -
???
-
???
StackInuse
+ +
{{.MemStats.HeapIdle}} ({{bunit .MemStats.HeapIdle}})
+
{{.MemStats.HeapObjects}}
+
{{.MemStats.StackInuse}} ({{bunit .MemStats.StackInuse}})
+ +
MSpanInuse
+
MCacheInuse
+
MSpanSys
+ +
{{.MemStats.MSpanInuse}} ({{bunit .MemStats.MSpanInuse}})
+
{{.MemStats.MCacheInuse}} ({{bunit .MemStats.MCacheInuse}})
+
{{.MemStats.MSpanSys}} ({{bunit .MemStats.MSpanSys}})
+ + +
MCacheSys
+
GCSys
+
OtherSys
+ +
{{.MemStats.MCacheSys}} ({{bunit .MemStats.MCacheSys}})
+
{{.MemStats.GCSys}} ({{bunit .MemStats.GCSys}})
+
{{.MemStats.OtherSys}} ({{bunit .MemStats.OtherSys}})
+
+
+

Caches

+
+
+
Topic Cache
+
User Cache
+
Reply Cache
+ +
{{.TCache}}
+
{{.UCache}}
+
0
+ + +
Topic List
+
???
+
???
+ +
{{if .TopicListThaw}}Thawed{{else}}Sleeping{{end}}
?
?
-
{{.MemStats.StackInuse}}
\ No newline at end of file diff --git a/themes/cosora/public/main.css b/themes/cosora/public/main.css index 2ff35bf2..45dbce8f 100644 --- a/themes/cosora/public/main.css +++ b/themes/cosora/public/main.css @@ -1594,42 +1594,13 @@ red { padding-bottom: 0px; padding-right: 10px; } -.grid_item span { +.grid_item span, .grid_item a { margin-top: 16px; margin-bottom: 16px; margin-left: auto; margin-right: auto; text-align: center; } -/* TODO: Move these to panel.css */ -#dash-version:before, #dash-cpu:before, #dash-ram:before, #dash-totonline:before, #dash-gonline:before, #dash-uonline:before, #dash-reqs:before, #dash-postsperday:before, #dash-topicsperday:before { - display: inline-block; - background: var(--tinted-background-color); - font: normal normal normal 14px/1 FontAwesome; - font-size: 20px; - padding-left: 17px; - padding-top: 16px; - padding-right: 19px; - color: hsl(0,0%,20%); -} -#dash-version:before { - content: "\f126"; -} -#dash-cpu:before { - content: "\f2db"; -} -#dash-ram:before { - content: "\f233"; -} -#dash-totonline:before, #dash-gonline:before, #dash-uonline:before { - content: "\f007"; -} -#dash-reqs:before { - content: "\f080"; -} -#dash-postsperday:before, #dash-topicsperday:before { - content: "\f27b"; -} @media(min-width: 1000px) { .footer { @@ -1648,13 +1619,6 @@ red { max-width: 1000px; margin-left: auto; margin-right: auto; - } - .footer { - max-width: 1000px; - margin-left: auto; - margin-right: auto; - } - #main { padding-top: 18px; padding-left: 16px; padding-right: 16px; @@ -1662,6 +1626,9 @@ red { border-right: 1px solid hsl(20,0%,95%); } .footer { + max-width: 1000px; + margin-left: auto; + margin-right: auto; padding-left: 8px; padding-right: 8px; } @@ -1686,10 +1653,7 @@ red { .like_count { margin-right: 1px; } - .like_count:after { - margin-right: 6px; - } - .created_at:before, .ip_item:before { + .like_count:after, .created_at:before, .ip_item:before { margin-right: 6px; } } diff --git a/themes/cosora/public/panel.css b/themes/cosora/public/panel.css index 1f066043..0690f59f 100644 --- a/themes/cosora/public/panel.css +++ b/themes/cosora/public/panel.css @@ -80,6 +80,41 @@ font-size: 17px; color: hsl(0,0%,40%); } +/* TODO: Move these to panel.css */ +#dash-version:before, #dash-cpu:before, #dash-ram:before, #dash-memused:before, #dash-totonline:before, #dash-gonline:before, #dash-uonline:before, #dash-reqs:before, #dash-postsperday:before, #dash-topicsperday:before { + display: inline-block; + background: var(--tinted-background-color); + font: normal normal normal 14px/1 FontAwesome; + font-size: 20px; + padding-left: 17px; + padding-top: 16px; + padding-right: 19px; + color: hsl(0,0%,20%); +} +#dash-version:before { + content: "\f126"; +} +#dash-cpu:before, #dash-memused:before { + content: "\f2db"; +} +#dash-ram:before { + content: "\f233"; +} +#dash-totonline:before, #dash-gonline:before, #dash-uonline:before { + content: "\f007"; +} +#dash-reqs:before { + content: "\f080"; +} +#dash-postsperday:before, #dash-topicsperday:before { + content: "\f27b"; +} +#panel_debug .grid_stat:not(.grid_stat_head) { + margin-bottom: 8px; +} +.debug_page.colstack_right .colstack_sub_head { + margin-top: 6px; +} .complex_rowlist { background-color: inherit !important; diff --git a/themes/nox/public/main.css b/themes/nox/public/main.css index 0e205093..b6c4418b 100644 --- a/themes/nox/public/main.css +++ b/themes/nox/public/main.css @@ -1399,9 +1399,9 @@ input[type=checkbox]:checked + label .sel { } } -@media(max-width: 850px) { - /**/ -} +{{/**@media(max-width: 850px) { + // +}**/}} @media(min-width: 1010px) { #container { @@ -1412,11 +1412,10 @@ input[type=checkbox]:checked + label .sel { margin-left: auto; margin-right: auto; } - .footBlock { + .footBlock, .footer { display: flex; } .footer { - display: flex; flex-direction: column; } diff --git a/themes/shadow/public/main.css b/themes/shadow/public/main.css index 3be6f595..c9e192a4 100644 --- a/themes/shadow/public/main.css +++ b/themes/shadow/public/main.css @@ -1026,21 +1026,6 @@ blockquote:first-child { background-color: var(--main-block-color); } -#panel_dashboard_right .colstack_head .rowitem { - padding: 10px; -} -#panel_dashboard_right .colstack_head .rowitem h1 { - font-size: 15px; - margin-left: auto; -} - -#panel_dashboard_right .colstack_head a { - text-align: center; - width: 100%; - display: block; - font-size: 15px; -} - @media(max-width: 935px) { .simple .user_tag { display: none; diff --git a/themes/shadow/public/panel.css b/themes/shadow/public/panel.css index 6c7c3c85..e5a5c27f 100644 --- a/themes/shadow/public/panel.css +++ b/themes/shadow/public/panel.css @@ -43,6 +43,21 @@ content: "{{lang "panel_delete_button_text" . }}"; } +#panel_dashboard_right .colstack_head .rowitem { + padding: 10px; +} +#panel_dashboard_right .colstack_head .rowitem h1, #panel_dashboard_right .colstack_sub_head .rowitem h2 { + font-size: 15px; + margin-left: auto; + margin-right: auto; +} +#panel_dashboard_right .colstack_head a, #panel_dashboard_right .colstack_sub_head a { + text-align: center; + width: 100%; + display: block; + font-size: 15px; +} + #panel_forums .rowitem { display: flex; }