diff options
author | Arthur Zamarin <arthurzam@gentoo.org> | 2024-02-15 22:06:22 +0200 |
---|---|---|
committer | Arthur Zamarin <arthurzam@gentoo.org> | 2024-02-20 09:08:41 +0200 |
commit | 2686c931924411bc6fb57d21a4365cc958ef2d1d (patch) | |
tree | f35f1d5acecb8bb3a9ad46f41a059d0ad827903a /pkg | |
parent | migrate index page (diff) | |
download | soko-2686c931924411bc6fb57d21a4365cc958ef2d1d.tar.gz soko-2686c931924411bc6fb57d21a4365cc958ef2d1d.tar.bz2 soko-2686c931924411bc6fb57d21a4365cc958ef2d1d.zip |
migrate useflags pages
Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/app/handler/useflags/expand.go | 45 | ||||
-rw-r--r-- | pkg/app/handler/useflags/expand.templ | 60 | ||||
-rw-r--r-- | pkg/app/handler/useflags/global.go | 46 | ||||
-rw-r--r-- | pkg/app/handler/useflags/global.templ | 44 | ||||
-rw-r--r-- | pkg/app/handler/useflags/index.go | 30 | ||||
-rw-r--r-- | pkg/app/handler/useflags/local.go | 46 | ||||
-rw-r--r-- | pkg/app/handler/useflags/local.templ | 48 | ||||
-rw-r--r-- | pkg/app/handler/useflags/popular.templ | 31 | ||||
-rw-r--r-- | pkg/app/handler/useflags/search.go | 59 | ||||
-rw-r--r-- | pkg/app/handler/useflags/search.templ | 92 | ||||
-rw-r--r-- | pkg/app/handler/useflags/show.go | 132 | ||||
-rw-r--r-- | pkg/app/handler/useflags/show.templ | 175 | ||||
-rw-r--r-- | pkg/app/handler/useflags/utils.go | 20 | ||||
-rw-r--r-- | pkg/app/layout/page.templ | 86 | ||||
-rw-r--r-- | pkg/app/serve.go | 2 |
15 files changed, 533 insertions, 383 deletions
diff --git a/pkg/app/handler/useflags/expand.go b/pkg/app/handler/useflags/expand.go deleted file mode 100644 index 631f70a..0000000 --- a/pkg/app/handler/useflags/expand.go +++ /dev/null @@ -1,45 +0,0 @@ -package useflags - -import ( - "html/template" - "net/http" - "soko/pkg/app/utils" - "soko/pkg/database" - "soko/pkg/models" - - "github.com/go-pg/pg" -) - -func Expand(w http.ResponseWriter, r *http.Request) { - var useflags []models.Useflag - err := database.DBCon.Model(&useflags). - Where("scope = 'use_expand'"). - Order("use_expand", "name"). - Select() - if err != nil && err != pg.ErrNoRows { - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) - return - } - - data := struct { - Header models.Header - Page string - Useflags []models.Useflag - Application models.Application - }{ - Header: models.Header{Title: "Use Expand" + " – ", Tab: "useflags"}, - Page: "expand", - Useflags: useflags, - Application: utils.GetApplicationData(), - } - - templates := template.Must( - template.Must( - template.Must( - template.New("Show").ParseGlob("web/templates/layout/*.tmpl")). - ParseGlob("web/templates/useflags/browseuseflagsheader.tmpl")). - ParseGlob("web/templates/useflags/listexpand.tmpl")) - - templates.ExecuteTemplate(w, "listexpand.tmpl", data) -} diff --git a/pkg/app/handler/useflags/expand.templ b/pkg/app/handler/useflags/expand.templ new file mode 100644 index 0000000..82581f2 --- /dev/null +++ b/pkg/app/handler/useflags/expand.templ @@ -0,0 +1,60 @@ +package useflags + +import "net/http" +import "soko/pkg/database" +import "soko/pkg/models" +import "github.com/go-pg/pg/v10" + +templ expand(useflags []models.Useflag) { + <div class="container mb-5"> + <div class="row"> + <div class="col-md-9"> + <div class="card border-0"> + <div class="list-group"> + for i, use := range useflags { + if i == 0 || use.UseExpand != useflags[i-1].UseExpand { + @templ.Raw("</div></div>") + <h3 class={ templ.KV("mt-4", i > 0) } id={ use.UseExpand }>{ use.UseExpand }</h3> + @templ.Raw(`<div class="card border-0"><div class="list-group">`) + } + <a + class="list-group-item list-group-item-action text-dark" + href={ templ.SafeURL("/useflags/" + use.Name) } + > + <h3 class="kk-search-result-header">{ use.Name }</h3> + { use.Description } + </a> + } + </div> + </div> + </div> + <div class="col-md-3"> + <dl> + <dd class="ml-3 mb-0"> + for i, use := range useflags { + if i == 0 || use.UseExpand != useflags[i-1].UseExpand { + <a href={ templ.URL("#" + use.UseExpand) } class="text-muted">{ use.UseExpand }</a> + <br/> + } + } + </dd> + </dl> + </div> + </div> + </div> +} + +func Expand(w http.ResponseWriter, r *http.Request) { + var useflags []models.Useflag + err := database.DBCon.Model(&useflags). + Where("scope = 'use_expand'"). + Order("use_expand", "name"). + Column("use_expand", "name", "description"). + Select() + if err != nil && err != pg.ErrNoRows { + http.Error(w, http.StatusText(http.StatusInternalServerError), + http.StatusInternalServerError) + return + } + RenderPage(w, r, "USE Expand", "USE Expand", expand(useflags)) +} diff --git a/pkg/app/handler/useflags/global.go b/pkg/app/handler/useflags/global.go deleted file mode 100644 index 63e8e3e..0000000 --- a/pkg/app/handler/useflags/global.go +++ /dev/null @@ -1,46 +0,0 @@ -package useflags - -import ( - "html/template" - "net/http" - "soko/pkg/app/utils" - "soko/pkg/database" - "soko/pkg/models" - - "github.com/go-pg/pg" -) - -func Global(w http.ResponseWriter, r *http.Request) { - - var useflags []models.Useflag - err := database.DBCon.Model(&useflags). - Order("name"). - Where("scope = 'global'"). - Select() - if err != nil && err != pg.ErrNoRows { - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) - return - } - - data := struct { - Header models.Header - Page string - Useflags []models.Useflag - Application models.Application - }{ - Header: models.Header{Title: "Global" + " – ", Tab: "useflags"}, - Page: "global", - Useflags: useflags, - Application: utils.GetApplicationData(), - } - - templates := template.Must( - template.Must( - template.Must( - template.New("Show").ParseGlob("web/templates/layout/*.tmpl")). - ParseGlob("web/templates/useflags/browseuseflagsheader.tmpl")). - ParseGlob("web/templates/useflags/list.tmpl")) - - templates.ExecuteTemplate(w, "list.tmpl", data) -} diff --git a/pkg/app/handler/useflags/global.templ b/pkg/app/handler/useflags/global.templ new file mode 100644 index 0000000..46fe1f0 --- /dev/null +++ b/pkg/app/handler/useflags/global.templ @@ -0,0 +1,44 @@ +package useflags + +import "net/http" +import "soko/pkg/database" +import "soko/pkg/models" +import "github.com/go-pg/pg/v10" + +templ global(useflags []models.Useflag) { + <div class="container mb-5"> + <div class="row"> + <div class="col-12"> + <h3><span class="text-capitalize">Global</span> USE flags</h3> + <div class="card border-0"> + <div class="list-group"> + for _, use := range useflags { + <a + class="list-group-item list-group-item-action text-dark" + href={ templ.SafeURL("/useflags/" + use.Name) } + > + <h3 class="kk-search-result-header">{ use.Name }</h3> + { use.Description } + </a> + } + </div> + </div> + </div> + </div> + </div> +} + +func Global(w http.ResponseWriter, r *http.Request) { + var useflags []models.Useflag + err := database.DBCon.Model(&useflags). + Where("scope = 'global'"). + Order("name"). + Column("name", "description"). + Select() + if err != nil && err != pg.ErrNoRows { + http.Error(w, http.StatusText(http.StatusInternalServerError), + http.StatusInternalServerError) + return + } + RenderPage(w, r, "Global", "Global", global(useflags)) +} diff --git a/pkg/app/handler/useflags/index.go b/pkg/app/handler/useflags/index.go index c14161e..d08d62b 100644 --- a/pkg/app/handler/useflags/index.go +++ b/pkg/app/handler/useflags/index.go @@ -3,40 +3,14 @@ package useflags import ( - "html/template" "net/http" - utils2 "soko/pkg/app/utils" - "soko/pkg/models" + "soko/pkg/app/utils" ) // Index renders a template to show the index page of the USE flags // section containing a bubble chart of popular USE flags -func Index(w http.ResponseWriter, r *http.Request) { - - data := struct { - Header models.Header - Page string - Application models.Application - }{ - Header: models.Header{Title: "Useflags – ", Tab: "useflags"}, - Page: "browse", - Application: utils2.GetApplicationData(), - } - - templates := template.Must( - template.Must( - template.Must( - template.New("Show").ParseGlob("web/templates/layout/*.tmpl")). - ParseGlob("web/templates/useflags/browseuseflagsheader.tmpl")). - ParseGlob("web/templates/useflags/index.tmpl")) - - templates.ExecuteTemplate(w, "index.tmpl", data) -} - -// Index renders a template to show the index page of the USE flags -// section containing a bubble chart of popular USE flags func Default(w http.ResponseWriter, r *http.Request) { - userPreferences := utils2.GetUserPreferences(r) + userPreferences := utils.GetUserPreferences(r) if userPreferences.Useflags.Layout == "bubble" { http.Redirect(w, r, "/useflags/popular", http.StatusSeeOther) } else { diff --git a/pkg/app/handler/useflags/local.go b/pkg/app/handler/useflags/local.go deleted file mode 100644 index 63a5a76..0000000 --- a/pkg/app/handler/useflags/local.go +++ /dev/null @@ -1,46 +0,0 @@ -package useflags - -import ( - "html/template" - "net/http" - "soko/pkg/app/utils" - "soko/pkg/database" - "soko/pkg/models" - - "github.com/go-pg/pg" -) - -func Local(w http.ResponseWriter, r *http.Request) { - - var useflags []models.Useflag - err := database.DBCon.Model(&useflags). - Where("scope = 'local'"). - Order("package", "name"). - Select() - if err != nil && err != pg.ErrNoRows { - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) - return - } - - data := struct { - Header models.Header - Page string - Useflags []models.Useflag - Application models.Application - }{ - Header: models.Header{Title: "Local" + " – ", Tab: "useflags"}, - Page: "local", - Useflags: useflags, - Application: utils.GetApplicationData(), - } - - templates := template.Must( - template.Must( - template.Must( - template.New("Show").ParseGlob("web/templates/layout/*.tmpl")). - ParseGlob("web/templates/useflags/browseuseflagsheader.tmpl")). - ParseGlob("web/templates/useflags/listlocal.tmpl")) - - templates.ExecuteTemplate(w, "listlocal.tmpl", data) -} diff --git a/pkg/app/handler/useflags/local.templ b/pkg/app/handler/useflags/local.templ new file mode 100644 index 0000000..01a7544 --- /dev/null +++ b/pkg/app/handler/useflags/local.templ @@ -0,0 +1,48 @@ +package useflags + +import "net/http" +import "soko/pkg/database" +import "soko/pkg/models" +import "github.com/go-pg/pg/v10" + +templ local(useflags []models.Useflag) { + <div class="container mb-5"> + <div class="row"> + <div class="col-12"> + <div class="card border-0"> + <div class="list-group"> + for i, use := range useflags { + if i == 0 || use.Package != useflags[i-1].Package { + @templ.Raw("</div></div>") + <h3 class={ templ.KV("mt-4", i > 0) }>{ use.Package }</h3> + @templ.Raw(`<div class="card border-0"><div class="list-group">`) + } + <a + class="list-group-item list-group-item-action text-dark" + href={ templ.SafeURL("/useflags/" + use.Name) } + > + <h3 class="kk-search-result-header">{ use.Name }</h3> + { use.Description } + </a> + } + </div> + </div> + </div> + </div> + </div> +} + +func Local(w http.ResponseWriter, r *http.Request) { + var useflags []models.Useflag + err := database.DBCon.Model(&useflags). + Where("scope = 'local'"). + Order("package", "name"). + Column("package", "name", "description"). + Select() + if err != nil && err != pg.ErrNoRows { + http.Error(w, http.StatusText(http.StatusInternalServerError), + http.StatusInternalServerError) + return + } + RenderPage(w, r, "Local", "Local", local(useflags)) +} diff --git a/pkg/app/handler/useflags/popular.templ b/pkg/app/handler/useflags/popular.templ new file mode 100644 index 0000000..716a73a --- /dev/null +++ b/pkg/app/handler/useflags/popular.templ @@ -0,0 +1,31 @@ +package useflags + +import "net/http" + +templ popular() { + <div class="container mb-5"> + <div class="row"> + <div class="col-12"> + <div class="card" style="background: none;border: none;"> + <noscript> + <div class="panel-body kk-panel-content-sorry"> + This feature requires JavaScript to work. + </div> + </noscript> + <div + class="panel-body kk-useflag-bubble-container" + id="bubble-placeholder" + style="overflow: hidden!important; display: none;" + ></div> + </div> + </div> + </div> + </div> + <script src="/assets/useflags.js"></script> +} + +// PopularPage renders a template to show the index page of the USE flags +// section containing a bubble chart of popular USE flags +func PopularPage(w http.ResponseWriter, r *http.Request) { + RenderPage(w, r, "Useflags", "Widely used", popular()) +} diff --git a/pkg/app/handler/useflags/search.go b/pkg/app/handler/useflags/search.go deleted file mode 100644 index 31d0bae..0000000 --- a/pkg/app/handler/useflags/search.go +++ /dev/null @@ -1,59 +0,0 @@ -// Used to search for USE flags - -package useflags - -import ( - "html/template" - "net/http" - "soko/pkg/app/utils" - "soko/pkg/database" - "soko/pkg/models" - - "github.com/go-pg/pg" -) - -// Search renders a template containing a list of search results -// for a given query of USE flags -func Search(w http.ResponseWriter, r *http.Request) { - - results := r.URL.Query()["q"] - - param := "" - var useflags []models.Useflag - if len(results) != 0 { - param = results[0] - err := database.DBCon.Model(&useflags). - Column("name", "description", "scope", "package"). - Where("name LIKE ?", param+"%"). - OrderExpr("scope, name <-> ?", param). - Select() - if err != nil && err != pg.ErrNoRows { - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) - return - } - } - - data := struct { - Header models.Header - Page string - Search string - Useflags []models.Useflag - Application models.Application - }{ - Header: models.Header{Title: param + " – ", Tab: "useflags"}, - Page: "search", - Search: param, - Useflags: useflags, - Application: utils.GetApplicationData(), - } - - templates := template.Must( - template.Must( - template.Must( - template.New("Show").ParseGlob("web/templates/layout/*.tmpl")). - ParseGlob("web/templates/useflags/browseuseflagsheader.tmpl")). - ParseGlob("web/templates/useflags/search.tmpl")) - - templates.ExecuteTemplate(w, "search.tmpl", data) -} diff --git a/pkg/app/handler/useflags/search.templ b/pkg/app/handler/useflags/search.templ new file mode 100644 index 0000000..bcfa88a --- /dev/null +++ b/pkg/app/handler/useflags/search.templ @@ -0,0 +1,92 @@ +package useflags + +import "net/http" +import "soko/pkg/database" +import "soko/pkg/models" +import "github.com/go-pg/pg/v10" + +css searchButton() { + border-top-right-radius: 0.25rem !important; + border-bottom-right-radius: 0.25rem !important; + font-size: 1.1em !important; + height: 2.3em !important; + border-left: 0px; + box-shadow: inset 0 1px 1px rgba(0,0,0,0.075) !important; +} + +templ search(query string, useflags []models.Useflag) { + <div class="container mb-5"> + <div class="row"> + <div class={ "col-12", templ.KV("mt-5", len(useflags) == 0), templ.KV("pt-5", len(useflags) == 0) }> + <div class="col-12 mt-3 text-center"> + <h2>Find USE flags</h2> + </div> + <div class="col-12"> + <form action="/useflags/search" method="get" class="useflag-search mt-3 mb-5 mx-5 px-5"> + <div class="typeahead__container mx-5 px-5"> + <div class="typeahead__field"> + <span class="typeahead__query" style="font-size: 1.1em; height: 2.3em;"> + <input id="q" name="q" class="rounded-left" style="font-size: 1.1em; height: 2.3em;border-right: 0px;" type="search" autocomplete="off" placeholder="Find USE flags"/> + </span> + <span class="typeahead__button" style="font-size: 1.1em!important; height: 2.3em!important;border-left: 0px;"> + <button class={ searchButton() } type="submit"> + <span class="typeahead__search-icon"></span> + </button> + </span> + </div> + </div> + </form> + </div> + if query != "" { + if len(useflags) > 0 { + <h2>USE Flag Search Results <small>{ "for" } { query }</small></h2> + <div class="card border-0"> + <div class="list-group"> + for _, use := range useflags { + <a + class="list-group-item list-group-item-action text-dark" + href={ templ.URL("/useflags/" + use.Name) } + > + <h3 class="kk-search-result-header"> + { use.Name } + if use.Scope == "local" { + <span class="text-secondary">({ use.Package })</span> + } + </h3> + { use.Description } + </a> + } + </div> + </div> + } else { + <h2>No results found <small>{ "for" } { query }</small></h2> + } + } + </div> + </div> + </div> + <script src="/assets/useflags.js"></script> +} + +// Search renders a template containing a list of search results +// for a given query of USE flags +func Search(w http.ResponseWriter, r *http.Request) { + results := r.URL.Query()["q"] + + param := "" + var useflags []models.Useflag + if len(results) != 0 { + param = results[0] + err := database.DBCon.Model(&useflags). + Column("name", "description", "scope", "package"). + Where("name LIKE ?", param+"%"). + OrderExpr("scope, name <-> ?", param). + Select() + if err != nil && err != pg.ErrNoRows { + http.Error(w, http.StatusText(http.StatusInternalServerError), + http.StatusInternalServerError) + return + } + } + RenderPage(w, r, param, "Search", search(param, useflags)) +} diff --git a/pkg/app/handler/useflags/show.go b/pkg/app/handler/useflags/show.go deleted file mode 100644 index 6823274..0000000 --- a/pkg/app/handler/useflags/show.go +++ /dev/null @@ -1,132 +0,0 @@ -// Used to show a specific package - -package useflags - -import ( - "html/template" - "net/http" - "soko/pkg/app/utils" - "soko/pkg/database" - "soko/pkg/models" - "strings" - - "github.com/go-pg/pg/v10" -) - -// Show renders a template to show a given USE flag -func Show(w http.ResponseWriter, r *http.Request) { - useFlagName := r.URL.Path[len("/useflags/"):] - - var useflags []models.Useflag - err := database.DBCon.Model(&useflags).Where("name = ?", useFlagName).Select() - if err != nil || len(useflags) < 1 { - http.NotFound(w, r) - return - } - - useflag := useflags[0] - var localuseflags []models.Useflag - - for _, use := range useflags { - if use.Scope == "global" { - useflag = use - } else if use.Scope == "local" { - localuseflags = append(localuseflags, use) - } else if use.Scope == "use_expand" { - ShowUseExpand(w, r, use) - return - } - } - - var packages []string - err = database.DBCon.Model((*models.Version)(nil)). - Column("atom").Distinct(). - Where("useflags::jsonb @> ?", "\""+useFlagName+"\""). - Select(&packages) - if err != nil && err != pg.ErrNoRows { - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) - return - } - - data := struct { - Header models.Header - Page string - Useflag models.Useflag - LocalUseflags []models.Useflag - Packages []string - Application models.Application - }{ - Header: models.Header{Title: useflag.Name + " – ", Tab: "useflags"}, - Page: "show", - Useflag: useflag, - LocalUseflags: localuseflags, - Packages: packages, - Application: utils.GetApplicationData(), - } - - templates := template.Must( - template.Must( - template.Must( - template.New("Show").Funcs(template.FuncMap{ - "replaceall": strings.ReplaceAll, - }).ParseGlob("web/templates/layout/*.tmpl")). - ParseGlob("web/templates/useflags/useflagsheader.tmpl")). - ParseGlob("web/templates/useflags/show.tmpl")) - - templates.ExecuteTemplate(w, "show.tmpl", data) -} - -// ShowUseExpand renders a template to show a given use_expand -func ShowUseExpand(w http.ResponseWriter, r *http.Request, useExpand models.Useflag) { - funcMap := template.FuncMap{ - "replaceall": strings.ReplaceAll, - } - - var otherUseExpands []models.Useflag - err := database.DBCon.Model(&otherUseExpands). - Column("name", "description"). - Where("use_expand = ?", useExpand.UseExpand). - Select() - if err != nil && err != pg.ErrNoRows { - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) - return - } - - var packages []string - err = database.DBCon.Model((*models.Version)(nil)). - Column("atom").Distinct(). - Where("useflags::jsonb @> ?", "\""+useExpand.Name+"\""). - Select(&packages) - if err != nil && err != pg.ErrNoRows { - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) - return - } - - data := struct { - Header models.Header - Page string - Useflag models.Useflag - OtherUseExpands []models.Useflag - Packages []string - Application models.Application - }{ - Header: models.Header{Title: useExpand.Name + " – ", Tab: "useflags"}, - Page: "show", - Useflag: useExpand, - OtherUseExpands: otherUseExpands, - Packages: packages, - Application: utils.GetApplicationData(), - } - - templates := template.Must( - template.Must( - template.Must( - template.New("Show").Funcs(funcMap).ParseGlob("web/templates/layout/*.tmpl")). - ParseGlob("web/templates/useflags/useflagsheader.tmpl")). - ParseGlob("web/templates/useflags/showexpand.tmpl")) - - templates.ExecuteTemplate(w, "showexpand.tmpl", data) -} diff --git a/pkg/app/handler/useflags/show.templ b/pkg/app/handler/useflags/show.templ new file mode 100644 index 0000000..aa8dd80 --- /dev/null +++ b/pkg/app/handler/useflags/show.templ @@ -0,0 +1,175 @@ +package useflags + +import "net/http" +import "strconv" +import "strings" +import "soko/pkg/app/layout" +import "soko/pkg/database" +import "soko/pkg/models" +import "github.com/go-pg/pg/v10" + +templ showUseflagHeader(useflag models.Useflag) { + <div class="kk-header-container"> + <div class="container"> + <div class="row"> + <div class="col-12"> + <div class="row mt-3 pt-2"> + <div class="col-md-5"> + <h1 class="stick-top kk-package-title" id="package-title"> + <small class="kk-package-cat"> + <a href="/useflags" class={ "text-dark", "ml-1", templ.KV("text-capitalize", useflag.UseExpand == "") }> + if useflag.UseExpand != "" { + { useflag.UseExpand } + } else { + { useflag.Scope } USE flag + } + </a> + </small> + <div> + <div class="kk-package-name" style="margin-left: 0px!important;"> + <span class="fa fa-fw fa-sliders"></span> + <span class="ml-2"> + if useflag.UseExpand != "" { + { strings.TrimPrefix(useflag.Name, useflag.UseExpand + "_") } + } else { + { useflag.Name } + } + </span> + </div> + </div> + </h1> + </div> + if useflag.Scope != "local" { + <div class="col-md-7"> + <p class="lead kk-package-maindesc"> + { useflag.Description } + </p> + </div> + } + <div class="col-md-12 pt-4 mt-1"></div> + </div> + </div> + </div> + </div> + </div> +} + +templ show(useflag models.Useflag, localUseflags, otherUseExpands []models.Useflag, Packages []string) { + @showUseflagHeader(useflag) + <div class="tab-content" id="myTabContent"> + <div class="container mb-5"> + <div class="row"> + <div class="col-12"> + if len(otherUseExpands) != 0 { + <h3 class="mb-2">Other “{ useflag.UseExpand }” USE_EXPAND flag values</h3> + <div class="card"> + <div class="table-responsive"> + <table class="table"> + <thead> + <th>Use Flag</th> + <th>Description</th> + </thead> + <tbody> + for _, use := range otherUseExpands { + <tr> + <th class="kk-nobreak-cell"> + <a href={ templ.URL("/useflags/" + use.Name) }>{ use.Name }</a> + </th> + <td>{ use.Description }</td> + </tr> + } + </tbody> + </table> + </div> + </div> + } + if len(localUseflags) != 0 { + <h3 class="mb-2">Packages describing “{ useflag.Name }” as local USE flag</h3> + <div class="card mb-4 border-top-0"> + <div class="table-responsive"> + <table class="table mb-0"> + <thead> + <th>Package</th> + <th>“{ useflag.Name }” Flag Description</th> + </thead> + <tbody> + for _, use := range localUseflags { + <tr> + <th class="kk-nobreak-cell"> + <a href={ templ.URL("/packages/" + use.Package) }>{ use.Package }</a> + </th> + <td>{ use.Description }</td> + </tr> + } + </tbody> + </table> + </div> + </div> + } + if len(Packages) != 0 { + <h3 class="mb-2 pt-2">All packages providing a “{ useflag.Name }” USE flag ({ strconv.Itoa(len(Packages)) })</h3> + <div class="card"> + <div class="card-body"> + <ul class="kk-col-list kk-3col-list kk-useflag-listing mb-0"> + for _, pkg := range Packages { + <li><a href={ templ.URL("/packages/" + pkg) }>{ pkg }</a></li> + } + </ul> + </div> + </div> + } + </div> + </div> + </div> + </div> +} + +// Show renders a template to show a given USE flag +func Show(w http.ResponseWriter, r *http.Request) { + useFlagName := r.URL.Path[len("/useflags/"):] + + var useflags []models.Useflag + err := database.DBCon.Model(&useflags). + Where("name = ?", useFlagName). + Order("scope", "package"). + Select() + if err != nil || len(useflags) < 1 { + http.NotFound(w, r) + return + } + + var packages []string + err = database.DBCon.Model((*models.Version)(nil)). + Column("atom").Distinct(). + Where("useflags::jsonb @> ?", "\""+useFlagName+"\""). + Order("atom"). + Select(&packages) + if err != nil && err != pg.ErrNoRows { + http.Error(w, http.StatusText(http.StatusInternalServerError), + http.StatusInternalServerError) + return + } + + useflag := useflags[0] + + var localUseFlags, otherUseExpands []models.Useflag + if use := useflags[len(useflags)-1]; use.Scope == "use_expand" { + err := database.DBCon.Model(&otherUseExpands). + Column("name", "description"). + Where("use_expand = ?", useflag.UseExpand). + Order("name"). + Select() + if err != nil && err != pg.ErrNoRows { + http.Error(w, http.StatusText(http.StatusInternalServerError), + http.StatusInternalServerError) + return + } + } else if useflag.Scope == "global" { + localUseFlags = useflags[1:] + } else { + localUseFlags = useflags + } + + layout.Layout(useFlagName, "useflags", + show(useflag, localUseFlags, otherUseExpands, packages)).Render(r.Context(), w) +} diff --git a/pkg/app/handler/useflags/utils.go b/pkg/app/handler/useflags/utils.go new file mode 100644 index 0000000..54d0828 --- /dev/null +++ b/pkg/app/handler/useflags/utils.go @@ -0,0 +1,20 @@ +package useflags + +import ( + "net/http" + "soko/pkg/app/layout" + + "github.com/a-h/templ" +) + +var tabs = []layout.SubTab{ + {Name: "Widely used", Link: templ.URL("/useflags"), Icon: "fa fa-line-chart mr-1"}, + {Name: "Search", Link: templ.URL("/useflags/search"), Icon: "fa fa-search mr-1"}, + {Name: "Global", Link: templ.URL("/useflags/global"), Icon: "fa fa-globe mr-1"}, + {Name: "Local", Link: templ.URL("/useflags/local"), Icon: "fa fa-map-marker mr-1"}, + {Name: "USE Expand", Link: templ.URL("/useflags/expand"), Icon: "fa fa-list mr-1"}, +} + +func RenderPage(w http.ResponseWriter, r *http.Request, title string, currentTab string, content templ.Component) { + layout.TabbedLayout(title, "useflags", "USE flags", "fa fa-fw fa-sliders", tabs, currentTab, content).Render(r.Context(), w) +} diff --git a/pkg/app/layout/page.templ b/pkg/app/layout/page.templ index 98509ce..7fc5a24 100644 --- a/pkg/app/layout/page.templ +++ b/pkg/app/layout/page.templ @@ -5,12 +5,12 @@ import "soko/pkg/config" templ head(title string) { <head> <title> - if title != "" { - { title } – Gentoo Packages - } else { - Gentoo Packages - } - </title> + if title != "" { + { title } – Gentoo Packages + } else { + Gentoo Packages + } + </title> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="theme-color" content="#54487a"/> @@ -59,13 +59,6 @@ templ siteTitle() { </div> } -func activeClass(tab string, currentTab string) string { - if tab == currentTab { - return "nav-item active" - } - return "nav-item" -} - templ navigationBar(tab string) { <nav class="tyrian-navbar navbar navbar-dark navbar-expand-lg bg-primary" role="navigation"> <div class="container"> @@ -76,12 +69,12 @@ templ navigationBar(tab string) { </div> <div class="collapse navbar-collapse navbar-main-collapse" id="navbar-main-collapse"> <ul class="navbar-nav mr-auto"> - <li class={ activeClass("home", tab) }><a class="nav-link" href="/">Home</a></li> - <li class={ activeClass("packages", tab) }><a class="nav-link" href="/categories">Packages</a></li> - <li class={ activeClass("maintainers", tab) }><a class="nav-link" href="/maintainers">Maintainers</a></li> - <li class={ activeClass("useflags", tab) }><a class="nav-link" href="/useflags">USE flags</a></li> - <li class={ activeClass("arches", tab) }><a class="nav-link" href="/arches">Architectures</a></li> - <li class={ activeClass("about", tab) }><a class="nav-link" href="/about">About</a></li> + <li class={ "nav-item", templ.KV("active", tab == "home") }><a class="nav-link" href="/">Home</a></li> + <li class={ "nav-item", templ.KV("active", tab == "packages") }><a class="nav-link" href="/categories">Packages</a></li> + <li class={ "nav-item", templ.KV("active", tab == "maintainers") }><a class="nav-link" href="/maintainers">Maintainers</a></li> + <li class={ "nav-item", templ.KV("active", tab == "useflags") }><a class="nav-link" href="/useflags">USE flags</a></li> + <li class={ "nav-item", templ.KV("active", tab == "arches") }><a class="nav-link" href="/arches">Architectures</a></li> + <li class={ "nav-item", templ.KV("active", tab == "about") }><a class="nav-link" href="/about">About</a></li> </ul> if tab != "home" { <form class="form-inline inlinesearch" role="search" action="/packages/search" method="get"> @@ -110,7 +103,7 @@ templ footer() { </ul> </div> <div class="col-8 col-sm-8 col-md-8"> - <strong>© 2001–2023 Gentoo Authors</strong> + <strong>© 2001–2024 Gentoo Authors</strong> <br/> <small> Gentoo is a trademark of the Gentoo Foundation, Inc. @@ -121,10 +114,8 @@ templ footer() { </div> <div class="col-2 col-sm-2 col-md-2 text-right"> <strong><a class="text-dark" href="https://www.gentoo.org/inside-gentoo/contact/">Contact</a></strong> - <br /> - <small> - { config.Version() } - </small> + <br/> + <small>{ config.Version() }</small> </div> </div> </div> @@ -140,8 +131,51 @@ templ Layout(title string, tab string, contents templ.Component) { @siteTitle() @navigationBar(tab) </header> - @contents - @footer() + @contents + @footer() </body> </html> } + +type SubTab struct { + Name string + Link templ.SafeURL + Icon string +} + +templ tabbedHeader(subTitle string, icon string, tabs []SubTab, currentSubTab string, contents templ.Component) { + <div class="kk-header-container"> + <div class="container"> + <div class="row"> + <div class="col-12"> + <div class="row mt-3 pt-2"> + <div class="col-md-5"> + <h1 class="stick-top kk-package-title" id="package-title"> + <div> + <div class="kk-package-name" style="margin-left: 0px!important;"><span class={ icon }></span><span class="ml-2">{ subTitle }</span></div> + </div> + </h1> + </div> + <div class="col-md-7"></div> + <div class="col-md-12 pt-4 mt-1"> + <nav class="nav kk-package-nav"> + for _, tab := range tabs { + <a class={ "nav-link", templ.KV("active", tab.Name == currentSubTab) } href={ tab.Link }> + <i class={ tab.Icon } aria-hidden="true"></i> { tab.Name } + </a> + } + </nav> + </div> + </div> + </div> + </div> + </div> + </div> + <div class="tab-content" id="myTabContent"> + @contents + </div> +} + +templ TabbedLayout(title string, tab string, subTitle string, icon string, tabs []SubTab, currentSubTab string, contents templ.Component) { + @Layout(title, tab, tabbedHeader(subTitle, icon, tabs, currentSubTab, contents)) +} diff --git a/pkg/app/serve.go b/pkg/app/serve.go index 7f9f618..bd6c6ff 100644 --- a/pkg/app/serve.go +++ b/pkg/app/serve.go @@ -41,7 +41,7 @@ func Serve() { setRoute("/useflags/global", useflags.Global) setRoute("/useflags/local", useflags.Local) setRoute("/useflags/expand", useflags.Expand) - setRoute("/useflags/popular", useflags.Index) + setRoute("/useflags/popular", useflags.PopularPage) setRoute("/useflags", useflags.Default) setRoute("/useflags/", useflags.Show) |