105 lines
2.9 KiB
Go
105 lines
2.9 KiB
Go
package admin
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"github.com/mattnite/forgejo-tickets/internal/models"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type TicketHandler struct {
|
|
deps Dependencies
|
|
}
|
|
|
|
type ticketListRow struct {
|
|
models.Ticket
|
|
RepoName string
|
|
RepoSlug string
|
|
UserEmail string
|
|
UserName string
|
|
}
|
|
|
|
func (h *TicketHandler) List(c *gin.Context) {
|
|
statusFilter := c.Query("status")
|
|
|
|
var tickets []ticketListRow
|
|
query := h.deps.DB.Table("tickets").
|
|
Select("tickets.*, repos.name as repo_name, repos.slug as repo_slug, users.email as user_email, users.name as user_name").
|
|
Joins("JOIN repos ON repos.id = tickets.repo_id").
|
|
Joins("JOIN users ON users.id = tickets.user_id")
|
|
|
|
if statusFilter != "" {
|
|
query = query.Where("tickets.status = ?", statusFilter)
|
|
}
|
|
|
|
if err := query.Order("tickets.created_at DESC").Limit(100).Scan(&tickets).Error; err != nil {
|
|
log.Error().Err(err).Msg("list tickets error")
|
|
h.deps.Renderer.RenderError(c.Writer, c.Request, http.StatusInternalServerError, "Failed to load tickets")
|
|
return
|
|
}
|
|
|
|
h.deps.Renderer.Render(c.Writer, c.Request, "admin/tickets/list", map[string]interface{}{
|
|
"Tickets": tickets,
|
|
"StatusFilter": statusFilter,
|
|
})
|
|
}
|
|
|
|
func (h *TicketHandler) Detail(c *gin.Context) {
|
|
ticketID, err := uuid.Parse(c.Param("id"))
|
|
if err != nil {
|
|
h.deps.Renderer.RenderError(c.Writer, c.Request, http.StatusBadRequest, "Invalid ticket ID")
|
|
return
|
|
}
|
|
|
|
var ticket models.Ticket
|
|
if err := h.deps.DB.First(&ticket, "id = ?", ticketID).Error; err != nil {
|
|
h.deps.Renderer.RenderError(c.Writer, c.Request, http.StatusNotFound, "Ticket not found")
|
|
return
|
|
}
|
|
|
|
var user models.User
|
|
h.deps.DB.First(&user, "id = ?", ticket.UserID)
|
|
|
|
var repo models.Repo
|
|
h.deps.DB.First(&repo, "id = ?", ticket.RepoID)
|
|
|
|
var comments []struct {
|
|
models.TicketComment
|
|
UserName string
|
|
UserEmail string
|
|
}
|
|
h.deps.DB.Table("ticket_comments").
|
|
Select("ticket_comments.*, users.name as user_name, users.email as user_email").
|
|
Joins("JOIN users ON users.id = ticket_comments.user_id").
|
|
Where("ticket_comments.ticket_id = ?", ticket.ID).
|
|
Order("ticket_comments.created_at ASC").
|
|
Scan(&comments)
|
|
|
|
h.deps.Renderer.Render(c.Writer, c.Request, "admin/tickets/detail", map[string]interface{}{
|
|
"Ticket": ticket,
|
|
"User": user,
|
|
"Repo": repo,
|
|
"Comments": comments,
|
|
})
|
|
}
|
|
|
|
func (h *TicketHandler) UpdateStatus(c *gin.Context) {
|
|
ticketID, err := uuid.Parse(c.Param("id"))
|
|
if err != nil {
|
|
h.deps.Renderer.RenderError(c.Writer, c.Request, http.StatusBadRequest, "Invalid ticket ID")
|
|
return
|
|
}
|
|
|
|
status := models.TicketStatus(c.PostForm("status"))
|
|
|
|
if err := h.deps.DB.Model(&models.Ticket{}).Where("id = ?", ticketID).Update("status", status).Error; err != nil {
|
|
log.Error().Err(err).Msg("update ticket status error")
|
|
h.deps.Renderer.RenderError(c.Writer, c.Request, http.StatusInternalServerError, "Failed to update status")
|
|
return
|
|
}
|
|
|
|
c.Redirect(http.StatusSeeOther, "/tickets/"+ticketID.String())
|
|
}
|