forgejo-tickets/internal/handlers/admin/dashboard.go

92 lines
2.5 KiB
Go

package admin
import (
"github.com/gin-gonic/gin"
"github.com/mattnite/forgejo-tickets/internal/forgejo"
"github.com/mattnite/forgejo-tickets/internal/models"
"github.com/rs/zerolog/log"
)
type DashboardHandler struct {
deps Dependencies
}
func (h *DashboardHandler) Index(c *gin.Context) {
var userCount int64
if err := h.deps.DB.Model(&models.User{}).Count(&userCount).Error; err != nil {
log.Error().Err(err).Msg("count users error")
}
var totalTickets int64
if err := h.deps.DB.Model(&models.Ticket{}).Count(&totalTickets).Error; err != nil {
log.Error().Err(err).Msg("count tickets error")
}
// Get distinct repos that have tickets
type repoInfo struct {
ForgejoOwner string
ForgejoRepo string
}
var repos []repoInfo
h.deps.DB.Table("tickets").
Select("DISTINCT repos.forgejo_owner, repos.forgejo_repo").
Joins("JOIN repos ON repos.id = tickets.repo_id").
Scan(&repos)
// Get all ticket issue numbers grouped by repo for matching
type ticketIssue struct {
ForgejoOwner string
ForgejoRepo string
ForgejoIssueNumber int64
}
var ticketIssues []ticketIssue
h.deps.DB.Table("tickets").
Select("repos.forgejo_owner, repos.forgejo_repo, tickets.forgejo_issue_number").
Joins("JOIN repos ON repos.id = tickets.repo_id").
Scan(&ticketIssues)
// Build a set of known issue numbers per repo
knownIssues := map[string]map[int64]bool{}
for _, ti := range ticketIssues {
key := ti.ForgejoOwner + "/" + ti.ForgejoRepo
if knownIssues[key] == nil {
knownIssues[key] = map[int64]bool{}
}
knownIssues[key][ti.ForgejoIssueNumber] = true
}
var openTickets, inProgressTickets, closedTickets int64
for _, repo := range repos {
issues, err := h.deps.ForgejoClient.ListIssues(repo.ForgejoOwner, repo.ForgejoRepo, "all", "")
if err != nil {
log.Error().Err(err).Str("repo", repo.ForgejoOwner+"/"+repo.ForgejoRepo).Msg("dashboard: forgejo list issues error")
continue
}
key := repo.ForgejoOwner + "/" + repo.ForgejoRepo
known := knownIssues[key]
for i := range issues {
if !known[issues[i].Number] {
continue
}
switch forgejo.DeriveStatus(&issues[i]) {
case "open":
openTickets++
case "in_progress":
inProgressTickets++
case "closed":
closedTickets++
}
}
}
h.deps.Renderer.Render(c.Writer, c.Request, "admin/dashboard", map[string]interface{}{
"UserCount": userCount,
"TotalTickets": totalTickets,
"OpenTickets": openTickets,
"InProgressTickets": inProgressTickets,
"ClosedTickets": closedTickets,
})
}