Archived
Template
1
0
This repository has been archived on 2023-12-20. You can view files and clone it, but cannot push or open issues or pull requests.
Files
golang-base-project/routes/admin.go

173 lines
3.3 KiB
Go
Raw Normal View History

2021-12-12 14:56:13 +01:00
package routes
import (
"fmt"
2021-12-12 14:56:13 +01:00
"github.com/gin-gonic/gin"
"github.com/uberswe/golang-base-project/models"
"gorm.io/gorm"
"log"
"math"
2021-12-12 14:56:13 +01:00
"net/http"
"sort"
"time"
2021-12-12 14:56:13 +01:00
)
type AdminData struct {
PageData
Chart Chart
}
type Chart struct {
Title string
XLabel string
YLabel string
XValues []ChartValue
YValues []ChartValue
Points string
}
type ChartValue struct {
Value string
X int
Y int
}
type MonthlySignUps struct {
Year int
Month int
Count int
}
// Admin renders the admin dashboard
2021-12-12 14:56:13 +01:00
func (controller Controller) Admin(c *gin.Context) {
2022-01-29 10:21:05 +01:00
pd := controller.DefaultPageData(c)
pd.Title = pd.Trans("Admin")
ad := AdminData{
PageData: pd,
Chart: Chart{
Title: "Monthly User Sign Ups",
XLabel: "Month",
YLabel: "Users",
},
}
var msu []MonthlySignUps
res := controller.db.Model(&models.User{}).
Select("YEAR(created_at) as year, MONTH(created_at) AS month, COUNT(*) AS count").
Where("created_at >= CURDATE() - INTERVAL 1 YEAR").
Group("YEAR(created_at), MONTH(created_at)").
Find(&msu)
if res.Error != nil && res.Error != gorm.ErrRecordNotFound {
pd.Messages = append(pd.Messages, Message{
Type: "error",
Content: "Something went wrong while fetching user data",
})
log.Println(res.Error)
c.HTML(http.StatusInternalServerError, "admin.html", ad)
return
}
// TODO make this into a graph package or find a go package to replace this manual code
// Add 0 values
y, m, _ := time.Now().AddDate(-1, 0, 0).Date()
ny, nm, _ := time.Now().Date()
for y < ny || m < nm {
found := false
for _, ms := range msu {
if ms.Year == y && ms.Month == int(m) {
found = true
}
}
if !found {
msu = append(msu, MonthlySignUps{
Year: y,
Month: int(m),
Count: 0,
})
}
m++
if m > 12 {
m = 1
y++
}
}
// Sort our values so that the graph shows left to right going from earliest to latest date
sort.Slice(msu, func(i, j int) bool {
if msu[i].Year < msu[j].Year {
return true
} else if msu[i].Year == msu[j].Year && msu[i].Month < msu[j].Month {
return true
}
return false
})
rightAdjust := 50
base := 350
lowest := math.MaxInt32
highest := 0
count := len(msu)
for _, m := range msu {
if lowest > m.Count {
lowest = m.Count
}
if highest < m.Count {
highest = m.Count
}
}
diff := highest - lowest
if diff < 5 {
diff = 5
}
// We multiply counts by this ratio after subtracting our lowest
ratio := base / diff
// y line is 90 x to 705 x at 370 y
maxX := 705
minX := 90
seg := (maxX - minX) / count
var yValues []ChartValue
for i, m := range msu {
yValues = append(yValues, ChartValue{
Value: fmt.Sprintf("%d-%d", m.Year, m.Month),
X: rightAdjust + 20 + minX + (i * seg),
Y: base + 40,
})
}
// x line is 5 y to 371 y on 90 x
var xValues []ChartValue
seg2 := diff / 5
for i := 0; i <= 5; i++ {
xValues = append(xValues, ChartValue{
Value: fmt.Sprintf("%d", lowest+(seg2*i)+1),
X: minX - 20,
Y: (base - 10) - (i * seg2 * ratio),
})
}
points := ""
for i, m := range msu {
if i > 0 {
points += " "
}
points += fmt.Sprintf("%d,%d", rightAdjust+minX+(i*seg), (base+20)-(m.Count*ratio))
}
ad.Chart.XValues = xValues
ad.Chart.YValues = yValues
ad.Chart.Points = points
// The chart is inverted so we need to subtract the base value to our calculated values
c.HTML(http.StatusOK, "admin.html", ad)
2021-12-12 14:56:13 +01:00
}