Added Mem to the dashboard and added a historic process memory use analytics pane.
Added the memchunks table. Eliminated some unnecessary indentation in the analytics templates. Added the panel_menu_statistics_memory phrase. Added the panel_dashboard_memused phrase. Added the panel_dashboard_memused_desc phrase. Added the panel_statistics_memory_head phrase. You will need to run the updater / patcher for this commit.
This commit is contained in:
parent
a52d9cc371
commit
5dc238f196
|
@ -614,6 +614,13 @@ func createTables(adapter qgen.Adapter) error {
|
|||
}, nil,
|
||||
)
|
||||
|
||||
qgen.Install.CreateTable("memchunks", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"count", "int", 0, false, false, "0"},
|
||||
tblColumn{"createdAt", "datetime", 0, false, false, ""},
|
||||
}, nil,
|
||||
)
|
||||
|
||||
qgen.Install.CreateTable("sync", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"last_update", "datetime", 0, false, false, ""},
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package counters
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"database/sql"
|
||||
|
||||
c "github.com/Azareal/Gosora/common"
|
||||
"github.com/Azareal/Gosora/query_gen"
|
||||
)
|
||||
|
||||
var MemoryCounter *DefaultMemoryCounter
|
||||
|
||||
type DefaultMemoryCounter struct {
|
||||
insert *sql.Stmt
|
||||
}
|
||||
|
||||
func NewMemoryCounter(acc *qgen.Accumulator) (*DefaultMemoryCounter, error) {
|
||||
co := &DefaultMemoryCounter{
|
||||
insert: acc.Insert("memchunks").Columns("count, createdAt").Fields("?,UTC_TIMESTAMP()").Prepare(),
|
||||
}
|
||||
c.AddScheduledFifteenMinuteTask(co.Tick)
|
||||
//c.AddScheduledSecondTask(co.Tick)
|
||||
c.AddShutdownTask(co.Tick)
|
||||
return co, acc.FirstError()
|
||||
}
|
||||
|
||||
func (co *DefaultMemoryCounter) Tick() (err error) {
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
c.DebugLogf("Inserting a memchunk with a value of %d", m.Sys)
|
||||
_, err = co.insert.Exec(m.Sys)
|
||||
return err
|
||||
}
|
|
@ -300,6 +300,13 @@ type PanelAnalyticsStd struct{
|
|||
Unit string
|
||||
TimeType string
|
||||
}
|
||||
type PanelAnalyticsStdUnit struct{
|
||||
Graph PanelTimeGraph
|
||||
ViewItems []PanelAnalyticsItemUnit
|
||||
TimeRange string
|
||||
Unit string
|
||||
TimeType string
|
||||
}
|
||||
|
||||
type PanelStats struct {
|
||||
Users int
|
||||
|
@ -376,6 +383,11 @@ type PanelAnalyticsItem struct {
|
|||
Time int64
|
||||
Count int64
|
||||
}
|
||||
type PanelAnalyticsItemUnit struct {
|
||||
Time int64
|
||||
Count int64
|
||||
Unit string
|
||||
}
|
||||
|
||||
type PanelAnalyticsPage struct {
|
||||
*BasePanelPage
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
*
|
||||
* Utility Functions And Stuff
|
||||
* Copyright Azareal 2017 - 2019
|
||||
* Copyright Azareal 2017 - 2020
|
||||
*
|
||||
*/
|
||||
package common
|
||||
|
|
443
gen_router.go
443
gen_router.go
|
@ -94,6 +94,7 @@ var RouteMap = map[string]interface{}{
|
|||
"panel.AnalyticsLanguageViews": panel.AnalyticsLanguageViews,
|
||||
"panel.AnalyticsReferrerViews": panel.AnalyticsReferrerViews,
|
||||
"panel.AnalyticsPosts": panel.AnalyticsPosts,
|
||||
"panel.AnalyticsMemory": panel.AnalyticsMemory,
|
||||
"panel.AnalyticsTopics": panel.AnalyticsTopics,
|
||||
"panel.AnalyticsForums": panel.AnalyticsForums,
|
||||
"panel.Groups": panel.Groups,
|
||||
|
@ -241,78 +242,79 @@ var routeMapEnum = map[string]int{
|
|||
"panel.AnalyticsLanguageViews": 68,
|
||||
"panel.AnalyticsReferrerViews": 69,
|
||||
"panel.AnalyticsPosts": 70,
|
||||
"panel.AnalyticsTopics": 71,
|
||||
"panel.AnalyticsForums": 72,
|
||||
"panel.Groups": 73,
|
||||
"panel.GroupsEdit": 74,
|
||||
"panel.GroupsEditPerms": 75,
|
||||
"panel.GroupsEditSubmit": 76,
|
||||
"panel.GroupsEditPermsSubmit": 77,
|
||||
"panel.GroupsCreateSubmit": 78,
|
||||
"panel.Backups": 79,
|
||||
"panel.LogsRegs": 80,
|
||||
"panel.LogsMod": 81,
|
||||
"panel.Debug": 82,
|
||||
"panel.Dashboard": 83,
|
||||
"routes.AccountEdit": 84,
|
||||
"routes.AccountEditPassword": 85,
|
||||
"routes.AccountEditPasswordSubmit": 86,
|
||||
"routes.AccountEditAvatarSubmit": 87,
|
||||
"routes.AccountEditUsernameSubmit": 88,
|
||||
"routes.AccountEditMFA": 89,
|
||||
"routes.AccountEditMFASetup": 90,
|
||||
"routes.AccountEditMFASetupSubmit": 91,
|
||||
"routes.AccountEditMFADisableSubmit": 92,
|
||||
"routes.AccountEditEmail": 93,
|
||||
"routes.AccountEditEmailTokenSubmit": 94,
|
||||
"routes.AccountLogins": 95,
|
||||
"routes.LevelList": 96,
|
||||
"routes.ViewProfile": 97,
|
||||
"routes.BanUserSubmit": 98,
|
||||
"routes.UnbanUser": 99,
|
||||
"routes.ActivateUser": 100,
|
||||
"routes.IPSearch": 101,
|
||||
"routes.CreateTopicSubmit": 102,
|
||||
"routes.EditTopicSubmit": 103,
|
||||
"routes.DeleteTopicSubmit": 104,
|
||||
"routes.StickTopicSubmit": 105,
|
||||
"routes.UnstickTopicSubmit": 106,
|
||||
"routes.LockTopicSubmit": 107,
|
||||
"routes.UnlockTopicSubmit": 108,
|
||||
"routes.MoveTopicSubmit": 109,
|
||||
"routes.LikeTopicSubmit": 110,
|
||||
"routes.AddAttachToTopicSubmit": 111,
|
||||
"routes.RemoveAttachFromTopicSubmit": 112,
|
||||
"routes.ViewTopic": 113,
|
||||
"routes.CreateReplySubmit": 114,
|
||||
"routes.ReplyEditSubmit": 115,
|
||||
"routes.ReplyDeleteSubmit": 116,
|
||||
"routes.ReplyLikeSubmit": 117,
|
||||
"routes.AddAttachToReplySubmit": 118,
|
||||
"routes.RemoveAttachFromReplySubmit": 119,
|
||||
"routes.ProfileReplyCreateSubmit": 120,
|
||||
"routes.ProfileReplyEditSubmit": 121,
|
||||
"routes.ProfileReplyDeleteSubmit": 122,
|
||||
"routes.PollVote": 123,
|
||||
"routes.PollResults": 124,
|
||||
"routes.AccountLogin": 125,
|
||||
"routes.AccountRegister": 126,
|
||||
"routes.AccountLogout": 127,
|
||||
"routes.AccountLoginSubmit": 128,
|
||||
"routes.AccountLoginMFAVerify": 129,
|
||||
"routes.AccountLoginMFAVerifySubmit": 130,
|
||||
"routes.AccountRegisterSubmit": 131,
|
||||
"routes.AccountPasswordReset": 132,
|
||||
"routes.AccountPasswordResetSubmit": 133,
|
||||
"routes.AccountPasswordResetToken": 134,
|
||||
"routes.AccountPasswordResetTokenSubmit": 135,
|
||||
"routes.DynamicRoute": 136,
|
||||
"routes.UploadedFile": 137,
|
||||
"routes.StaticFile": 138,
|
||||
"routes.RobotsTxt": 139,
|
||||
"routes.SitemapXml": 140,
|
||||
"routes.BadRoute": 141,
|
||||
"routes.HTTPSRedirect": 142,
|
||||
"panel.AnalyticsMemory": 71,
|
||||
"panel.AnalyticsTopics": 72,
|
||||
"panel.AnalyticsForums": 73,
|
||||
"panel.Groups": 74,
|
||||
"panel.GroupsEdit": 75,
|
||||
"panel.GroupsEditPerms": 76,
|
||||
"panel.GroupsEditSubmit": 77,
|
||||
"panel.GroupsEditPermsSubmit": 78,
|
||||
"panel.GroupsCreateSubmit": 79,
|
||||
"panel.Backups": 80,
|
||||
"panel.LogsRegs": 81,
|
||||
"panel.LogsMod": 82,
|
||||
"panel.Debug": 83,
|
||||
"panel.Dashboard": 84,
|
||||
"routes.AccountEdit": 85,
|
||||
"routes.AccountEditPassword": 86,
|
||||
"routes.AccountEditPasswordSubmit": 87,
|
||||
"routes.AccountEditAvatarSubmit": 88,
|
||||
"routes.AccountEditUsernameSubmit": 89,
|
||||
"routes.AccountEditMFA": 90,
|
||||
"routes.AccountEditMFASetup": 91,
|
||||
"routes.AccountEditMFASetupSubmit": 92,
|
||||
"routes.AccountEditMFADisableSubmit": 93,
|
||||
"routes.AccountEditEmail": 94,
|
||||
"routes.AccountEditEmailTokenSubmit": 95,
|
||||
"routes.AccountLogins": 96,
|
||||
"routes.LevelList": 97,
|
||||
"routes.ViewProfile": 98,
|
||||
"routes.BanUserSubmit": 99,
|
||||
"routes.UnbanUser": 100,
|
||||
"routes.ActivateUser": 101,
|
||||
"routes.IPSearch": 102,
|
||||
"routes.CreateTopicSubmit": 103,
|
||||
"routes.EditTopicSubmit": 104,
|
||||
"routes.DeleteTopicSubmit": 105,
|
||||
"routes.StickTopicSubmit": 106,
|
||||
"routes.UnstickTopicSubmit": 107,
|
||||
"routes.LockTopicSubmit": 108,
|
||||
"routes.UnlockTopicSubmit": 109,
|
||||
"routes.MoveTopicSubmit": 110,
|
||||
"routes.LikeTopicSubmit": 111,
|
||||
"routes.AddAttachToTopicSubmit": 112,
|
||||
"routes.RemoveAttachFromTopicSubmit": 113,
|
||||
"routes.ViewTopic": 114,
|
||||
"routes.CreateReplySubmit": 115,
|
||||
"routes.ReplyEditSubmit": 116,
|
||||
"routes.ReplyDeleteSubmit": 117,
|
||||
"routes.ReplyLikeSubmit": 118,
|
||||
"routes.AddAttachToReplySubmit": 119,
|
||||
"routes.RemoveAttachFromReplySubmit": 120,
|
||||
"routes.ProfileReplyCreateSubmit": 121,
|
||||
"routes.ProfileReplyEditSubmit": 122,
|
||||
"routes.ProfileReplyDeleteSubmit": 123,
|
||||
"routes.PollVote": 124,
|
||||
"routes.PollResults": 125,
|
||||
"routes.AccountLogin": 126,
|
||||
"routes.AccountRegister": 127,
|
||||
"routes.AccountLogout": 128,
|
||||
"routes.AccountLoginSubmit": 129,
|
||||
"routes.AccountLoginMFAVerify": 130,
|
||||
"routes.AccountLoginMFAVerifySubmit": 131,
|
||||
"routes.AccountRegisterSubmit": 132,
|
||||
"routes.AccountPasswordReset": 133,
|
||||
"routes.AccountPasswordResetSubmit": 134,
|
||||
"routes.AccountPasswordResetToken": 135,
|
||||
"routes.AccountPasswordResetTokenSubmit": 136,
|
||||
"routes.DynamicRoute": 137,
|
||||
"routes.UploadedFile": 138,
|
||||
"routes.StaticFile": 139,
|
||||
"routes.RobotsTxt": 140,
|
||||
"routes.SitemapXml": 141,
|
||||
"routes.BadRoute": 142,
|
||||
"routes.HTTPSRedirect": 143,
|
||||
}
|
||||
var reverseRouteMapEnum = map[int]string{
|
||||
0: "routes.Overview",
|
||||
|
@ -386,78 +388,79 @@ var reverseRouteMapEnum = map[int]string{
|
|||
68: "panel.AnalyticsLanguageViews",
|
||||
69: "panel.AnalyticsReferrerViews",
|
||||
70: "panel.AnalyticsPosts",
|
||||
71: "panel.AnalyticsTopics",
|
||||
72: "panel.AnalyticsForums",
|
||||
73: "panel.Groups",
|
||||
74: "panel.GroupsEdit",
|
||||
75: "panel.GroupsEditPerms",
|
||||
76: "panel.GroupsEditSubmit",
|
||||
77: "panel.GroupsEditPermsSubmit",
|
||||
78: "panel.GroupsCreateSubmit",
|
||||
79: "panel.Backups",
|
||||
80: "panel.LogsRegs",
|
||||
81: "panel.LogsMod",
|
||||
82: "panel.Debug",
|
||||
83: "panel.Dashboard",
|
||||
84: "routes.AccountEdit",
|
||||
85: "routes.AccountEditPassword",
|
||||
86: "routes.AccountEditPasswordSubmit",
|
||||
87: "routes.AccountEditAvatarSubmit",
|
||||
88: "routes.AccountEditUsernameSubmit",
|
||||
89: "routes.AccountEditMFA",
|
||||
90: "routes.AccountEditMFASetup",
|
||||
91: "routes.AccountEditMFASetupSubmit",
|
||||
92: "routes.AccountEditMFADisableSubmit",
|
||||
93: "routes.AccountEditEmail",
|
||||
94: "routes.AccountEditEmailTokenSubmit",
|
||||
95: "routes.AccountLogins",
|
||||
96: "routes.LevelList",
|
||||
97: "routes.ViewProfile",
|
||||
98: "routes.BanUserSubmit",
|
||||
99: "routes.UnbanUser",
|
||||
100: "routes.ActivateUser",
|
||||
101: "routes.IPSearch",
|
||||
102: "routes.CreateTopicSubmit",
|
||||
103: "routes.EditTopicSubmit",
|
||||
104: "routes.DeleteTopicSubmit",
|
||||
105: "routes.StickTopicSubmit",
|
||||
106: "routes.UnstickTopicSubmit",
|
||||
107: "routes.LockTopicSubmit",
|
||||
108: "routes.UnlockTopicSubmit",
|
||||
109: "routes.MoveTopicSubmit",
|
||||
110: "routes.LikeTopicSubmit",
|
||||
111: "routes.AddAttachToTopicSubmit",
|
||||
112: "routes.RemoveAttachFromTopicSubmit",
|
||||
113: "routes.ViewTopic",
|
||||
114: "routes.CreateReplySubmit",
|
||||
115: "routes.ReplyEditSubmit",
|
||||
116: "routes.ReplyDeleteSubmit",
|
||||
117: "routes.ReplyLikeSubmit",
|
||||
118: "routes.AddAttachToReplySubmit",
|
||||
119: "routes.RemoveAttachFromReplySubmit",
|
||||
120: "routes.ProfileReplyCreateSubmit",
|
||||
121: "routes.ProfileReplyEditSubmit",
|
||||
122: "routes.ProfileReplyDeleteSubmit",
|
||||
123: "routes.PollVote",
|
||||
124: "routes.PollResults",
|
||||
125: "routes.AccountLogin",
|
||||
126: "routes.AccountRegister",
|
||||
127: "routes.AccountLogout",
|
||||
128: "routes.AccountLoginSubmit",
|
||||
129: "routes.AccountLoginMFAVerify",
|
||||
130: "routes.AccountLoginMFAVerifySubmit",
|
||||
131: "routes.AccountRegisterSubmit",
|
||||
132: "routes.AccountPasswordReset",
|
||||
133: "routes.AccountPasswordResetSubmit",
|
||||
134: "routes.AccountPasswordResetToken",
|
||||
135: "routes.AccountPasswordResetTokenSubmit",
|
||||
136: "routes.DynamicRoute",
|
||||
137: "routes.UploadedFile",
|
||||
138: "routes.StaticFile",
|
||||
139: "routes.RobotsTxt",
|
||||
140: "routes.SitemapXml",
|
||||
141: "routes.BadRoute",
|
||||
142: "routes.HTTPSRedirect",
|
||||
71: "panel.AnalyticsMemory",
|
||||
72: "panel.AnalyticsTopics",
|
||||
73: "panel.AnalyticsForums",
|
||||
74: "panel.Groups",
|
||||
75: "panel.GroupsEdit",
|
||||
76: "panel.GroupsEditPerms",
|
||||
77: "panel.GroupsEditSubmit",
|
||||
78: "panel.GroupsEditPermsSubmit",
|
||||
79: "panel.GroupsCreateSubmit",
|
||||
80: "panel.Backups",
|
||||
81: "panel.LogsRegs",
|
||||
82: "panel.LogsMod",
|
||||
83: "panel.Debug",
|
||||
84: "panel.Dashboard",
|
||||
85: "routes.AccountEdit",
|
||||
86: "routes.AccountEditPassword",
|
||||
87: "routes.AccountEditPasswordSubmit",
|
||||
88: "routes.AccountEditAvatarSubmit",
|
||||
89: "routes.AccountEditUsernameSubmit",
|
||||
90: "routes.AccountEditMFA",
|
||||
91: "routes.AccountEditMFASetup",
|
||||
92: "routes.AccountEditMFASetupSubmit",
|
||||
93: "routes.AccountEditMFADisableSubmit",
|
||||
94: "routes.AccountEditEmail",
|
||||
95: "routes.AccountEditEmailTokenSubmit",
|
||||
96: "routes.AccountLogins",
|
||||
97: "routes.LevelList",
|
||||
98: "routes.ViewProfile",
|
||||
99: "routes.BanUserSubmit",
|
||||
100: "routes.UnbanUser",
|
||||
101: "routes.ActivateUser",
|
||||
102: "routes.IPSearch",
|
||||
103: "routes.CreateTopicSubmit",
|
||||
104: "routes.EditTopicSubmit",
|
||||
105: "routes.DeleteTopicSubmit",
|
||||
106: "routes.StickTopicSubmit",
|
||||
107: "routes.UnstickTopicSubmit",
|
||||
108: "routes.LockTopicSubmit",
|
||||
109: "routes.UnlockTopicSubmit",
|
||||
110: "routes.MoveTopicSubmit",
|
||||
111: "routes.LikeTopicSubmit",
|
||||
112: "routes.AddAttachToTopicSubmit",
|
||||
113: "routes.RemoveAttachFromTopicSubmit",
|
||||
114: "routes.ViewTopic",
|
||||
115: "routes.CreateReplySubmit",
|
||||
116: "routes.ReplyEditSubmit",
|
||||
117: "routes.ReplyDeleteSubmit",
|
||||
118: "routes.ReplyLikeSubmit",
|
||||
119: "routes.AddAttachToReplySubmit",
|
||||
120: "routes.RemoveAttachFromReplySubmit",
|
||||
121: "routes.ProfileReplyCreateSubmit",
|
||||
122: "routes.ProfileReplyEditSubmit",
|
||||
123: "routes.ProfileReplyDeleteSubmit",
|
||||
124: "routes.PollVote",
|
||||
125: "routes.PollResults",
|
||||
126: "routes.AccountLogin",
|
||||
127: "routes.AccountRegister",
|
||||
128: "routes.AccountLogout",
|
||||
129: "routes.AccountLoginSubmit",
|
||||
130: "routes.AccountLoginMFAVerify",
|
||||
131: "routes.AccountLoginMFAVerifySubmit",
|
||||
132: "routes.AccountRegisterSubmit",
|
||||
133: "routes.AccountPasswordReset",
|
||||
134: "routes.AccountPasswordResetSubmit",
|
||||
135: "routes.AccountPasswordResetToken",
|
||||
136: "routes.AccountPasswordResetTokenSubmit",
|
||||
137: "routes.DynamicRoute",
|
||||
138: "routes.UploadedFile",
|
||||
139: "routes.StaticFile",
|
||||
140: "routes.RobotsTxt",
|
||||
141: "routes.SitemapXml",
|
||||
142: "routes.BadRoute",
|
||||
143: "routes.HTTPSRedirect",
|
||||
}
|
||||
var osMapEnum = map[string]int{
|
||||
"unknown": 0,
|
||||
|
@ -612,7 +615,7 @@ type HTTPSRedirect struct {
|
|||
|
||||
func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
w.Header().Set("Connection", "close")
|
||||
counters.RouteViewCounter.Bump(142)
|
||||
counters.RouteViewCounter.Bump(143)
|
||||
dest := "https://" + req.Host + req.URL.String()
|
||||
http.Redirect(w, req, dest, http.StatusTemporaryRedirect)
|
||||
}
|
||||
|
@ -816,7 +819,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
counters.GlobalViewCounter.Bump()
|
||||
|
||||
if prefix == "/static" {
|
||||
counters.RouteViewCounter.Bump(138)
|
||||
counters.RouteViewCounter.Bump(139)
|
||||
req.URL.Path += extraData
|
||||
routes.StaticFile(w, req)
|
||||
return
|
||||
|
@ -1504,13 +1507,21 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
|
||||
counters.RouteViewCounter.Bump(70)
|
||||
err = panel.AnalyticsPosts(w,req,user)
|
||||
case "/panel/analytics/topics/":
|
||||
case "/panel/analytics/memory/":
|
||||
err = c.ParseForm(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(71)
|
||||
err = panel.AnalyticsMemory(w,req,user)
|
||||
case "/panel/analytics/topics/":
|
||||
err = c.ParseForm(w,req,user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(72)
|
||||
err = panel.AnalyticsTopics(w,req,user)
|
||||
case "/panel/analytics/forums/":
|
||||
err = c.ParseForm(w,req,user)
|
||||
|
@ -1518,16 +1529,16 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(72)
|
||||
counters.RouteViewCounter.Bump(73)
|
||||
err = panel.AnalyticsForums(w,req,user)
|
||||
case "/panel/groups/":
|
||||
counters.RouteViewCounter.Bump(73)
|
||||
counters.RouteViewCounter.Bump(74)
|
||||
err = panel.Groups(w,req,user)
|
||||
case "/panel/groups/edit/":
|
||||
counters.RouteViewCounter.Bump(74)
|
||||
counters.RouteViewCounter.Bump(75)
|
||||
err = panel.GroupsEdit(w,req,user,extraData)
|
||||
case "/panel/groups/edit/perms/":
|
||||
counters.RouteViewCounter.Bump(75)
|
||||
counters.RouteViewCounter.Bump(76)
|
||||
err = panel.GroupsEditPerms(w,req,user,extraData)
|
||||
case "/panel/groups/edit/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1535,7 +1546,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(76)
|
||||
counters.RouteViewCounter.Bump(77)
|
||||
err = panel.GroupsEditSubmit(w,req,user,extraData)
|
||||
case "/panel/groups/edit/perms/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1543,7 +1554,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(77)
|
||||
counters.RouteViewCounter.Bump(78)
|
||||
err = panel.GroupsEditPermsSubmit(w,req,user,extraData)
|
||||
case "/panel/groups/create/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1551,7 +1562,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(78)
|
||||
counters.RouteViewCounter.Bump(79)
|
||||
err = panel.GroupsCreateSubmit(w,req,user)
|
||||
case "/panel/backups/":
|
||||
err = c.SuperAdminOnly(w,req,user)
|
||||
|
@ -1565,13 +1576,13 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
w.Header().Del("Content-Type")
|
||||
w.Header().Del("Content-Encoding")
|
||||
}
|
||||
counters.RouteViewCounter.Bump(79)
|
||||
counters.RouteViewCounter.Bump(80)
|
||||
err = panel.Backups(w,req,user,extraData)
|
||||
case "/panel/logs/regs/":
|
||||
counters.RouteViewCounter.Bump(80)
|
||||
counters.RouteViewCounter.Bump(81)
|
||||
err = panel.LogsRegs(w,req,user)
|
||||
case "/panel/logs/mod/":
|
||||
counters.RouteViewCounter.Bump(81)
|
||||
counters.RouteViewCounter.Bump(82)
|
||||
err = panel.LogsMod(w,req,user)
|
||||
case "/panel/debug/":
|
||||
err = c.AdminOnly(w,req,user)
|
||||
|
@ -1579,10 +1590,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(82)
|
||||
counters.RouteViewCounter.Bump(83)
|
||||
err = panel.Debug(w,req,user)
|
||||
default:
|
||||
counters.RouteViewCounter.Bump(83)
|
||||
counters.RouteViewCounter.Bump(84)
|
||||
err = panel.Dashboard(w,req,user)
|
||||
}
|
||||
case "/user":
|
||||
|
@ -1593,7 +1604,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(84)
|
||||
counters.RouteViewCounter.Bump(85)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1605,7 +1616,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(85)
|
||||
counters.RouteViewCounter.Bump(86)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1622,7 +1633,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(86)
|
||||
counters.RouteViewCounter.Bump(87)
|
||||
err = routes.AccountEditPasswordSubmit(w,req,user)
|
||||
case "/user/edit/avatar/submit/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
|
@ -1639,7 +1650,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(87)
|
||||
counters.RouteViewCounter.Bump(88)
|
||||
err = routes.AccountEditAvatarSubmit(w,req,user)
|
||||
case "/user/edit/username/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1652,7 +1663,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(88)
|
||||
counters.RouteViewCounter.Bump(89)
|
||||
err = routes.AccountEditUsernameSubmit(w,req,user)
|
||||
case "/user/edit/mfa/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
|
@ -1660,7 +1671,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(89)
|
||||
counters.RouteViewCounter.Bump(90)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1672,7 +1683,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(90)
|
||||
counters.RouteViewCounter.Bump(91)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1689,7 +1700,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(91)
|
||||
counters.RouteViewCounter.Bump(92)
|
||||
err = routes.AccountEditMFASetupSubmit(w,req,user)
|
||||
case "/user/edit/mfa/disable/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1702,7 +1713,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(92)
|
||||
counters.RouteViewCounter.Bump(93)
|
||||
err = routes.AccountEditMFADisableSubmit(w,req,user)
|
||||
case "/user/edit/email/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
|
@ -1710,14 +1721,14 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(93)
|
||||
counters.RouteViewCounter.Bump(94)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = routes.AccountEditEmail(w,req,user,head)
|
||||
case "/user/edit/token/":
|
||||
counters.RouteViewCounter.Bump(94)
|
||||
counters.RouteViewCounter.Bump(95)
|
||||
err = routes.AccountEditEmailTokenSubmit(w,req,user,extraData)
|
||||
case "/user/edit/logins/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
|
@ -1725,7 +1736,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(95)
|
||||
counters.RouteViewCounter.Bump(96)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1737,7 +1748,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(96)
|
||||
counters.RouteViewCounter.Bump(97)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1745,7 +1756,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
err = routes.LevelList(w,req,user,head)
|
||||
default:
|
||||
req.URL.Path += extraData
|
||||
counters.RouteViewCounter.Bump(97)
|
||||
counters.RouteViewCounter.Bump(98)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1765,7 +1776,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(98)
|
||||
counters.RouteViewCounter.Bump(99)
|
||||
err = routes.BanUserSubmit(w,req,user,extraData)
|
||||
case "/users/unban/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1778,7 +1789,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(99)
|
||||
counters.RouteViewCounter.Bump(100)
|
||||
err = routes.UnbanUser(w,req,user,extraData)
|
||||
case "/users/activate/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1791,7 +1802,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(100)
|
||||
counters.RouteViewCounter.Bump(101)
|
||||
err = routes.ActivateUser(w,req,user,extraData)
|
||||
case "/users/ips/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
|
@ -1799,7 +1810,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(101)
|
||||
counters.RouteViewCounter.Bump(102)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1823,7 +1834,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(102)
|
||||
counters.RouteViewCounter.Bump(103)
|
||||
err = routes.CreateTopicSubmit(w,req,user)
|
||||
case "/topic/edit/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1836,7 +1847,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(103)
|
||||
counters.RouteViewCounter.Bump(104)
|
||||
err = routes.EditTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/delete/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1850,7 +1861,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
}
|
||||
|
||||
req.URL.Path += extraData
|
||||
counters.RouteViewCounter.Bump(104)
|
||||
counters.RouteViewCounter.Bump(105)
|
||||
err = routes.DeleteTopicSubmit(w,req,user)
|
||||
case "/topic/stick/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1863,7 +1874,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(105)
|
||||
counters.RouteViewCounter.Bump(106)
|
||||
err = routes.StickTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/unstick/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1876,7 +1887,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(106)
|
||||
counters.RouteViewCounter.Bump(107)
|
||||
err = routes.UnstickTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/lock/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1890,7 +1901,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
}
|
||||
|
||||
req.URL.Path += extraData
|
||||
counters.RouteViewCounter.Bump(107)
|
||||
counters.RouteViewCounter.Bump(108)
|
||||
err = routes.LockTopicSubmit(w,req,user)
|
||||
case "/topic/unlock/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1903,7 +1914,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(108)
|
||||
counters.RouteViewCounter.Bump(109)
|
||||
err = routes.UnlockTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/move/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1916,7 +1927,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(109)
|
||||
counters.RouteViewCounter.Bump(110)
|
||||
err = routes.MoveTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/like/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1929,7 +1940,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(110)
|
||||
counters.RouteViewCounter.Bump(111)
|
||||
err = routes.LikeTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/attach/add/submit/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
|
@ -1946,7 +1957,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(111)
|
||||
counters.RouteViewCounter.Bump(112)
|
||||
err = routes.AddAttachToTopicSubmit(w,req,user,extraData)
|
||||
case "/topic/attach/remove/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1959,10 +1970,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(112)
|
||||
counters.RouteViewCounter.Bump(113)
|
||||
err = routes.RemoveAttachFromTopicSubmit(w,req,user,extraData)
|
||||
default:
|
||||
counters.RouteViewCounter.Bump(113)
|
||||
counters.RouteViewCounter.Bump(114)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1986,7 +1997,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(114)
|
||||
counters.RouteViewCounter.Bump(115)
|
||||
err = routes.CreateReplySubmit(w,req,user)
|
||||
case "/reply/edit/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -1999,7 +2010,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(115)
|
||||
counters.RouteViewCounter.Bump(116)
|
||||
err = routes.ReplyEditSubmit(w,req,user,extraData)
|
||||
case "/reply/delete/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -2012,7 +2023,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(116)
|
||||
counters.RouteViewCounter.Bump(117)
|
||||
err = routes.ReplyDeleteSubmit(w,req,user,extraData)
|
||||
case "/reply/like/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -2025,7 +2036,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(117)
|
||||
counters.RouteViewCounter.Bump(118)
|
||||
err = routes.ReplyLikeSubmit(w,req,user,extraData)
|
||||
case "/reply/attach/add/submit/":
|
||||
err = c.MemberOnly(w,req,user)
|
||||
|
@ -2042,7 +2053,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(118)
|
||||
counters.RouteViewCounter.Bump(119)
|
||||
err = routes.AddAttachToReplySubmit(w,req,user,extraData)
|
||||
case "/reply/attach/remove/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -2055,7 +2066,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(119)
|
||||
counters.RouteViewCounter.Bump(120)
|
||||
err = routes.RemoveAttachFromReplySubmit(w,req,user,extraData)
|
||||
}
|
||||
case "/profile":
|
||||
|
@ -2071,7 +2082,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(120)
|
||||
counters.RouteViewCounter.Bump(121)
|
||||
err = routes.ProfileReplyCreateSubmit(w,req,user)
|
||||
case "/profile/reply/edit/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -2084,7 +2095,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(121)
|
||||
counters.RouteViewCounter.Bump(122)
|
||||
err = routes.ProfileReplyEditSubmit(w,req,user,extraData)
|
||||
case "/profile/reply/delete/submit/":
|
||||
err = c.NoSessionMismatch(w,req,user)
|
||||
|
@ -2097,7 +2108,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(122)
|
||||
counters.RouteViewCounter.Bump(123)
|
||||
err = routes.ProfileReplyDeleteSubmit(w,req,user,extraData)
|
||||
}
|
||||
case "/poll":
|
||||
|
@ -2113,23 +2124,23 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(123)
|
||||
counters.RouteViewCounter.Bump(124)
|
||||
err = routes.PollVote(w,req,user,extraData)
|
||||
case "/poll/results/":
|
||||
counters.RouteViewCounter.Bump(124)
|
||||
counters.RouteViewCounter.Bump(125)
|
||||
err = routes.PollResults(w,req,user,extraData)
|
||||
}
|
||||
case "/accounts":
|
||||
switch(req.URL.Path) {
|
||||
case "/accounts/login/":
|
||||
counters.RouteViewCounter.Bump(125)
|
||||
counters.RouteViewCounter.Bump(126)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = routes.AccountLogin(w,req,user,head)
|
||||
case "/accounts/create/":
|
||||
counters.RouteViewCounter.Bump(126)
|
||||
counters.RouteViewCounter.Bump(127)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -2146,7 +2157,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(127)
|
||||
counters.RouteViewCounter.Bump(128)
|
||||
err = routes.AccountLogout(w,req,user)
|
||||
case "/accounts/login/submit/":
|
||||
err = c.ParseForm(w,req,user)
|
||||
|
@ -2154,10 +2165,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(128)
|
||||
counters.RouteViewCounter.Bump(129)
|
||||
err = routes.AccountLoginSubmit(w,req,user)
|
||||
case "/accounts/mfa_verify/":
|
||||
counters.RouteViewCounter.Bump(129)
|
||||
counters.RouteViewCounter.Bump(130)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -2169,7 +2180,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(130)
|
||||
counters.RouteViewCounter.Bump(131)
|
||||
err = routes.AccountLoginMFAVerifySubmit(w,req,user)
|
||||
case "/accounts/create/submit/":
|
||||
err = c.ParseForm(w,req,user)
|
||||
|
@ -2177,10 +2188,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(131)
|
||||
counters.RouteViewCounter.Bump(132)
|
||||
err = routes.AccountRegisterSubmit(w,req,user)
|
||||
case "/accounts/password-reset/":
|
||||
counters.RouteViewCounter.Bump(132)
|
||||
counters.RouteViewCounter.Bump(133)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -2192,10 +2203,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(133)
|
||||
counters.RouteViewCounter.Bump(134)
|
||||
err = routes.AccountPasswordResetSubmit(w,req,user)
|
||||
case "/accounts/password-reset/token/":
|
||||
counters.RouteViewCounter.Bump(134)
|
||||
counters.RouteViewCounter.Bump(135)
|
||||
head, err := c.UserCheck(w,req,&user)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -2207,7 +2218,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
return err
|
||||
}
|
||||
|
||||
counters.RouteViewCounter.Bump(135)
|
||||
counters.RouteViewCounter.Bump(136)
|
||||
err = routes.AccountPasswordResetTokenSubmit(w,req,user)
|
||||
}
|
||||
/*case "/sitemaps": // TODO: Count these views
|
||||
|
@ -2223,7 +2234,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
w.Header().Del("Content-Type")
|
||||
w.Header().Del("Content-Encoding")
|
||||
}
|
||||
counters.RouteViewCounter.Bump(137)
|
||||
counters.RouteViewCounter.Bump(138)
|
||||
req.URL.Path += extraData
|
||||
// TODO: Find a way to propagate errors up from this?
|
||||
r.UploadHandler(w,req) // TODO: Count these views
|
||||
|
@ -2233,7 +2244,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
// TODO: Add support for favicons and robots.txt files
|
||||
switch(extraData) {
|
||||
case "robots.txt":
|
||||
counters.RouteViewCounter.Bump(139)
|
||||
counters.RouteViewCounter.Bump(140)
|
||||
return routes.RobotsTxt(w,req)
|
||||
case "favicon.ico":
|
||||
req.URL.Path = "/static"+req.URL.Path+extraData
|
||||
|
@ -2241,7 +2252,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
routes.StaticFile(w,req)
|
||||
return nil
|
||||
/*case "sitemap.xml":
|
||||
counters.RouteViewCounter.Bump(140)
|
||||
counters.RouteViewCounter.Bump(141)
|
||||
return routes.SitemapXml(w,req)*/
|
||||
}
|
||||
return c.NotFound(w,req,nil)
|
||||
|
@ -2252,7 +2263,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
r.RUnlock()
|
||||
|
||||
if ok {
|
||||
counters.RouteViewCounter.Bump(136) // TODO: Be more specific about *which* dynamic route it is
|
||||
counters.RouteViewCounter.Bump(137) // TODO: Be more specific about *which* dynamic route it is
|
||||
req.URL.Path += extraData
|
||||
return handle(w,req,user)
|
||||
}
|
||||
|
@ -2263,7 +2274,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
|||
} else {
|
||||
r.DumpRequest(req,"Bad Route")
|
||||
}
|
||||
counters.RouteViewCounter.Bump(141)
|
||||
counters.RouteViewCounter.Bump(142)
|
||||
return c.NotFound(w,req,nil)
|
||||
}
|
||||
return err
|
||||
|
|
|
@ -740,6 +740,7 @@
|
|||
"panel_menu_statistics_systems":"Systems",
|
||||
"panel_menu_statistics_languages":"Languages",
|
||||
"panel_menu_statistics_referrers":"Referrers",
|
||||
"panel_menu_statistics_memory":"Memory",
|
||||
"panel_menu_reports":"Reports",
|
||||
"panel_menu_logs":"Logs",
|
||||
"panel_menu_logs_registrations":"Registrations",
|
||||
|
@ -755,6 +756,8 @@
|
|||
"panel_dashboard_cpu_desc":"The global CPU usage of this server",
|
||||
"panel_dashboard_ram":"RAM: %s",
|
||||
"panel_dashboard_ram_desc":"The global RAM usage of this server",
|
||||
"panel_dashboard_memused":"Mem: %.1f%s",
|
||||
"panel_dashboard_memused_desc":"The amount of memory likely being used by this instance",
|
||||
"panel_dashboard_online": "%d%s online",
|
||||
"panel_dashboard_online_desc":"The number of people who are currently online",
|
||||
"panel_dashboard_guests_online":"%d%s guests online",
|
||||
|
@ -880,6 +883,7 @@
|
|||
"panel_statistics_operating_systems_head":"Operating Systems",
|
||||
"panel_statistics_topic_counts_head":"Topic Counts",
|
||||
"panel_statistics_requests_head":"Requests",
|
||||
"panel_statistics_memory_head":"Memory",
|
||||
|
||||
"panel_statistics_time_range_one_year":"1 year",
|
||||
"panel_statistics_time_range_three_months":"3 months",
|
||||
|
|
4
main.go
4
main.go
|
@ -218,6 +218,10 @@ func afterDBInit() (err error) {
|
|||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
counters.MemoryCounter, err = counters.NewMemoryCounter(acc)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ func init() {
|
|||
addPatch(16, patch16)
|
||||
addPatch(17, patch17)
|
||||
addPatch(18, patch18)
|
||||
addPatch(19, patch19)
|
||||
}
|
||||
|
||||
func patch0(scanner *bufio.Scanner) (err error) {
|
||||
|
@ -593,3 +594,12 @@ func patch17(scanner *bufio.Scanner) error {
|
|||
func patch18(scanner *bufio.Scanner) error {
|
||||
return execStmt(qgen.Builder.AddColumn("forums", tblColumn{"order", "int", 0, false, false, "0"}, nil))
|
||||
}
|
||||
|
||||
func patch19(scanner *bufio.Scanner) error {
|
||||
return execStmt(qgen.Builder.CreateTable("memchunks", "", "",
|
||||
[]tblColumn{
|
||||
tblColumn{"count", "int", 0, false, false, "0"},
|
||||
tblColumn{"createdAt", "datetime", 0, false, false, ""},
|
||||
}, nil,
|
||||
))
|
||||
}
|
|
@ -2,29 +2,41 @@
|
|||
|
||||
})*/
|
||||
|
||||
const Kilobyte = 1024;
|
||||
const Megabyte = Kilobyte * 1024;
|
||||
const Gigabyte = Megabyte * 1024;
|
||||
const Terabyte = Gigabyte * 1024;
|
||||
const Petabyte = Terabyte * 1024;
|
||||
|
||||
function convertByteUnit(bytes) {
|
||||
if(bytes >= Petabyte) return Math.ceil(bytes / Petabyte) + "PB";
|
||||
else if(bytes >= Terabyte) return Math.ceil(bytes / Terabyte) + "TB";
|
||||
else if(bytes >= Gigabyte) return Math.ceil(bytes / Gigabyte) + "GB";
|
||||
else if(bytes >= Megabyte) return Math.ceil(bytes / Megabyte) + "MB";
|
||||
else if(bytes >= Kilobyte) return Math.ceil(bytes / Kilobyte) + "KB";
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// TODO: Fully localise this
|
||||
// TODO: Load rawLabels and seriesData dynamically rather than potentially fiddling with nonces for the CSP?
|
||||
function buildStatsChart(rawLabels, seriesData, timeRange, legendNames) {
|
||||
function buildStatsChart(rawLabels, seriesData, timeRange, legendNames, bytes = false) {
|
||||
console.log("buildStatsChart");
|
||||
let labels = [];
|
||||
let aphrases = phraseBox["analytics"];
|
||||
if(timeRange=="one-year") {
|
||||
labels = [aphrases["analytics.now"],"1" + aphrases["analytics.months_short"]];
|
||||
for(let i = 2; i < 12; i++) {
|
||||
let label = i + aphrases["analytics.months_short"];
|
||||
labels.push(label);
|
||||
labels.push(i + aphrases["analytics.months_short"]);
|
||||
}
|
||||
} else if(timeRange=="three-months") {
|
||||
labels = [aphrases["analytics.now"],"3" + aphrases["analytics.days_short"]]
|
||||
for(let i = 6; i < 90; i = i + 3) {
|
||||
let label = i + aphrases["analytics.days_short"];
|
||||
labels.push(label);
|
||||
labels.push(i + aphrases["analytics.days_short"]);
|
||||
}
|
||||
} else if(timeRange=="one-month") {
|
||||
labels = [aphrases["analytics.now"],"1" + aphrases["analytics.days_short"]];
|
||||
for(let i = 2; i < 30; i++) {
|
||||
let label = i + aphrases["analytics.days_short"];
|
||||
labels.push(label);
|
||||
labels.push(i + aphrases["analytics.days_short"]);
|
||||
}
|
||||
} else if(timeRange=="one-week") {
|
||||
labels = [aphrases["analytics.now"]];
|
||||
|
@ -43,18 +55,15 @@ function buildStatsChart(rawLabels, seriesData, timeRange, legendNames) {
|
|||
}
|
||||
}
|
||||
labels = labels.reverse()
|
||||
for(let i = 0; i < seriesData.length;i++) {
|
||||
for(let i = 0; i < seriesData.length; i++) {
|
||||
seriesData[i] = seriesData[i].reverse();
|
||||
}
|
||||
|
||||
let config = {
|
||||
height: '250px',
|
||||
};
|
||||
let config = {height: '250px', plugins:[]};
|
||||
if(legendNames.length > 0) config.plugins = [
|
||||
Chartist.plugins.legend({
|
||||
legendNames: legendNames,
|
||||
})
|
||||
];
|
||||
Chartist.plugins.legend({legendNames: legendNames})
|
||||
];
|
||||
if(bytes) config.plugins.push(Chartist.plugins.byteUnits());
|
||||
Chartist.Line('.ct_chart', {
|
||||
labels: labels,
|
||||
series: seriesData,
|
||||
|
|
|
@ -212,6 +212,7 @@ func panelRoutes() *RouteGroup {
|
|||
View("panel.AnalyticsLanguageViews", "/panel/analytics/lang/", "extraData"),
|
||||
View("panel.AnalyticsReferrerViews", "/panel/analytics/referrer/", "extraData"),
|
||||
View("panel.AnalyticsPosts", "/panel/analytics/posts/").Before("ParseForm"),
|
||||
View("panel.AnalyticsMemory", "/panel/analytics/memory/").Before("ParseForm"),
|
||||
View("panel.AnalyticsTopics", "/panel/analytics/topics/").Before("ParseForm"),
|
||||
View("panel.AnalyticsForums", "/panel/analytics/forums/").Before("ParseForm"),
|
||||
|
||||
|
|
|
@ -464,6 +464,58 @@ func AnalyticsPosts(w http.ResponseWriter, r *http.Request, user c.User) c.Route
|
|||
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "panel_analytics_right","analytics","panel_analytics_posts", pi})
|
||||
}
|
||||
|
||||
func AnalyticsMemory(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
|
||||
basePage, ferr := PreAnalyticsDetail(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
timeRange, err := analyticsTimeRange(r.FormValue("timeRange"))
|
||||
if err != nil {
|
||||
return c.LocalError(err.Error(), w, r, user)
|
||||
}
|
||||
revLabelList, labelList, viewMap := analyticsTimeRangeToLabelList(timeRange)
|
||||
|
||||
c.DebugLog("in panel.AnalyticsMemory")
|
||||
rows, err := qgen.NewAcc().Select("memchunks").Columns("count, createdAt").DateCutoff("createdAt", timeRange.Quantity, timeRange.Unit).Query()
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
viewMap, err = analyticsRowsToViewMap(rows, labelList, viewMap)
|
||||
if err != nil {
|
||||
return c.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
var divBy int64 = 1
|
||||
switch timeRange.Range {
|
||||
case "one-year":
|
||||
divBy = 2 * 30 * 12
|
||||
case "three-months":
|
||||
divBy = 2 * 30 * 3
|
||||
case "one-month":
|
||||
divBy = 2 * 30
|
||||
case "one-week":
|
||||
divBy = 1 * 7
|
||||
case "two-days":
|
||||
divBy = 4
|
||||
case "one-day":
|
||||
divBy = 2
|
||||
}
|
||||
|
||||
// TODO: Adjust for the missing chunks in week and month
|
||||
var viewList []int64
|
||||
var viewItems []c.PanelAnalyticsItemUnit
|
||||
for _, value := range revLabelList {
|
||||
viewMap[value] = viewMap[value] / divBy
|
||||
viewList = append(viewList, viewMap[value])
|
||||
cv, cu := c.ConvertByteUnit(float64(viewMap[value]))
|
||||
viewItems = append(viewItems, c.PanelAnalyticsItemUnit{Time: value, Unit: cu, Count: int64(cv)})
|
||||
}
|
||||
graph := c.PanelTimeGraph{Series: [][]int64{viewList}, Labels: labelList}
|
||||
c.DebugLogf("graph: %+v\n", graph)
|
||||
pi := c.PanelAnalyticsStdUnit{graph, viewItems, timeRange.Range, timeRange.Unit, "time"}
|
||||
return renderTemplate("panel", w, r, basePage.Header, c.Panel{basePage, "panel_analytics_right","analytics","panel_analytics_memory", pi})
|
||||
}
|
||||
|
||||
func analyticsRowsToNameMap(rows *sql.Rows) (map[string]int, error) {
|
||||
nameMap := make(map[string]int)
|
||||
defer rows.Close()
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"runtime"
|
||||
|
||||
c "github.com/Azareal/Gosora/common"
|
||||
p "github.com/Azareal/Gosora/common/phrases"
|
||||
|
@ -113,6 +114,10 @@ func Dashboard(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError
|
|||
ramColour = lessThanSwitch(int(ramperc), 50, 75)
|
||||
}
|
||||
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
memCount, memUnit := c.ConvertByteUnit(float64(m.Sys))
|
||||
|
||||
greaterThanSwitch := func(number int, lowerBound int, midBound int) string {
|
||||
switch {
|
||||
case number > midBound:
|
||||
|
@ -166,14 +171,16 @@ func Dashboard(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError
|
|||
return c.InternalError(intErr, w, r)
|
||||
}
|
||||
|
||||
// TODO: Localise these
|
||||
var gridElements = []GE{
|
||||
// TODO: Implement a check for new versions of Gosora
|
||||
// TODO: Localise this
|
||||
//GE{"dash-version", "v" + version.String(), 0, "grid_istat stat_green", "", "", "Gosora is up-to-date :)"},
|
||||
GE{"dash-version", "v" + c.SoftwareVersion.String(), 0, "grid_istat", "", "", ""},
|
||||
|
||||
GE{"dash-cpu", p.GetTmplPhrasef("panel_dashboard_cpu",cpustr), 1, "grid_istat " + cpuColour, "", "", p.GetTmplPhrase("panel_dashboard_cpu_desc")},
|
||||
GE{"dash-ram", p.GetTmplPhrasef("panel_dashboard_ram",ramstr), 2, "grid_istat " + ramColour, "", "", p.GetTmplPhrase("panel_dashboard_ram_desc")},
|
||||
|
||||
GE{"dash-memused", p.GetTmplPhrasef("panel_dashboard_memused",memCount, memUnit), 2, "grid_istat", "", "", p.GetTmplPhrase("panel_dashboard_memused_desc")},
|
||||
}
|
||||
var addElement = func(element GE) {
|
||||
gridElements = append(gridElements, element)
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
CREATE TABLE [memchunks] (
|
||||
[count] int DEFAULT 0 not null,
|
||||
[createdAt] datetime not null
|
||||
);
|
|
@ -0,0 +1,4 @@
|
|||
CREATE TABLE `memchunks` (
|
||||
`count` int DEFAULT 0 not null,
|
||||
`createdAt` datetime not null
|
||||
);
|
|
@ -0,0 +1,4 @@
|
|||
CREATE TABLE "memchunks" (
|
||||
`count` int DEFAULT 0 not null,
|
||||
`createdAt` timestamp not null
|
||||
);
|
|
@ -1,11 +1,11 @@
|
|||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{.FriendlyAgent}}{{lang "panel_statistics_views_head_suffix"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/agent/{{.Agent}}" method="get"></form>
|
||||
<div id="panel_analytics_views" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{.FriendlyAgent}}{{lang "panel_statistics_views_head_suffix"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/agent/{{.Agent}}" method="get"></form>
|
||||
<div id="panel_analytics_views" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
{{template "panel_analytics_script.html" . }}
|
|
@ -1,19 +1,19 @@
|
|||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_user_agents_head"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/agents/" method="get"></form>
|
||||
<div id="panel_analytics_agents_chart" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div id="panel_analytics_agents" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/analytics/agent/{{.Agent}}" class="panel_upshift">{{.FriendlyAgent}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span>
|
||||
</div>
|
||||
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_user_agents_no_user_agents"}}</div>{{end}}
|
||||
</div>
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_user_agents_head"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/agents/" method="get"></form>
|
||||
<div id="panel_analytics_agents_chart" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div id="panel_analytics_agents" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/analytics/agent/{{.Agent}}" class="panel_upshift">{{.FriendlyAgent}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span>
|
||||
</div>
|
||||
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_user_agents_no_user_agents"}}</div>{{end}}
|
||||
</div>
|
||||
{{template "panel_analytics_script.html" . }}
|
|
@ -1,11 +1,11 @@
|
|||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{.FriendlyAgent}}{{lang "panel_statistics_views_head_suffix"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/forum/{{.Agent}}" method="get"></form>
|
||||
<div id="panel_analytics_views" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{.FriendlyAgent}}{{lang "panel_statistics_views_head_suffix"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/forum/{{.Agent}}" method="get"></form>
|
||||
<div id="panel_analytics_views" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
{{template "panel_analytics_script.html" . }}
|
|
@ -1,11 +1,11 @@
|
|||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{.FriendlyAgent}}{{lang "panel_statistics_views_head_suffix"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/lang/{{.Agent}}" method="get"></form>
|
||||
<div id="panel_analytics_langs" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{.FriendlyAgent}}{{lang "panel_statistics_views_head_suffix"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/lang/{{.Agent}}" method="get"></form>
|
||||
<div id="panel_analytics_langs" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
{{template "panel_analytics_script.html" . }}
|
|
@ -1,19 +1,19 @@
|
|||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_languages_head"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/langs/" method="get"></form>
|
||||
<div id="panel_analytics_langs_chart" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div id="panel_analytics_langs" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/analytics/lang/{{.Agent}}" class="panel_upshift">{{.FriendlyAgent}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span>
|
||||
</div>
|
||||
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_languages_no_languages"}}</div>{{end}}
|
||||
</div>
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_languages_head"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/langs/" method="get"></form>
|
||||
<div id="panel_analytics_langs_chart" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div id="panel_analytics_langs" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/analytics/lang/{{.Agent}}" class="panel_upshift">{{.FriendlyAgent}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span>
|
||||
</div>
|
||||
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_languages_no_languages"}}</div>{{end}}
|
||||
</div>
|
||||
{{template "panel_analytics_script.html" . }}
|
|
@ -0,0 +1,71 @@
|
|||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_memory_head"}}</h1>
|
||||
<select form="timeRangeForm" class="timeRangeSelector to_right" 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>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/memory/" method="get"></form>
|
||||
<div id="panel_analytics_memory" class="colstack_graph_holder">
|
||||
<div class="ct_chart" aria-label="{{lang "panel_statistics_post_counts_chart_aria"}}"></div>
|
||||
</div>
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_details_head"}}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div id="panel_analytics_posts_table" class="colstack_item rowlist" aria-label="{{lang "panel_statistics_post_counts_table_aria"}}">
|
||||
{{range .ViewItems}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a class="panel_upshift {{if or (or (or (eq $.TimeRange "six-hours") (eq $.TimeRange "twelve-hours")) (eq $.TimeRange "one-day")) (eq $.TimeRange "two-days")}}unix_to_24_hour_time{{else}}unix_to_date{{end}}">{{.Time}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}{{.Unit}}</span>
|
||||
</div>
|
||||
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_post_counts_no_post_counts"}}</div>{{end}}
|
||||
</div>
|
||||
<script>
|
||||
let rawLabels = [{{range .Graph.Labels}}
|
||||
{{.}},{{end}}
|
||||
];
|
||||
let seriesData = [{{range .Graph.Series}}[{{range .}}
|
||||
{{.}},{{end}}
|
||||
],{{end}}
|
||||
];
|
||||
let legendNames = [{{range .Graph.Legends}}
|
||||
{{.}},{{end}}
|
||||
];
|
||||
|
||||
(function(window, document, Chartist) {
|
||||
'use strict';
|
||||
|
||||
Chartist.plugins = Chartist.plugins || {};
|
||||
Chartist.plugins.byteUnits = function(options) {
|
||||
options = Chartist.extend({}, {}, options);
|
||||
|
||||
return function byteUnits(chart) {
|
||||
if (chart instanceof Chartist.Line) {
|
||||
chart.on('created', function() {
|
||||
console.log("running created")
|
||||
let vbits = document.getElementsByClassName("ct-vertical");
|
||||
for(let i = 0; i < vbits.length; i++) {
|
||||
vbits[i].innerHTML = convertByteUnit(vbits[i].innerHTML);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
}(window, document, Chartist));
|
||||
addInitHook("after_phrases", () => {
|
||||
addInitHook("end_init", () => {
|
||||
addInitHook("analytics_loaded", () => {
|
||||
buildStatsChart(rawLabels, seriesData, "{{.TimeRange}}",legendNames, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -1,19 +1,19 @@
|
|||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_routes_head"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/routes/" method="get"></form>
|
||||
<div id="panel_analytics_routes_chart" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div id="panel_analytics_routes" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/analytics/route/{{.Route}}" class="panel_upshift">{{.Route}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span>
|
||||
</div>
|
||||
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_routes_no_routes"}}</div>{{end}}
|
||||
</div>
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_routes_head"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/routes/" method="get"></form>
|
||||
<div id="panel_analytics_routes_chart" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div id="panel_analytics_routes" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/analytics/route/{{.Route}}" class="panel_upshift">{{.Route}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span>
|
||||
</div>
|
||||
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_routes_no_routes"}}</div>{{end}}
|
||||
</div>
|
||||
{{template "panel_analytics_script.html" . }}
|
|
@ -1,19 +1,19 @@
|
|||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_operating_systems_head"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/systems/" method="get"></form>
|
||||
<div id="panel_analytics_systems_chart" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div id="panel_analytics_systems" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/analytics/system/{{.Agent}}" class="panel_upshift">{{.FriendlyAgent}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span>
|
||||
</div>
|
||||
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_operating_systems_no_operating_systems"}}</div>{{end}}
|
||||
</div>
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem">
|
||||
<h1>{{lang "panel_statistics_operating_systems_head"}}</h1>
|
||||
{{template "panel_analytics_time_range.html" . }}
|
||||
</div>
|
||||
</div>
|
||||
<form id="timeRangeForm" name="timeRangeForm" action="/panel/analytics/systems/" method="get"></form>
|
||||
<div id="panel_analytics_systems_chart" class="colstack_graph_holder">
|
||||
<div class="ct_chart"></div>
|
||||
</div>
|
||||
<div id="panel_analytics_systems" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/analytics/system/{{.Agent}}" class="panel_upshift">{{.FriendlyAgent}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}{{lang "panel_statistics_views_suffix"}}</span>
|
||||
</div>
|
||||
{{else}}<div class="rowitem passive rowmsg">{{lang "panel_statistics_operating_systems_no_operating_systems"}}</div>{{end}}
|
||||
</div>
|
||||
{{template "panel_analytics_script.html" . }}
|
|
@ -62,6 +62,9 @@
|
|||
<div class="rowitem passive submenu">
|
||||
<a href="/panel/analytics/referrers/">{{lang "panel_menu_statistics_referrers"}}</a>
|
||||
</div>
|
||||
<div class="rowitem passive submenu">
|
||||
<a href="/panel/analytics/memory/">{{lang "panel_menu_statistics_memory"}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="rowitem passive">
|
||||
<a href="/forum/{{.ReportForumID}}">{{lang "panel_menu_reports"}}</a> <a class="menu_stats" href="#">({{.Stats.Reports}})</a>
|
||||
|
|
|
@ -62,6 +62,9 @@
|
|||
<div class="rowitem passive submenu">
|
||||
<a href="/panel/analytics/referrers/">{{lang "panel_menu_statistics_referrers"}}</a>
|
||||
</div>
|
||||
<div class="rowitem passive submenu">
|
||||
<a href="/panel/analytics/memory/">{{lang "panel_menu_statistics_memory"}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="rowitem passive">
|
||||
<a href="/forum/{{.ReportForumID}}">{{lang "panel_menu_reports"}}</a> <a class="menu_stats" href="#">({{.Stats.Reports}})</a>
|
||||
|
|
|
@ -175,6 +175,7 @@ button, .formbutton, .panel_right_button:not(.has_inner_button), #panel_users .p
|
|||
padding: 16px;
|
||||
padding-bottom: 0px;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.colstack_graph_holder .ct-label {
|
||||
|
|
Loading…
Reference in New Issue