Added some basic route statistics to the Control Panel.
Fixed the direction of the labels on the views graph.
This commit is contained in:
parent
dcfcd08248
commit
e259a575e9
@ -97,6 +97,7 @@ var PreRenderHooks = map[string][]func(http.ResponseWriter, *http.Request, *User
|
||||
"pre_render_panel_delete_forum": nil,
|
||||
"pre_render_panel_edit_forum": nil,
|
||||
"pre_render_panel_analytics": nil,
|
||||
"pre_render_panel_analytics_routes": nil,
|
||||
"pre_render_panel_settings": nil,
|
||||
"pre_render_panel_setting": nil,
|
||||
"pre_render_panel_word_filters": nil,
|
||||
|
@ -163,6 +163,20 @@ type PanelAnalyticsPage struct {
|
||||
PrimaryGraph PanelTimeGraph
|
||||
}
|
||||
|
||||
type PanelAnalyticsRoutesItem struct {
|
||||
Route string
|
||||
Count int
|
||||
}
|
||||
|
||||
type PanelAnalyticsRoutesPage struct {
|
||||
Title string
|
||||
CurrentUser User
|
||||
Header *HeaderVars
|
||||
Stats PanelStats
|
||||
Zone string
|
||||
ItemList []PanelAnalyticsRoutesItem
|
||||
}
|
||||
|
||||
type PanelThemesPage struct {
|
||||
Title string
|
||||
CurrentUser User
|
||||
|
156
gen_router.go
156
gen_router.go
@ -50,6 +50,7 @@ var RouteMap = map[string]interface{}{
|
||||
"routePanelUsersEdit": routePanelUsersEdit,
|
||||
"routePanelUsersEditSubmit": routePanelUsersEditSubmit,
|
||||
"routePanelAnalyticsViews": routePanelAnalyticsViews,
|
||||
"routePanelAnalyticsRoutes": routePanelAnalyticsRoutes,
|
||||
"routePanelGroups": routePanelGroups,
|
||||
"routePanelGroupsEdit": routePanelGroupsEdit,
|
||||
"routePanelGroupsEditPerms": routePanelGroupsEditPerms,
|
||||
@ -114,31 +115,32 @@ var routeMapEnum = map[string]int{
|
||||
"routePanelUsersEdit": 32,
|
||||
"routePanelUsersEditSubmit": 33,
|
||||
"routePanelAnalyticsViews": 34,
|
||||
"routePanelGroups": 35,
|
||||
"routePanelGroupsEdit": 36,
|
||||
"routePanelGroupsEditPerms": 37,
|
||||
"routePanelGroupsEditSubmit": 38,
|
||||
"routePanelGroupsEditPermsSubmit": 39,
|
||||
"routePanelGroupsCreateSubmit": 40,
|
||||
"routePanelBackups": 41,
|
||||
"routePanelLogsMod": 42,
|
||||
"routePanelDebug": 43,
|
||||
"routePanel": 44,
|
||||
"routeAccountEditCritical": 45,
|
||||
"routeAccountEditCriticalSubmit": 46,
|
||||
"routeAccountEditAvatar": 47,
|
||||
"routeAccountEditAvatarSubmit": 48,
|
||||
"routeAccountEditUsername": 49,
|
||||
"routeAccountEditUsernameSubmit": 50,
|
||||
"routeAccountEditEmail": 51,
|
||||
"routeAccountEditEmailTokenSubmit": 52,
|
||||
"routeProfile": 53,
|
||||
"routeBanSubmit": 54,
|
||||
"routeUnban": 55,
|
||||
"routeActivate": 56,
|
||||
"routeIps": 57,
|
||||
"routeDynamic": 58,
|
||||
"routeUploads": 59,
|
||||
"routePanelAnalyticsRoutes": 35,
|
||||
"routePanelGroups": 36,
|
||||
"routePanelGroupsEdit": 37,
|
||||
"routePanelGroupsEditPerms": 38,
|
||||
"routePanelGroupsEditSubmit": 39,
|
||||
"routePanelGroupsEditPermsSubmit": 40,
|
||||
"routePanelGroupsCreateSubmit": 41,
|
||||
"routePanelBackups": 42,
|
||||
"routePanelLogsMod": 43,
|
||||
"routePanelDebug": 44,
|
||||
"routePanel": 45,
|
||||
"routeAccountEditCritical": 46,
|
||||
"routeAccountEditCriticalSubmit": 47,
|
||||
"routeAccountEditAvatar": 48,
|
||||
"routeAccountEditAvatarSubmit": 49,
|
||||
"routeAccountEditUsername": 50,
|
||||
"routeAccountEditUsernameSubmit": 51,
|
||||
"routeAccountEditEmail": 52,
|
||||
"routeAccountEditEmailTokenSubmit": 53,
|
||||
"routeProfile": 54,
|
||||
"routeBanSubmit": 55,
|
||||
"routeUnban": 56,
|
||||
"routeActivate": 57,
|
||||
"routeIps": 58,
|
||||
"routeDynamic": 59,
|
||||
"routeUploads": 60,
|
||||
}
|
||||
var reverseRouteMapEnum = map[int]string{
|
||||
0: "routeAPI",
|
||||
@ -176,31 +178,32 @@ var reverseRouteMapEnum = map[int]string{
|
||||
32: "routePanelUsersEdit",
|
||||
33: "routePanelUsersEditSubmit",
|
||||
34: "routePanelAnalyticsViews",
|
||||
35: "routePanelGroups",
|
||||
36: "routePanelGroupsEdit",
|
||||
37: "routePanelGroupsEditPerms",
|
||||
38: "routePanelGroupsEditSubmit",
|
||||
39: "routePanelGroupsEditPermsSubmit",
|
||||
40: "routePanelGroupsCreateSubmit",
|
||||
41: "routePanelBackups",
|
||||
42: "routePanelLogsMod",
|
||||
43: "routePanelDebug",
|
||||
44: "routePanel",
|
||||
45: "routeAccountEditCritical",
|
||||
46: "routeAccountEditCriticalSubmit",
|
||||
47: "routeAccountEditAvatar",
|
||||
48: "routeAccountEditAvatarSubmit",
|
||||
49: "routeAccountEditUsername",
|
||||
50: "routeAccountEditUsernameSubmit",
|
||||
51: "routeAccountEditEmail",
|
||||
52: "routeAccountEditEmailTokenSubmit",
|
||||
53: "routeProfile",
|
||||
54: "routeBanSubmit",
|
||||
55: "routeUnban",
|
||||
56: "routeActivate",
|
||||
57: "routeIps",
|
||||
58: "routeDynamic",
|
||||
59: "routeUploads",
|
||||
35: "routePanelAnalyticsRoutes",
|
||||
36: "routePanelGroups",
|
||||
37: "routePanelGroupsEdit",
|
||||
38: "routePanelGroupsEditPerms",
|
||||
39: "routePanelGroupsEditSubmit",
|
||||
40: "routePanelGroupsEditPermsSubmit",
|
||||
41: "routePanelGroupsCreateSubmit",
|
||||
42: "routePanelBackups",
|
||||
43: "routePanelLogsMod",
|
||||
44: "routePanelDebug",
|
||||
45: "routePanel",
|
||||
46: "routeAccountEditCritical",
|
||||
47: "routeAccountEditCriticalSubmit",
|
||||
48: "routeAccountEditAvatar",
|
||||
49: "routeAccountEditAvatarSubmit",
|
||||
50: "routeAccountEditUsername",
|
||||
51: "routeAccountEditUsernameSubmit",
|
||||
52: "routeAccountEditEmail",
|
||||
53: "routeAccountEditEmailTokenSubmit",
|
||||
54: "routeProfile",
|
||||
55: "routeBanSubmit",
|
||||
56: "routeUnban",
|
||||
57: "routeActivate",
|
||||
58: "routeIps",
|
||||
59: "routeDynamic",
|
||||
60: "routeUploads",
|
||||
}
|
||||
|
||||
// TODO: Stop spilling these into the package scope?
|
||||
@ -571,14 +574,17 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
case "/panel/analytics/views/":
|
||||
common.RouteViewCounter.Bump(34)
|
||||
err = routePanelAnalyticsViews(w,req,user)
|
||||
case "/panel/groups/":
|
||||
case "/panel/analytics/routes/":
|
||||
common.RouteViewCounter.Bump(35)
|
||||
err = routePanelAnalyticsRoutes(w,req,user)
|
||||
case "/panel/groups/":
|
||||
common.RouteViewCounter.Bump(36)
|
||||
err = routePanelGroups(w,req,user)
|
||||
case "/panel/groups/edit/":
|
||||
common.RouteViewCounter.Bump(36)
|
||||
common.RouteViewCounter.Bump(37)
|
||||
err = routePanelGroupsEdit(w,req,user,extraData)
|
||||
case "/panel/groups/edit/perms/":
|
||||
common.RouteViewCounter.Bump(37)
|
||||
common.RouteViewCounter.Bump(38)
|
||||
err = routePanelGroupsEditPerms(w,req,user,extraData)
|
||||
case "/panel/groups/edit/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
@ -587,7 +593,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(38)
|
||||
common.RouteViewCounter.Bump(39)
|
||||
err = routePanelGroupsEditSubmit(w,req,user,extraData)
|
||||
case "/panel/groups/edit/perms/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
@ -596,7 +602,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(39)
|
||||
common.RouteViewCounter.Bump(40)
|
||||
err = routePanelGroupsEditPermsSubmit(w,req,user,extraData)
|
||||
case "/panel/groups/create/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
@ -605,7 +611,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(40)
|
||||
common.RouteViewCounter.Bump(41)
|
||||
err = routePanelGroupsCreateSubmit(w,req,user)
|
||||
case "/panel/backups/":
|
||||
err = common.SuperAdminOnly(w,req,user)
|
||||
@ -614,10 +620,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(41)
|
||||
common.RouteViewCounter.Bump(42)
|
||||
err = routePanelBackups(w,req,user,extraData)
|
||||
case "/panel/logs/mod/":
|
||||
common.RouteViewCounter.Bump(42)
|
||||
common.RouteViewCounter.Bump(43)
|
||||
err = routePanelLogsMod(w,req,user)
|
||||
case "/panel/debug/":
|
||||
err = common.AdminOnly(w,req,user)
|
||||
@ -626,10 +632,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(43)
|
||||
common.RouteViewCounter.Bump(44)
|
||||
err = routePanelDebug(w,req,user)
|
||||
default:
|
||||
common.RouteViewCounter.Bump(44)
|
||||
common.RouteViewCounter.Bump(45)
|
||||
err = routePanel(w,req,user)
|
||||
}
|
||||
if err != nil {
|
||||
@ -644,7 +650,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(45)
|
||||
common.RouteViewCounter.Bump(46)
|
||||
err = routeAccountEditCritical(w,req,user)
|
||||
case "/user/edit/critical/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
@ -659,7 +665,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(46)
|
||||
common.RouteViewCounter.Bump(47)
|
||||
err = routeAccountEditCriticalSubmit(w,req,user)
|
||||
case "/user/edit/avatar/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
@ -668,7 +674,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(47)
|
||||
common.RouteViewCounter.Bump(48)
|
||||
err = routeAccountEditAvatar(w,req,user)
|
||||
case "/user/edit/avatar/submit/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
@ -677,7 +683,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(48)
|
||||
common.RouteViewCounter.Bump(49)
|
||||
err = routeAccountEditAvatarSubmit(w,req,user)
|
||||
case "/user/edit/username/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
@ -686,7 +692,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(49)
|
||||
common.RouteViewCounter.Bump(50)
|
||||
err = routeAccountEditUsername(w,req,user)
|
||||
case "/user/edit/username/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
@ -701,7 +707,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(50)
|
||||
common.RouteViewCounter.Bump(51)
|
||||
err = routeAccountEditUsernameSubmit(w,req,user)
|
||||
case "/user/edit/email/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
@ -710,7 +716,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(51)
|
||||
common.RouteViewCounter.Bump(52)
|
||||
err = routeAccountEditEmail(w,req,user)
|
||||
case "/user/edit/token/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
@ -725,11 +731,11 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(52)
|
||||
common.RouteViewCounter.Bump(53)
|
||||
err = routeAccountEditEmailTokenSubmit(w,req,user,extraData)
|
||||
default:
|
||||
req.URL.Path += extraData
|
||||
common.RouteViewCounter.Bump(53)
|
||||
common.RouteViewCounter.Bump(54)
|
||||
err = routeProfile(w,req,user)
|
||||
}
|
||||
if err != nil {
|
||||
@ -750,7 +756,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(54)
|
||||
common.RouteViewCounter.Bump(55)
|
||||
err = routeBanSubmit(w,req,user,extraData)
|
||||
case "/users/unban/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
@ -765,7 +771,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(55)
|
||||
common.RouteViewCounter.Bump(56)
|
||||
err = routeUnban(w,req,user,extraData)
|
||||
case "/users/activate/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
@ -780,7 +786,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(56)
|
||||
common.RouteViewCounter.Bump(57)
|
||||
err = routeActivate(w,req,user,extraData)
|
||||
case "/users/ips/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
@ -789,7 +795,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(57)
|
||||
common.RouteViewCounter.Bump(58)
|
||||
err = routeIps(w,req,user)
|
||||
}
|
||||
if err != nil {
|
||||
@ -806,7 +812,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
common.NotFound(w,req)
|
||||
return
|
||||
}
|
||||
common.RouteViewCounter.Bump(59)
|
||||
common.RouteViewCounter.Bump(60)
|
||||
req.URL.Path += extraData
|
||||
// TODO: Find a way to propagate errors up from this?
|
||||
router.UploadHandler(w,req) // TODO: Count these views
|
||||
@ -850,7 +856,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
router.RUnlock()
|
||||
|
||||
if ok {
|
||||
common.RouteViewCounter.Bump(58) // TODO: Be more specific about *which* dynamic route it is
|
||||
common.RouteViewCounter.Bump(59) // TODO: Be more specific about *which* dynamic route it is
|
||||
req.URL.Path += extraData
|
||||
err = handle(w,req,user)
|
||||
if err != nil {
|
||||
|
@ -450,26 +450,24 @@ func routePanelAnalyticsViews(w http.ResponseWriter, r *http.Request, user commo
|
||||
}
|
||||
|
||||
var viewList []int64
|
||||
log.Print("in routePanelAnalyticsViews")
|
||||
|
||||
acc := qgen.Builder.Accumulator()
|
||||
rows, err := acc.Select("viewchunks").Columns("count, createdAt, route").Where("route = ''").DateCutoff("createdAt", 6, "hour").Query()
|
||||
rows, err := acc.Select("viewchunks").Columns("count, createdAt").Where("route = ''").DateCutoff("createdAt", 6, "hour").Query()
|
||||
if err != nil && err != ErrNoRows {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
log.Print("WE HAVE ROWS")
|
||||
var count int64
|
||||
var createdAt time.Time
|
||||
var route string
|
||||
err := rows.Scan(&count, &createdAt, &route)
|
||||
err := rows.Scan(&count, &createdAt)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
log.Print("count: ", count)
|
||||
log.Print("createdAt: ", createdAt)
|
||||
log.Print("route: ", route)
|
||||
|
||||
var unixCreatedAt = createdAt.Unix()
|
||||
log.Print("unixCreatedAt: ", unixCreatedAt)
|
||||
@ -504,6 +502,61 @@ func routePanelAnalyticsViews(w http.ResponseWriter, r *http.Request, user commo
|
||||
return nil
|
||||
}
|
||||
|
||||
func routePanelAnalyticsRoutes(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
var routeMap = make(map[string]int)
|
||||
|
||||
acc := qgen.Builder.Accumulator()
|
||||
rows, err := acc.Select("viewchunks").Columns("count, createdAt, route").Where("route != ''").DateCutoff("createdAt", 1, "day").Query()
|
||||
if err != nil && err != ErrNoRows {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var count int
|
||||
var createdAt time.Time
|
||||
var route string
|
||||
err := rows.Scan(&count, &createdAt, &route)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
log.Print("count: ", count)
|
||||
log.Print("createdAt: ", createdAt)
|
||||
log.Print("route: ", route)
|
||||
routeMap[route] += count
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// TODO: Sort this slice
|
||||
var routeItems []common.PanelAnalyticsRoutesItem
|
||||
for route, count := range routeMap {
|
||||
routeItems = append(routeItems, common.PanelAnalyticsRoutesItem{
|
||||
Route: route,
|
||||
Count: count,
|
||||
})
|
||||
}
|
||||
|
||||
pi := common.PanelAnalyticsRoutesPage{common.GetTitlePhrase("panel-analytics"), user, headerVars, stats, "analytics", routeItems}
|
||||
if common.PreRenderHooks["pre_render_panel_analytics_routes"] != nil {
|
||||
if common.RunPreRenderHook("pre_render_panel_analytics_routes", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err = common.Templates.ExecuteTemplate(w, "panel-analytics-routes.html", pi)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func routePanelSettings(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
headerVars, stats, ferr := common.PanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
|
@ -90,6 +90,7 @@ func buildPanelRoutes() {
|
||||
Action("routePanelUsersEditSubmit", "/panel/users/edit/submit/", "extraData"),
|
||||
|
||||
View("routePanelAnalyticsViews", "/panel/analytics/views/"),
|
||||
View("routePanelAnalyticsRoutes", "/panel/analytics/routes/"),
|
||||
|
||||
View("routePanelGroups", "/panel/groups/"),
|
||||
View("routePanelGroupsEdit", "/panel/groups/edit/", "extraData"),
|
||||
|
18
templates/panel-analytics-routes.html
Normal file
18
templates/panel-analytics-routes.html
Normal file
@ -0,0 +1,18 @@
|
||||
{{template "header.html" . }}
|
||||
<div class="colstack panel_stack">
|
||||
{{template "panel-menu.html" . }}
|
||||
<main id="panel_dashboard_right" class="colstack_right">
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem"><a>Routes</a></div>
|
||||
</div>
|
||||
<div id="panel_analytics_routes" class="colstack_item rowlist">
|
||||
{{range .ItemList}}
|
||||
<div class="rowitem panel_compactrow editable_parent">
|
||||
<a href="/panel/groups/edit/{{.Route}}" class="panel_upshift">{{.Route}}</a>
|
||||
<span class="panel_compacttext to_right">{{.Count}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
{{template "footer.html" . }}
|
@ -5,7 +5,7 @@
|
||||
<div class="colstack_item colstack_head">
|
||||
<div class="rowitem"><a>Views</a></div>
|
||||
</div>
|
||||
<div id="panel_analytics" class="colstack_graph_holder">
|
||||
<div id="panel_analytics_views" class="colstack_graph_holder">
|
||||
<div class="ct-chart"></div>
|
||||
</div>
|
||||
</main>
|
||||
@ -23,6 +23,7 @@ for(const i in rawLabels) {
|
||||
console.log("label:", label);
|
||||
labels.push(label);
|
||||
}
|
||||
labels = labels.reverse()
|
||||
|
||||
let seriesData = [{{range .PrimaryGraph.Series}}
|
||||
{{.}},{{end}}
|
||||
|
@ -32,6 +32,9 @@
|
||||
<div class="rowitem passive submenu">
|
||||
<a href="/panel/analytics/posts/">Posts</a>
|
||||
</div>
|
||||
<div class="rowitem passive submenu">
|
||||
<a href="/panel/analytics/routes/">Routes</a>
|
||||
</div>
|
||||
<div class="rowitem passive submenu">
|
||||
<a href="/panel/analytics/crawlers/">Crawlers</a>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user