diff options
author | Arthur Zamarin <arthurzam@gentoo.org> | 2024-03-20 22:03:58 +0200 |
---|---|---|
committer | Arthur Zamarin <arthurzam@gentoo.org> | 2024-03-20 22:14:31 +0200 |
commit | b3af97293aaa47c39fc3ae9fcabd2c67ca332d23 (patch) | |
tree | 5cfb2844a2265d3bf0e28e7645f03e5a49642dcd /pkg/app | |
parent | db: when logging query, also log the duration (diff) | |
download | soko-b3af97293aaa47c39fc3ae9fcabd2c67ca332d23.tar.gz soko-b3af97293aaa47c39fc3ae9fcabd2c67ca332d23.tar.bz2 soko-b3af97293aaa47c39fc3ae9fcabd2c67ca332d23.zip |
app/category: optimize and simplify the show
Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
Diffstat (limited to 'pkg/app')
-rw-r--r-- | pkg/app/handler/categories/feeds.go | 38 | ||||
-rw-r--r-- | pkg/app/handler/categories/show.go | 207 | ||||
-rw-r--r-- | pkg/app/handler/categories/show.templ | 67 | ||||
-rw-r--r-- | pkg/app/handler/maintainer/show.go | 15 | ||||
-rw-r--r-- | pkg/app/serve.go | 12 | ||||
-rw-r--r-- | pkg/app/utils/stabilization.go | 20 |
6 files changed, 199 insertions, 160 deletions
diff --git a/pkg/app/handler/categories/feeds.go b/pkg/app/handler/categories/feeds.go new file mode 100644 index 0000000..2afdf13 --- /dev/null +++ b/pkg/app/handler/categories/feeds.go @@ -0,0 +1,38 @@ +package categories + +import ( + "net/http" + "soko/pkg/app/utils" + "soko/pkg/database" + "soko/pkg/models" +) + +func OutdatedFeed(w http.ResponseWriter, r *http.Request) { + categoryName := r.PathValue("category") + var outdated []models.OutdatedPackages + err := database.DBCon.Model(&outdated). + Where("SPLIT_PART(atom, '/', 1) = ?", categoryName). + Order("atom"). + Select() + if err != nil { + http.NotFound(w, r) + return + } + utils.OutdatedFeed(w, "https://packages.gentoo.org/categories/"+categoryName+"/outdated", "category "+categoryName, outdated) +} + +func StabilizationFeed(w http.ResponseWriter, r *http.Request) { + categoryName := r.PathValue("category") + var results []*models.PkgCheckResult + err := database.DBCon.Model(&results). + Column("atom", "cpv", "message"). + Where("class = ?", "StableRequest"). + Where("SPLIT_PART(atom, '/', 1) = ?", categoryName). + OrderExpr("cpv"). + Select() + if err != nil { + http.NotFound(w, r) + return + } + utils.StabilizationFeed(w, "https://packages.gentoo.org/categories/"+categoryName+"/stabilization", "category "+categoryName, results) +} diff --git a/pkg/app/handler/categories/show.go b/pkg/app/handler/categories/show.go index b48e37c..4f8bc60 100644 --- a/pkg/app/handler/categories/show.go +++ b/pkg/app/handler/categories/show.go @@ -5,112 +5,148 @@ package categories import ( "encoding/json" "net/http" - "soko/pkg/app/utils" - "soko/pkg/database" - "soko/pkg/models" "strings" "github.com/go-pg/pg/v10" + + "soko/pkg/app/handler/packages/components" + "soko/pkg/app/utils" + "soko/pkg/database" + "soko/pkg/models" ) -// Show renders a template to show a given category -func Show(w http.ResponseWriter, r *http.Request) { +func common(w http.ResponseWriter, r *http.Request) (categoryName string, category models.Category, err error) { + categoryName = r.PathValue("category") + + err = database.DBCon.Model(&category). + Where("category.name = ?", categoryName). + Relation("PackagesInformation").Select() + if err == pg.ErrNoRows { + http.NotFound(w, r) + return + } else if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + return +} + +type packageInfo struct { + Package string + Description string +} + +func ShowPackages(w http.ResponseWriter, r *http.Request) { categoryName := r.PathValue("category") - pageUrl := r.PathValue("pageName") + if strings.HasSuffix(categoryName, ".json") { + buildJson(w, categoryName[:len(categoryName)-5]) + return + } + categoryName, category, err := common(w, r) + if err != nil { + return + } - if pageUrl == "" && strings.HasSuffix(categoryName, ".json") { - buildJson(w, r, strings.TrimSuffix(categoryName, ".json")) + var packages []packageInfo + err = database.DBCon.Model((*models.Version)(nil)). + DistinctOn("package"). + Column("package", "description"). + Where("category = ?", categoryName). + Order("package ASC"). + Select(&packages) + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } + renderShowPage(w, r, "Packages", &category, + showPackages(categoryName, packages)) +} - var pullRequests []*models.GithubPullRequest - category := new(models.Category) - query := database.DBCon.Model(category). - Where("category.name = ?", categoryName). - Relation("PackagesInformation"). - Relation("Packages", func(q *pg.Query) (*pg.Query, error) { - return q.Order("name ASC"), nil - }) - - pageName := "Packages" - switch pageUrl { - case "stabilization": - pageName = "Stabilization" - query = query.Relation("Packages.Versions"). - Relation("Packages.Versions.PkgCheckResults", func(q *pg.Query) (*pg.Query, error) { - return q.Where("class = 'StableRequest'"), nil - }) - case "outdated": - pageName = "Outdated" - query = query.Relation("Packages.Versions"). - Relation("Packages.Outdated") - case "outdated.atom": - var outdated []models.OutdatedPackages - err := database.DBCon.Model(&outdated). - Where("SPLIT_PART(atom, '/', 1) = ?", categoryName). - Order("atom"). - Select() - if err != nil { - http.NotFound(w, r) - return - } - utils.OutdatedFeed(w, "https://packages.gentoo.org/categories/"+categoryName+"/outdated", "category "+categoryName, outdated) +func ShowOutdated(w http.ResponseWriter, r *http.Request) { + categoryName, category, err := common(w, r) + if err != nil { return - case "pull-requests": - pageName = "Pull requests" - err := database.DBCon.Model(&pullRequests). - Join("JOIN package_to_github_pull_requests ON package_to_github_pull_requests.github_pull_request_id = github_pull_request.id"). - Where("package_to_github_pull_requests.package_atom LIKE ?", categoryName+"/%"). - Group("github_pull_request.id"). - Order("github_pull_request.created_at DESC"). - Select() - if err != nil { - http.NotFound(w, r) - return - } - case "stabilization.json", "stabilization.xml", "stabilization.list": - err := query.Relation("Packages.Versions"). - Relation("Packages.Versions.PkgCheckResults", func(q *pg.Query) (*pg.Query, error) { - return q.Where("class = 'StableRequest'"), nil - }).Select() - if err != nil { - http.NotFound(w, r) - return - } - utils.StabilizationExport(w, pageUrl, category.Packages) + } + + var outdated []components.OutdatedItem + descriptionQuery := database.DBCon.Model((*models.Version)(nil)). + Column("description"). + Where("atom = outdated_packages.atom"). + Limit(1) + err = database.DBCon.Model((*models.OutdatedPackages)(nil)). + Column("atom").ColumnExpr("(?) AS description", descriptionQuery). + Where("SPLIT_PART(atom, '/', 1) = ?", categoryName). + Order("atom"). + Select(&outdated) + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return - case "stabilization.atom": - var results []*models.PkgCheckResult - err := database.DBCon.Model(&results). - Column("atom", "cpv", "message"). - Where("class = ?", "StableRequest"). - Where("SPLIT_PART(atom, '/', 1) = ?", categoryName). - OrderExpr("cpv"). - Select() - if err != nil { - http.NotFound(w, r) - return - } - utils.StabilizationFeed(w, "https://packages.gentoo.org/categories/"+categoryName+"/stabilization", "category "+categoryName, results) + } + renderShowPage(w, r, "Outdated", &category, + components.Outdated(outdated)) +} + +func ShowPullRequests(w http.ResponseWriter, r *http.Request) { + categoryName, category, err := common(w, r) + if err != nil { return - case "", "packages": - query = query.Relation("Packages.Versions") - default: - http.NotFound(w, r) + } + + var pullRequests []*models.GithubPullRequest + err = database.DBCon.Model(&pullRequests). + Join("JOIN package_to_github_pull_requests ON package_to_github_pull_requests.github_pull_request_id = github_pull_request.id"). + Where("package_to_github_pull_requests.package_atom LIKE ?", categoryName+"/%"). + Group("github_pull_request.id"). + Order("github_pull_request.created_at DESC"). + Select() + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } + renderShowPage(w, r, "Pull requests", &category, + components.PullRequests(category.PackagesInformation.PullRequests > 0, pullRequests)) +} - err := query.Select() +func ShowStabilizations(w http.ResponseWriter, r *http.Request) { + categoryName, category, err := common(w, r) if err != nil { - http.NotFound(w, r) return } - renderShowPage(w, r, pageName, category, pullRequests) + var results []*models.PkgCheckResult + err = database.DBCon.Model(&results). + Column("atom", "cpv", "message"). + Where("class = ?", "StableRequest"). + Where("SPLIT_PART(atom, '/', 1) = ?", categoryName). + OrderExpr("cpv"). + Select() + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + renderShowPage(w, r, "Stabilization", &category, + components.Stabilizations(category.PackagesInformation.StableRequests > 0, results)) +} + +func ShowStabilizationFile(w http.ResponseWriter, r *http.Request) { + categoryName := r.PathValue("category") + var results []*models.PkgCheckResult + err := database.DBCon.Model(&results). + Column("category", "package", "version", "message"). + Where("class = ?", "StableRequest"). + Where("SPLIT_PART(atom, '/', 1) = ?", categoryName). + OrderExpr("cpv"). + Select() + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + pageName := r.URL.Path[strings.LastIndexByte(r.URL.Path, '/')+1:] + utils.StabilizationExport(w, pageName, results) } // build the json for the category -func buildJson(w http.ResponseWriter, r *http.Request, categoryName string) { +func buildJson(w http.ResponseWriter, categoryName string) { var jsonCategory struct { Name string `json:"name"` Href string `json:"href"` @@ -129,7 +165,7 @@ func buildJson(w http.ResponseWriter, r *http.Request, categoryName string) { Order("package ASC"). Select(&jsonCategory.Packages) if err != nil { - http.NotFound(w, r) + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } @@ -138,8 +174,7 @@ func buildJson(w http.ResponseWriter, r *http.Request, categoryName string) { b, err := json.Marshal(jsonCategory) if err != nil { - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } diff --git a/pkg/app/handler/categories/show.templ b/pkg/app/handler/categories/show.templ index 82cf4bb..92812cc 100644 --- a/pkg/app/handler/categories/show.templ +++ b/pkg/app/handler/categories/show.templ @@ -3,7 +3,6 @@ package categories import "net/http" import "strconv" import "strings" -import "soko/pkg/app/handler/packages/components" import "soko/pkg/app/layout" import "soko/pkg/models" @@ -11,7 +10,7 @@ func packageLetter(name string) string { return strings.ToLower(strings.TrimLeft(name, "_")[:1]) } -templ showPackages(packages []*models.Package) { +templ showPackages(categoryName string, packages []packageInfo) { <div class="row"> <div class="col-12"> <div class="row"> @@ -23,12 +22,12 @@ templ showPackages(packages []*models.Package) { <table class="table mb-0 rounded"> for i, pkg := range packages { <tr - if i == 0 || packageLetter(pkg.Name) != packageLetter(packages[i-1].Name) { - id={ packageLetter(pkg.Name) } + if i == 0 || packageLetter(pkg.Package) != packageLetter(packages[i-1].Package) { + id={ packageLetter(pkg.Package) } } > - <th class="kk-nobreak-cell"><a href={ templ.URL("/packages/" + pkg.Atom) }>{ pkg.Name }</a></th> - <td>{ pkg.Versions[0].Description }</td> + <th class="kk-nobreak-cell"><a href={ templ.URL("/packages/" + categoryName + "/" + pkg.Package) }>{ pkg.Package }</a></th> + <td>{ pkg.Description }</td> </tr> } </table> @@ -42,10 +41,10 @@ templ showPackages(packages []*models.Package) { <h4 class="mt-4">Filter by Category</h4> <div class="row pl-4 pr-5 mr-5"> for i, pkg := range packages { - if i == 0 || packageLetter(pkg.Name) != packageLetter(packages[i-1].Name) { + if i == 0 || packageLetter(pkg.Package) != packageLetter(packages[i-1].Package) { <div class="col-md-2 px-2"> - <a href={ templ.URL("#" + packageLetter(pkg.Name)) } class="text-muted text-capitalize"> - { packageLetter(pkg.Name) } + <a href={ templ.URL("#" + packageLetter(pkg.Package)) } class="text-muted text-capitalize"> + { packageLetter(pkg.Package) } </a> </div> } @@ -57,54 +56,18 @@ templ showPackages(packages []*models.Package) { </div> } -func collectStabilizations(packages []*models.Package) (stabilizations []*models.PkgCheckResult) { - for _, pkg := range packages { - for _, ver := range pkg.Versions { - for _, res := range ver.PkgCheckResults { - if res.Class == "StableRequest" { - stabilizations = append(stabilizations, res) - break - } - } - } - } - return -} - -func collectOutdated(packages []*models.Package) (outdated []components.OutdatedItem) { - for _, pkg := range packages { - if len(pkg.Outdated) > 0 { - outdated = append(outdated, components.OutdatedItem{ - Atom: pkg.Atom, - Description: pkg.Description(), - }) - } - } - return -} - -templ show(pageName string, category *models.Category, pullRequests []*models.GithubPullRequest) { +templ show(component templ.Component) { <div class="container mb-5 tab-pane fade show active" id="overview" role="tabpanel" aria-labelledby="overview-tab"> - switch pageName { - case "Packages": - @showPackages(category.Packages) - case "Stabilization": - @components.Stabilizations(category.PackagesInformation.StableRequests > 0, collectStabilizations(category.Packages)) - case "Outdated": - @components.Outdated(collectOutdated(category.Packages)) - case "Pull requests": - @components.PullRequests(category.PackagesInformation.PullRequests > 0, pullRequests) - } + @component </div> } -func renderShowPage(w http.ResponseWriter, r *http.Request, currentTab string, category *models.Category, pullRequests []*models.GithubPullRequest) { +func renderShowPage(w http.ResponseWriter, r *http.Request, currentTab string, category *models.Category, component templ.Component) { layout.TabbedLayout(category.Name, "packages", category.Name, "fa fa-fw fa-cubes", category.Description, []layout.SubTab{ { - Name: "Packages", - Link: templ.URL("/categories/" + category.Name), - Icon: "fa fa-list-ul mr-1", - BadgeValue: strconv.Itoa(len(category.Packages)), + Name: "Packages", + Link: templ.URL("/categories/" + category.Name), + Icon: "fa fa-list-ul mr-1", }, { Name: "Stabilization", @@ -124,5 +87,5 @@ func renderShowPage(w http.ResponseWriter, r *http.Request, currentTab string, c Icon: "octicon octicon-git-pull-request opticon-resource-icon ml-1", BadgeValue: strconv.Itoa(category.PackagesInformation.PullRequests), }, - }, currentTab, show(currentTab, category, pullRequests)).Render(r.Context(), w) + }, currentTab, show(component)).Render(r.Context(), w) } diff --git a/pkg/app/handler/maintainer/show.go b/pkg/app/handler/maintainer/show.go index 981a5c6..5f05382 100644 --- a/pkg/app/handler/maintainer/show.go +++ b/pkg/app/handler/maintainer/show.go @@ -261,17 +261,18 @@ func ShowStabilizationFile(w http.ResponseWriter, r *http.Request) { } pageName := r.URL.Path[strings.LastIndexByte(r.URL.Path, '/')+1:] - var gpackages []*models.Package - err = query.Model(&gpackages). - Relation("Versions"). - Relation("Versions.PkgCheckResults", func(q *pg.Query) (*pg.Query, error) { - return q.Where("class = ?", "StableRequest"), nil - }).Select() + var results []*models.PkgCheckResult + err = database.DBCon.Model(&results). + Column("atom", "cpv", "message"). + Where("class = ?", "StableRequest"). + Where("atom IN (?)", query). + OrderExpr("cpv"). + Select() if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } - utils.StabilizationExport(w, pageName, gpackages) + utils.StabilizationExport(w, pageName, results) } func ShowStabilizationFeed(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/app/serve.go b/pkg/app/serve.go index d13cada..6a6bf9a 100644 --- a/pkg/app/serve.go +++ b/pkg/app/serve.go @@ -27,14 +27,20 @@ import ( // Serve is used to serve the web application func Serve() { - database.Connect() defer database.DBCon.Close() setRoute("GET /categories", categories.Index) setRoute("GET /categories.json", categories.JSONCategories) - setRoute("GET /categories/{category}", categories.Show) - setRoute("GET /categories/{category}/{pageName}", categories.Show) + setRoute("GET /categories/{category}", categories.ShowPackages) + setRoute("GET /categories/{category}/outdated", categories.ShowOutdated) + setRoute("GET /categories/{category}/outdated.atom", categories.OutdatedFeed) + setRoute("GET /categories/{category}/pull-requests", categories.ShowPullRequests) + setRoute("GET /categories/{category}/stabilization", categories.ShowStabilizations) + setRoute("GET /categories/{category}/stabilization.atom", categories.StabilizationFeed) + setRoute("GET /categories/{category}/stabilization.json", categories.ShowStabilizationFile) + setRoute("GET /categories/{category}/stabilization.list", categories.ShowStabilizationFile) + setRoute("GET /categories/{category}/stabilization.xml", categories.ShowStabilizationFile) setRoute("GET /useflags/popular.json", useflags.Popular) setRoute("GET /useflags/suggest.json", useflags.Suggest) diff --git a/pkg/app/utils/stabilization.go b/pkg/app/utils/stabilization.go index 4395294..85a8111 100644 --- a/pkg/app/utils/stabilization.go +++ b/pkg/app/utils/stabilization.go @@ -24,18 +24,14 @@ func (s stabilization) String() string { return s.Category + "/" + s.Package + "-" + s.Version + " # " + s.Message } -func StabilizationExport(w http.ResponseWriter, pageUrl string, gpackages []*models.Package) { - result := make([]stabilization, 0) - for _, gpackage := range gpackages { - for _, version := range gpackage.Versions { - for _, pkgcheck := range version.PkgCheckResults { - result = append(result, stabilization{ - Category: pkgcheck.Category, - Package: pkgcheck.Package, - Version: pkgcheck.Version, - Message: pkgcheck.Message, - }) - } +func StabilizationExport(w http.ResponseWriter, pageUrl string, results []*models.PkgCheckResult) { + result := make([]stabilization, len(results)) + for i, pkgcheck := range results { + result[i] = stabilization{ + Category: pkgcheck.Category, + Package: pkgcheck.Package, + Version: pkgcheck.Version, + Message: pkgcheck.Message, } } |