blob: e0c6fb01841cd725cb96b5a4a74bbd35a50d9c95 [file] [log] [blame]
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"net/http"
"strconv"
"strings"
"time"
"github.com/google/safehtml"
"github.com/google/safehtml/template"
"golang.org/x/oscar/internal/github"
"golang.org/x/oscar/internal/htmlutil"
)
// overviewPage holds the fields needed to display the results
// of a search.
type overviewPage struct {
overviewForm // the raw form inputs
Result *overviewResult
Error string // if non-empty, the error to display instead of the result
}
type overviewResult struct {
github.IssueOverviewResult // the raw result
OverviewHTML safehtml.HTML // the overview as HTML
}
// overviewForm holds the raw inputs to the overview form.
type overviewForm struct {
Query string // the issue ID to lookup
}
func (g *Gaby) handleOverview(w http.ResponseWriter, r *http.Request) {
handlePage(w, g.populateOverviewPage(r), overviewPageTmpl)
}
var overviewPageTmpl = newTemplate(overviewPageTmplFile, template.FuncMap{
"fmttime": fmtTimeString,
})
// fmtTimeString formats an [time.RFC3339]-encoded time string
// as a [time.DateOnly] time string.
func fmtTimeString(s string) string {
if s == "" {
return s
}
t, err := time.Parse(time.RFC3339, s)
if err != nil {
return s
}
return t.Format(time.DateOnly)
}
// populateOverviewPage returns the contents of the overview page.
func (g *Gaby) populateOverviewPage(r *http.Request) overviewPage {
form := overviewForm{
Query: r.FormValue("q"),
}
if form.Query == "" {
return overviewPage{
overviewForm: form,
}
}
issue, err := strconv.Atoi(strings.TrimSpace(form.Query))
if err != nil {
return overviewPage{
overviewForm: form,
Error: fmt.Errorf("invalid form value %q: %w", form.Query, err).Error(),
}
}
overview, err := github.IssueOverview(r.Context(), g.llm, g.db, g.githubProject, int64(issue))
if err != nil {
return overviewPage{
overviewForm: form,
Error: fmt.Errorf("overview: %w", err).Error(),
}
}
return overviewPage{
overviewForm: form,
Result: &overviewResult{
IssueOverviewResult: *overview,
OverviewHTML: htmlutil.MarkdownToSafeHTML(overview.Overview.Overview),
},
}
}
// Related returns the relative URL of the related-entity search
// for the issue.
func (r *overviewResult) Related() string {
return fmt.Sprintf("/search?q=%s", r.Issue.HTMLURL)
}