add a page for tickets from gitea (#2)

Co-authored-by: Blake Ridgway <blake@blakeridgway.com>
Reviewed-on: #2
This commit is contained in:
2026-04-13 03:51:22 -05:00
parent 5bc3050dd4
commit b1feff3bbf
16 changed files with 782 additions and 12 deletions

View File

@@ -7,11 +7,13 @@ import (
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"ridgwaysystems.org/website/internal/blog"
"ridgwaysystems.org/website/internal/changelog"
"ridgwaysystems.org/website/internal/gitea"
"ridgwaysystems.org/website/internal/newsletter"
"ridgwaysystems.org/website/internal/status"
)
@@ -91,6 +93,13 @@ func (h *Handler) AdminRouter(w http.ResponseWriter, r *http.Request) {
h.requireAuth(h.adminNewsletter)(w, r)
}
case path == "/admin/outages":
if r.Method == http.MethodPost {
h.requireAuth(h.adminOutagesPost)(w, r)
} else {
h.requireAuth(h.adminOutagesGet)(w, r)
}
default:
h.renderErr(w, http.StatusNotFound, "Admin page not found.")
}
@@ -549,6 +558,74 @@ func (h *Handler) adminChangelogDelete(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/admin/changelog?flash=Entry+deleted", http.StatusSeeOther)
}
// --- Outage tagger ---
type adminOutagesData struct {
Issues []gitea.Issue
Label string
Flash string
Error string
}
func (h *Handler) adminOutagesGet(w http.ResponseWriter, r *http.Request) {
if h.gitea == nil || h.giteaOwner == "" || h.giteaRepo == "" {
h.render(w, "admin-outages", adminOutagesData{Error: "Gitea not configured. Set GITEA_URL, GITEA_TOKEN, GITEA_OWNER, and GITEA_REPO."})
return
}
issues, err := h.gitea.ListOpenIssues(h.giteaOwner, h.giteaRepo)
if err != nil {
h.render(w, "admin-outages", adminOutagesData{Error: "Could not load issues: " + err.Error()})
return
}
h.render(w, "admin-outages", adminOutagesData{
Issues: issues,
Label: h.giteaLabel,
Flash: r.URL.Query().Get("flash"),
})
}
func (h *Handler) adminOutagesPost(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
h.renderErr(w, http.StatusBadRequest, "Bad form data.")
return
}
if h.gitea == nil || h.giteaOwner == "" || h.giteaRepo == "" {
h.renderErr(w, http.StatusServiceUnavailable, "Gitea not configured.")
return
}
action := r.FormValue("action") // "add" or "remove"
issueNum, err := strconv.Atoi(r.FormValue("issue"))
if err != nil || issueNum <= 0 {
h.renderErr(w, http.StatusBadRequest, "Invalid issue number.")
return
}
label, err := h.gitea.GetOrCreateLabel(h.giteaOwner, h.giteaRepo, h.giteaLabel, "#e11d48")
if err != nil {
h.renderErr(w, http.StatusInternalServerError, "Label error: "+err.Error())
return
}
switch action {
case "add":
if err := h.gitea.AddLabel(h.giteaOwner, h.giteaRepo, issueNum, label.ID); err != nil {
h.renderErr(w, http.StatusInternalServerError, "Could not add label: "+err.Error())
return
}
case "remove":
if err := h.gitea.RemoveLabel(h.giteaOwner, h.giteaRepo, issueNum, label.ID); err != nil {
h.renderErr(w, http.StatusInternalServerError, "Could not remove label: "+err.Error())
return
}
default:
h.renderErr(w, http.StatusBadRequest, "Unknown action.")
return
}
http.Redirect(w, r, "/admin/outages?flash=Updated+#"+strconv.Itoa(issueNum), http.StatusSeeOther)
}
// sanitizeSlug ensures a slug is filesystem-safe.
func sanitizeSlug(s string) string {
s = strings.ToLower(strings.TrimSpace(s))