Use PAS UI

This commit is contained in:
snoutie 2025-05-20 20:41:26 +02:00
parent 90f1c4738e
commit 6b8ae2f236
17 changed files with 794 additions and 100 deletions

View File

@ -33,9 +33,9 @@ type CDSViewFieldJSON struct {
//TODO: "https://api.sap.com/api/1.0/container/CDSViews/artifacts?containerType=contentType&$filter=Type%20eq%20'CDSVIEW'&$top=" + fmt.Sprint(top) + "&$skip=" + fmt.Sprint(skip)
func GetCDSViewField(CDSViewTechnicalName string) error {
func GetCDSViewField(CDSViewTechnicalName table.TechnicalName) error {
var json CDSViewFieldJSON
path := "https://api.sap.com/odata/1.0/catalog.svc/CdsViewsContent.CdsViews('" + CDSViewTechnicalName + "')/$value"
path := string("https://api.sap.com/odata/1.0/catalog.svc/CdsViewsContent.CdsViews('" + CDSViewTechnicalName + "')/$value")
fmt.Println("Getting: ", CDSViewTechnicalName)
err := RequestJSON(path, &json)
if err != nil {
@ -60,7 +60,7 @@ func GetCDSViewFields() {
for _, cdsView := range *cdsViews {
var json CDSViewFieldJSON
path := "https://api.sap.com/odata/1.0/catalog.svc/CdsViewsContent.CdsViews('" + cdsView + "')/$value"
path := string("https://api.sap.com/odata/1.0/catalog.svc/CdsViewsContent.CdsViews('" + cdsView + "')/$value")
fmt.Println("Getting: ", cdsView)
err := RequestJSON(path, &json)
if err != nil {

View File

@ -23,19 +23,19 @@ import (
)
type CDSView struct {
TechnicalName string `json:"Name"`
DisplayName string `json:"DisplayName"`
Description string `json:"Description"`
Version string `json:"Version"`
State string `json:"State"`
CreatedAt int `json:"CreatedAt"`
ModifiedAt int `json:"ModifiedAt"`
TechnicalName `json:"Name"`
DisplayName `json:"DisplayName"`
Description `json:"Description"`
Version `json:"Version"`
State `json:"State"`
CreatedAt `json:"CreatedAt"`
ModifiedAt `json:"ModifiedAt"`
}
//go:embed sql/query_cds_view.sql
var query_cds_view string
func GetCDSView(TechnicalName string) (*CDSView, error) {
func GetCDSView(TechnicalName TechnicalName) (*CDSView, error) {
row := database.DB.QueryRow(query_cds_view, TechnicalName)
var CDSView CDSView
@ -50,15 +50,15 @@ func GetCDSView(TechnicalName string) (*CDSView, error) {
//go:embed sql/query_all_cds_view_technical_names.sql
var query_all_cds_view_technical_names string
func QueryAllCDSViewTechnicalNames() (*[]string, error) {
func QueryAllCDSViewTechnicalNames() (*[]TechnicalName, error) {
rows, err := database.DB.Query(query_all_cds_view_technical_names)
if err != nil {
return nil, err
}
var technicalNames []string
var technicalNames []TechnicalName
for rows.Next() {
var technicalName string
var technicalName TechnicalName
err := rows.Scan(&technicalName)
if err != nil {
return nil, err

View File

@ -23,11 +23,11 @@ import (
)
type CDSViewField struct {
CDSViewTechnicalName string
FieldName string `json:"fieldname"`
Description string `json:"description"`
DataType string `json:"datatype"`
FieldLength string `json:"fieldlength"`
CDSViewTechnicalName TechnicalName
FieldName `json:"fieldname"`
Description `json:"description"`
DataType `json:"datatype"`
FieldLength `json:"fieldlength"`
}
//go:embed sql/query_cds_view_fields.sql
@ -53,7 +53,7 @@ func GetCDSViewFields(CDSViewTechnicalName string) (*[]CDSViewField, error) {
//go:embed sql/query_cds_view_number_of_fields.sql
var query_cds_view_number_of_fields string
func GetCDSViewNumberOfFields(CDSViewTechnicalName string) (int, error) {
func GetCDSViewNumberOfFields(CDSViewTechnicalName TechnicalName) (int, error) {
rows, err := database.DB.Query(query_cds_view_number_of_fields, CDSViewTechnicalName)
if err != nil {
return 0, err

135
cmd/database/table/field.go Normal file
View File

@ -0,0 +1,135 @@
package table
import "code.achtarmig.org/pas/ui/field"
// CDS View
type (
TechnicalName string
DisplayName string
Description string
Version string
State string
CreatedAt int
ModifiedAt int
)
// CDS View Field
type (
FieldName string
DataType string
FieldLength string
)
func (t TechnicalName) Info(language string) field.Info {
return field.Info{
Title: "Technical Name",
Details: "Technical Name of the CDS View",
}
}
func (t TechnicalName) String() string {
return string(t)
}
func (t DisplayName) Info(language string) field.Info {
return field.Info{
Title: "Name",
Details: "Name of the CDS View",
}
}
func (t DisplayName) String() string {
return string(t)
}
func (t Description) Info(language string) field.Info {
return field.Info{
Title: "Description",
Details: "Discription",
}
}
func (t Description) String() string {
return string(t)
}
func (t Version) Info(language string) field.Info {
return field.Info{
Title: "Version",
Details: "Version of the CDS View",
Justify: field.JustifyRight,
}
}
func (t Version) String() string {
return string(t)
}
func (t State) Info(language string) field.Info {
return field.Info{
Title: "Release State",
Details: "Release State of the CDS View. Non-Released views may not be used",
}
}
func (t State) String() string {
return string(t)
}
func (t CreatedAt) Info(language string) field.Info {
return field.Info{
Title: "Created At",
Details: "Timestamp of creation of the dataset",
Justify: field.JustifyRight,
}
}
func (t CreatedAt) Int() int {
return int(t)
}
func (t ModifiedAt) Info(language string) field.Info {
return field.Info{
Title: "Modified At",
Details: "Timestamp of last modification of the dataset",
Justify: field.JustifyRight,
}
}
func (t ModifiedAt) Int() int {
return int(t)
}
func (t FieldName) Info(language string) field.Info {
return field.Info{
Title: "Field",
Details: "Name of the CDS View field",
}
}
func (t FieldName) String() string {
return string(t)
}
func (t DataType) Info(language string) field.Info {
return field.Info{
Title: "Type",
Details: "Data type of the CDS View field",
}
}
func (t DataType) String() string {
return string(t)
}
func (t FieldLength) Info(language string) field.Info {
return field.Info{
Title: "Length",
Details: "Length of the CDS View field",
Justify: field.JustifyRight,
}
}
func (t FieldLength) String() string {
return string(t)
}

View File

@ -23,7 +23,7 @@ import (
)
type Keyword struct {
CDSViewTechnicalName string
CDSViewTechnicalName TechnicalName
Keyword string
}

View File

@ -29,15 +29,16 @@ import (
type CDSViewFieldModel struct {
table.CDSViewField
DataTypeTitle string
FieldLengthOut string
DescriptionOut string
FieldNameOut table.FieldName
DataTypeTitle table.DataType
FieldLengthOut table.FieldLength
DescriptionOut table.Description
}
type CDSViewModel struct {
*table.CDSView
StateTitle string
TechnicalNameEncoded string
StateTitle table.State
TechnicalNameEncoded table.TechnicalName
NumberOfFields int
}
@ -53,8 +54,9 @@ func GetCDSViewModelFields(TechnicalName string) (*[]CDSViewFieldModel, error) {
var fieldsModel []CDSViewFieldModel
for _, field := range *fields {
fieldModel.CDSViewField = field
fieldModel.DataTypeTitle = englishCases.String(field.DataType)
fieldModel.FieldLengthOut = strings.TrimLeft(field.FieldLength, "0")
fieldModel.FieldNameOut = field.FieldName
fieldModel.DataTypeTitle = table.DataType(englishCases.String(field.DataType.String()))
fieldModel.FieldLengthOut = table.FieldLength(strings.TrimLeft(field.FieldLength.String(), "0"))
fieldModel.DescriptionOut = field.Description
if fieldModel.DescriptionOut == "" {
fieldModel.DescriptionOut = "-"
@ -65,7 +67,7 @@ func GetCDSViewModelFields(TechnicalName string) (*[]CDSViewFieldModel, error) {
return &fieldsModel, nil
}
func GetCDSViewModel(TechnicalName string) (*CDSViewModel, error) {
func GetCDSViewModel(TechnicalName table.TechnicalName) (*CDSViewModel, error) {
var model CDSViewModel
cdsView, err := table.GetCDSView(TechnicalName)
@ -75,8 +77,8 @@ func GetCDSViewModel(TechnicalName string) (*CDSViewModel, error) {
model.CDSView = cdsView
model.StateTitle = englishCases.String(model.State)
model.TechnicalNameEncoded = strings.Replace(base64.StdEncoding.EncodeToString([]byte(model.TechnicalName)), "=", "", -1)
model.StateTitle = table.State(englishCases.String(model.State.String()))
model.TechnicalNameEncoded = table.TechnicalName(strings.Replace(base64.StdEncoding.EncodeToString([]byte(model.TechnicalName)), "=", "", -1))
model.NumberOfFields, err = table.GetCDSViewNumberOfFields(TechnicalName)
if err != nil {

View File

@ -18,37 +18,23 @@
package router
import (
"api-cds-search/cmd/handler"
"api-cds-search/cmd/search"
"api-cds-search/cmd/ui"
"fmt"
"net/http"
"code.achtarmig.org/pas/ui/context"
"code.achtarmig.org/pas/ui/route"
"github.com/go-chi/chi"
)
func Load() *chi.Mux {
r := chi.NewRouter()
r.Group(func(r chi.Router) {
ui.Load()
r.Get("/", handleRoot)
r.Route("/search", func(r chi.Router) {
r.Get("/", search.HandleSearch)
})
r.Route("/cds", func(r chi.Router) {
r.Get("/field/", handler.GetCDSField)
})
r.Use(context.Middleware)
route.Routes(r)
})
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/search", http.StatusFound)
})
r.Handle("/ui/css/*", http.StripPrefix("/ui/css", http.FileServer(http.Dir("./cmd/ui/css"))))
r.Handle("/ui/svg/*", http.StripPrefix("/ui/svg", http.FileServer(http.Dir("./cmd/ui/svg"))))
return r
}
func handleRoot(w http.ResponseWriter, r *http.Request) {
err := ui.Template.ExecuteTemplate(w, "main", nil)
if err != nil {
fmt.Println(err)
return
}
}

View File

@ -18,8 +18,8 @@
package search
import (
"api-cds-search/cmd/database/table"
"api-cds-search/cmd/model"
"api-cds-search/cmd/ui"
"errors"
"fmt"
"net/http"
@ -33,7 +33,7 @@ import (
)
type fuzzyResult struct {
CDSViewTechnicalName string
CDSViewTechnicalName table.TechnicalName
hits int
perfectHits int
averageDistance float32
@ -54,7 +54,7 @@ var (
ErrNoResults = errors.New("no results")
)
var searchTargets map[string][]string = make(map[string][]string)
var searchTargets map[table.TechnicalName][]string = make(map[table.TechnicalName][]string)
var resultsBuffer map[string]*resultBuffer = make(map[string]*resultBuffer)
func Load() error {
@ -82,8 +82,8 @@ func Load() error {
return nil
}
func GetSearchTerm(r *http.Request) string {
return strings.ToLower(r.URL.Query().Get("q"))
func GetSearchTerm(q string) string {
return strings.ToLower(q)
}
func GetPage(r *http.Request) int {
@ -195,6 +195,48 @@ func BuildBuffer(searchTerm string) error {
return nil
}
func GetPages(buffer *resultBuffer, p int) (int, int) {
var maxPage int
if buffer.hits <= pageStep {
maxPage = 0
} else {
maxPage = (buffer.hits / pageStep)
}
if p+1 > maxPage {
return maxPage, maxPage
} else if p < 0 {
return 0, maxPage
}
return p, maxPage
}
func Search(buffer *resultBuffer, page int, maxPage int) *model.ResultsModel {
buffer.mu.Lock()
defer buffer.mu.Unlock()
resultsModel := model.NewResultsModel()
for i := page * pageStep; i < page*pageStep+pageStep; i++ {
if i > len(buffer.results)-1 {
break
}
result := buffer.results[i]
cdsView, err := model.GetCDSViewModel(result.CDSViewTechnicalName)
if err != nil {
fmt.Println(err)
continue
}
resultsModel.AppendResultsModelViews(cdsView, result.score)
}
resultsModel.CurrentPage = page
resultsModel.MaxPage = maxPage
return resultsModel
}
/*
func HandleSearch(w http.ResponseWriter, r *http.Request) {
searchTerm := GetSearchTerm(r)
@ -251,7 +293,7 @@ func HandleSearch(w http.ResponseWriter, r *http.Request) {
return
}
}
*/
func ClearOldBuffers() {
for key, buffer := range resultsBuffer {
if time.Since(buffer.createdAt) >= time.Minute*10 {

View File

@ -20,6 +20,12 @@
--yellow-5: #e5a50a;
--default-margin: 8px var(--base_margin) 8px var(--base_margin);
--default-outline: transparent solid 2px;
--default-outline-offset: 1px;
--transiton-outline:
outline-offset 0.1s ease-in-out, outline-color 0.1s ease-in-out;
}
@media (prefers-color-scheme: dark) {
@ -313,13 +319,9 @@ button:active {
}
* {
outline-offset: 1px;
outline-style: solid;
outline-width: 2px;
outline-color: transparent;
transition:
outline-offset 0.1s ease-in-out,
outline-color 0.1s ease-in-out;
outline-offset: var(--default-outline-offset);
outline: var(--default-outline);
transition: var(--transiton-outline);
}
*:focus-visible {
@ -412,17 +414,33 @@ button:active {
width: 0%;
height: 0%;
margin: 0%;
visibility: hidden;
border: none;
outline: none;
}
.boxed-list > .expander {
border-bottom-color: transparent !important;
transition: border-bottom 0.15s steps(1, end);
transition:
var(--transiton-outline),
border-bottom 0.15s steps(1, end),
border-bottom-right-radius 0.05s 0.1s,
border-bottom-left-radius 0.05s 0.1s;
}
.boxed-list > .active.expander:focus-within {
outline-offset: -1px;
outline-color: color-mix(in srgb, var(--accent) 50%, transparent);
z-index: 1;
}
.expander:has(> .expander-state:checked) {
border-bottom: 1px solid var(--border) !important;
transition: border-bottom 0.15s steps(1, start);
transition:
var(--transiton-outline),
border-bottom 0.15s steps(1, start),
border-bottom-right-radius 0.05s,
border-bottom-left-radius 0.05s;
transition-delay: 0s;
}
.expander-content {

View File

@ -11,6 +11,7 @@
{{end}} {{block "result" .}}
<label class="active expander" for="{{.TechnicalNameEncoded}}">
<input
tabindex="0"
class="expander-state"
type="checkbox"
id="{{.TechnicalNameEncoded}}"
@ -25,7 +26,7 @@
{{.StateTitle}}
</div>
</label>
<div class="expander-content">
<div class="expander-content" tabindex="none">
<div class="label heading">Field Properties</div>
<div class="container-center">
{{template "fields-placeholder" dict "Result" .}}

78
cmd/view/cdsDetails.go Normal file
View File

@ -0,0 +1,78 @@
package view
import (
"api-cds-search/cmd/model"
"fmt"
"net/http"
"code.achtarmig.org/pas/ui/element"
"code.achtarmig.org/pas/ui/element/container"
"code.achtarmig.org/pas/ui/element/input"
"code.achtarmig.org/pas/ui/element/option"
"code.achtarmig.org/pas/ui/element/table"
"code.achtarmig.org/pas/ui/element/view"
"code.achtarmig.org/pas/ui/route"
)
func cdsDetails() {
view.New("CDSDetails", func(p *view.Element) {
route.Register("/cds", p)
p.Title = "CDSDetails"
p.OnRequest = onRequestDetails
container.New(p, "Details", func(p *container.Element) {
p.Justify = option.JustifyCenter
input.New(p, "q", input.TypeText, func(p *input.Element) {
p.Placeholder = "CDSViewTechnicalName"
p.Shape = option.ShapeRound
p.SetHTMX(element.HTMX{
Method: http.MethodGet,
Target: "#DetailsTable",
URL: "/cds",
PushURL: true,
})
})
})
container.New(p, "", func(p *container.Element) {
p.Justify = option.JustifyCenter
table.New(p, "DetailsTable", func(p *table.Element) {
p.MinWidth = 20
p.MaxWidth = 32
})
})
})
}
func onRequestDetails(e *view.Element, w http.ResponseWriter, r *http.Request) view.ProcessElements {
cds, _ := e.GetElement("q").(*input.Element).GetDataText()
e.Title = fmt.Sprintf("CDSDetails - %s", cds)
fields, err := model.GetCDSViewModelFields(cds)
if err != nil {
fmt.Println(err)
return view.ProcessElements{}
}
table := e.GetElement("DetailsTable").(*table.Element)
table.SetData(*fields)
for _, header := range table.Data.Header {
switch header.Name {
case "FieldNameOut":
header.Option.Font = option.FontMonospaced
case "DataTypeTitle":
case "FieldLengthOut":
header.Option.Font = option.FontMonospaced
case "DescriptionOut":
default:
header.Option.Hidden = true
}
}
table.Data.SetFieldOrder("FieldNameOut", "DescriptionOut", "DataTypeTitle", "FieldLengthOut")
return view.ProcessElements{
Partial: []element.ElementInterface{e.GetElement("DetailsTable")},
}
}

6
cmd/view/load.go Normal file
View File

@ -0,0 +1,6 @@
package view
func Load() {
searchView()
cdsDetails()
}

50
cmd/view/results.go Normal file
View File

@ -0,0 +1,50 @@
package view
import (
"api-cds-search/cmd/model"
"errors"
"net/http"
"net/url"
"code.achtarmig.org/pas/ui/element"
"code.achtarmig.org/pas/ui/element/boxedlist"
"code.achtarmig.org/pas/ui/element/boxedlist/expander"
"code.achtarmig.org/pas/ui/element/option"
"code.achtarmig.org/pas/ui/element/placeholder"
"code.achtarmig.org/pas/ui/element/view"
)
func results(v *view.Element, m *model.ResultsModel) element.ElementInterface {
cont := v.GetElement("SearchResultsContainer")
cont.DeleteAllChildren()
bl, _ := boxedlist.New(cont, "", func(p *boxedlist.Element) {
p.MaxWidth = 42
p.MinWidth = 20
for _, result := range m.Views {
expander.New(p, func(p *expander.Element) {
p.Title = result.DisplayName.String()
p.Subtitle = result.TechnicalName.String()
p.PlaceholderHeight = 21 * result.NumberOfFields
p.CallbackLazyLoad = func(e *expander.Element, w http.ResponseWriter, r *http.Request) error {
http.Redirect(w, r, "/cds?q="+url.QueryEscape(result.TechnicalName.String()), http.StatusSeeOther)
return errors.New("redirect")
}
})
}
})
return bl
}
func noResults(v *view.Element) element.ElementInterface {
cont := v.GetElement("SearchResultsContainer")
cont.DeleteAllChildren()
pl, _ := placeholder.New(cont, "", func(p *placeholder.Element) {
p.Icon = option.IconLoupe
p.Title = "No Results"
p.Subtitle = "Try refining your search term"
})
return pl
}

152
cmd/view/search.go Normal file
View File

@ -0,0 +1,152 @@
package view
import (
"api-cds-search/cmd/search"
"net/http"
"code.achtarmig.org/pas/ui/element"
"code.achtarmig.org/pas/ui/element/button"
"code.achtarmig.org/pas/ui/element/container"
"code.achtarmig.org/pas/ui/element/form"
"code.achtarmig.org/pas/ui/element/input"
"code.achtarmig.org/pas/ui/element/option"
"code.achtarmig.org/pas/ui/element/placeholder"
"code.achtarmig.org/pas/ui/element/view"
"code.achtarmig.org/pas/ui/route"
)
func noSearch(v *view.Element) element.ElementInterface {
cont := v.GetElement("SearchResultsContainer")
cont.DeleteAllChildren()
pl, _ := placeholder.New(cont, "", func(p *placeholder.Element) {
p.Icon = option.IconLoupe
p.Title = "Search CDS-Views"
p.Subtitle = "Find CDS-Views from the Business Accelerator Hub"
})
return pl
}
func searchView() {
view.New("Search", func(p *view.Element) {
route.Register("/search", p)
p.Title = "CDS-Search"
p.OnRequest = func(v *view.Element, w http.ResponseWriter, r *http.Request) view.ProcessElements {
inputQuery := v.GetElement("q").(*input.Element)
inputQueryValue, _ := v.GetElement("q").(*input.Element).GetDataText()
searchTerm := search.GetSearchTerm(inputQueryValue)
if inputQueryValue == "" {
noSearch(v)
}
inputPage := v.GetElement("p").(*input.Element)
inputMaxPage := v.GetElement("MaxPage").(*input.Element)
currentPage, _ := inputPage.GetDataNumber()
if inputQuery.GetDataChanged() && inputQueryValue != "" {
buf, err := search.GetBuffer(searchTerm)
if err != nil {
search.BuildBuffer(searchTerm)
buf, err = search.GetBuffer(searchTerm)
}
if err != nil {
noResults(v)
} else {
currentPage, maxPage := search.GetPages(buf, currentPage)
m := search.Search(buf, currentPage, maxPage)
inputPage.Max = m.MaxPage
inputMaxPage.Min = m.MaxPage
inputMaxPage.Max = m.MaxPage
inputMaxPage.SetData(m.MaxPage)
results(v, m)
}
}
return view.ProcessElements{
Partial: []element.ElementInterface{v.GetElement("SearchResultsContainer")},
OOBUpdate: []element.ElementInterface{inputPage, inputMaxPage},
}
}
container.New(p, "MainContainer", func(p *container.Element) {
p.Justify = option.JustifyCenter
form.New(p, "SearchForm", func(p *form.Element) {
p.SetHTMX(element.HTMX{
Method: http.MethodGet,
Target: "#SearchResultsContainer>*",
Swap: "outerHTML",
URL: "/search",
PushURL: true,
Params: "q, p",
})
container.New(p, "SearchFormLinked", func(p *container.Element) {
p.Justify = option.JustifyCenter
p.LinkedHorizontal = true
input.New(p, "q", input.TypeText, func(p *input.Element) {
p.Placeholder = "Search here"
p.Shape = option.ShapeRound
p.MinWidth = 10
p.MaxWidth = 36
})
button.New(p, "SearchButton", func(p *button.Element) {
p.Label = "Search"
p.DisplayStyle = option.DisplayStyleSuggestedAction
p.Shape = option.ShapeRound
p.MaxWidth = 6
})
})
})
})
container.New(p, "CenterPager", func(p *container.Element) {
p.Justify = option.JustifyCenter
container.New(p, "Pager", func(p *container.Element) {
p.MaxWidth = 42
p.MinWidth = 10
p.Justify = option.JustifyRight
p.LinkedHorizontal = true
input.New(p, "p", input.TypeNumber, func(p *input.Element) {
p.Shape = option.ShapeRound
p.SetMin = true
p.Min = 0
p.SetMax = true
p.Max = 0
p.MinWidth = 4
p.SetHTMX(element.HTMX{
Method: http.MethodGet,
Include: "[name='q'], [name='p']",
Target: "#SearchResultsContainer>*",
URL: "/search",
Swap: "outerHTML",
PushURL: true,
})
})
input.New(p, "MaxPage", input.TypeNumber, func(p *input.Element) {
p.Disabled = true
p.Shape = option.ShapeRound
p.MinWidth = 4
p.SetMin = true
p.SetMax = true
})
})
})
container.New(p, "SearchResultsContainer", func(p *container.Element) {
p.Justify = option.JustifyCenter
})
})
}

4
go.mod
View File

@ -3,6 +3,7 @@ module api-cds-search
go 1.23.7
require (
code.achtarmig.org/pas/ui v0.0.0-20250517190325-787754158160
github.com/glebarez/go-sqlite v1.22.0
github.com/go-chi/chi v1.5.5
github.com/lithammer/fuzzysearch v1.1.8
@ -10,8 +11,9 @@ require (
)
require (
github.com/brunoga/deep v1.2.4 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
golang.org/x/sys v0.15.0 // indirect

216
go.sum
View File

@ -1,3 +1,215 @@
code.achtarmig.org/pas/ui v0.0.0-20250423130241-77cad1ae9e1d h1:uGvywYhWyOpo3AStulDAEt/eOVFKbj5wIb/DpdjTusM=
code.achtarmig.org/pas/ui v0.0.0-20250423130241-77cad1ae9e1d/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430113606-b06d1c915f57 h1:oN6mf0Y+buCL24zHHSYDnZG6h37WLuU47XQ8e6Zrfv8=
code.achtarmig.org/pas/ui v0.0.0-20250430113606-b06d1c915f57/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430122418-e994dcdf428e h1:sp4HES6StGtWPXGCUtjmJc00HXQqifwgfJ3bpCBkzt0=
code.achtarmig.org/pas/ui v0.0.0-20250430122418-e994dcdf428e/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430122527-723745a86856 h1:qhZbwO8E8lwnabUBy8I9NapW4gi74wXcuhdkOnPiQSo=
code.achtarmig.org/pas/ui v0.0.0-20250430122527-723745a86856/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430122621-716d6f1f7ca5 h1:hyxC82CZH+OofqLaDgkpPg0e/OrJ3sKiLAKGec2vwus=
code.achtarmig.org/pas/ui v0.0.0-20250430122621-716d6f1f7ca5/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430122747-0f082828f3d9 h1:gYoDsaZ4a4ZnX8KzNC/LNshLmkeTu+DZs2gQqp1vysM=
code.achtarmig.org/pas/ui v0.0.0-20250430122747-0f082828f3d9/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430125057-3c3d7f686e6d h1:mx/ofzGdwbmRgNCDhIHvDMtT8owh6LvVIAdEu2pp+2U=
code.achtarmig.org/pas/ui v0.0.0-20250430125057-3c3d7f686e6d/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430132955-f3328dc3d2bd h1:LyWYfQWNf1FRf7AEKSTcpuQcnpwpvIS6oOz828Lbq70=
code.achtarmig.org/pas/ui v0.0.0-20250430132955-f3328dc3d2bd/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430133200-55d5145d392f h1:BwatQO1LJod6vPXUqcR7IlGKVE4z+0MgVEcdoPdsSgE=
code.achtarmig.org/pas/ui v0.0.0-20250430133200-55d5145d392f/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430140629-19d614a3a17a h1:egpbXwz7V1NqlkUyKMsIKQoJUz30hgabhGCWo6MtGQI=
code.achtarmig.org/pas/ui v0.0.0-20250430140629-19d614a3a17a/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430183457-ddd4de8d7463 h1:iHoMtL048RLx4rggB5fxl1BzKLDJcjgYPK7nKe4cX8k=
code.achtarmig.org/pas/ui v0.0.0-20250430183457-ddd4de8d7463/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430184356-704e6170c8f9 h1:TEZklUc7HXxZDu9N1mBI0TUUxqOD6QDPaXv5Di2L4dM=
code.achtarmig.org/pas/ui v0.0.0-20250430184356-704e6170c8f9/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250430185113-67713d8f187a h1:k8e6d/YHlHWi0OHG5LRMxq84ZfIs6ZYD6rA0fj8hxz0=
code.achtarmig.org/pas/ui v0.0.0-20250430185113-67713d8f187a/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503122000-14ef7d4aa1fe h1:KYAD8d054+NW/6TFpbCsi1aZhxv1GBZMVgK7bUBjWiE=
code.achtarmig.org/pas/ui v0.0.0-20250503122000-14ef7d4aa1fe/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503122350-ca09a49145e1 h1:I8sMNf4RN9xrChdrHQNQR2g6VsCab/+kmvwM4Qcwgqc=
code.achtarmig.org/pas/ui v0.0.0-20250503122350-ca09a49145e1/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503123128-ef12a6cf86a7 h1:7nC74Z99klsKLMvhAfb2aXrgrYJ7nXUEUVltx3I1LSw=
code.achtarmig.org/pas/ui v0.0.0-20250503123128-ef12a6cf86a7/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503174327-574f87c22162 h1:8HsKiui5rFEuxcbYv0cprgzqhqIcuj75lyqiAv5jLCg=
code.achtarmig.org/pas/ui v0.0.0-20250503174327-574f87c22162/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503175603-cd58c6b71bae h1:lCYhD2ZjKUbDrUKy/K9G+ggZN1UPtgyITag5X2PyCYQ=
code.achtarmig.org/pas/ui v0.0.0-20250503175603-cd58c6b71bae/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503175854-ac3566f449e3 h1:4GiyS+c9z2oaM+5Vp7xOZQMJ0LoZ7dwES04TYz/7FrE=
code.achtarmig.org/pas/ui v0.0.0-20250503175854-ac3566f449e3/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503200130-5cfbd172319e h1:nAa/Z9zPpqOuqD8a88nXmDJutFvRyvL+DrxXkrYecC4=
code.achtarmig.org/pas/ui v0.0.0-20250503200130-5cfbd172319e/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503200638-86b83511e1ac h1:oCRNrA7iyknOh5IdKSowJHvxrFVsfLyxXFyPKuoZSfY=
code.achtarmig.org/pas/ui v0.0.0-20250503200638-86b83511e1ac/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503200916-89b2e3372d44 h1:u5g8Uue4hwHvC4mf88KR6UOP2MlOJ20ec+r2nL3larQ=
code.achtarmig.org/pas/ui v0.0.0-20250503200916-89b2e3372d44/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503202213-fe34a6626602 h1:cM7oU11Hyfguve2IisQ+njmLlShJ2/TMlONPn8mU21w=
code.achtarmig.org/pas/ui v0.0.0-20250503202213-fe34a6626602/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503202706-191f0ba06ef0 h1:E4KdkkQ7+/JaC8QVERSZF9IgUqrPFLsroLfkw2eCHX8=
code.achtarmig.org/pas/ui v0.0.0-20250503202706-191f0ba06ef0/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250503202925-88f242608f55 h1:9f7RX0BLAt6TdaZyzi6yJBSoqGpbeKKBKf9GCWerRts=
code.achtarmig.org/pas/ui v0.0.0-20250503202925-88f242608f55/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504114726-3bde89f2f2fb h1:SvbyZGE4q4fL+KuCxhm3QNvnTKiT1rr7lXvWNZIDHz8=
code.achtarmig.org/pas/ui v0.0.0-20250504114726-3bde89f2f2fb/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504115809-c8bb4889c67f h1:78c5k3ffa9jC5I1euYdu01csXMST+o0+bmXqALhGzeY=
code.achtarmig.org/pas/ui v0.0.0-20250504115809-c8bb4889c67f/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504115940-3e79e98097c0 h1:pl+3/Ru4KlRGMvGijDqsXN9DCc5Nuus/wr1piEECIck=
code.achtarmig.org/pas/ui v0.0.0-20250504115940-3e79e98097c0/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504120250-a9712dd18679 h1:uz95zU0tOZbVNa38n7bwjniHub4j7H53kWRmdPsC+1o=
code.achtarmig.org/pas/ui v0.0.0-20250504120250-a9712dd18679/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504121523-7fd26ddcd810 h1:Cu0oEI3/BLGCGd4gr+Ha/xPW6CE0VRwqYatTYlRijOk=
code.achtarmig.org/pas/ui v0.0.0-20250504121523-7fd26ddcd810/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504154112-b35362d1de7a h1:7T/1ys9aL2tT7/1MWFlmO3t+EswMUqQ4G/BrrTAS4mE=
code.achtarmig.org/pas/ui v0.0.0-20250504154112-b35362d1de7a/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504154732-a2c1862dbe42 h1:kGPimrMs0QMpOmllkdFg1in6yMOcbmBczr1zJdvhExg=
code.achtarmig.org/pas/ui v0.0.0-20250504154732-a2c1862dbe42/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504155328-7d607cc2b350 h1:CwHrMnI6Q+OZGjxNG4K8pA6mDMCF3BEVm90LnHe255c=
code.achtarmig.org/pas/ui v0.0.0-20250504155328-7d607cc2b350/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504155925-937597c45faf h1:CkEESNCQbBZr+nm6mP9lC3uO3IbB6I7fwcpWI2fD4ns=
code.achtarmig.org/pas/ui v0.0.0-20250504155925-937597c45faf/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504160422-82720c4a582f h1:aPwdsIpaR4zCJjXXr9TMCs+AAUfJR2mx/LQFj1H2rUg=
code.achtarmig.org/pas/ui v0.0.0-20250504160422-82720c4a582f/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504160947-5abddd47fc06 h1:+szpi3rOl/60a1c8rPDqA9vWkpc4S7+83VMHNdIjyqU=
code.achtarmig.org/pas/ui v0.0.0-20250504160947-5abddd47fc06/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504161605-3e0c61e0de92 h1:l4mhR9E1Ol7u+38u+OxsLkWq6EY+vslaJZ+gPVofVGc=
code.achtarmig.org/pas/ui v0.0.0-20250504161605-3e0c61e0de92/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504162027-fbb39ad09295 h1:cUyyCcpC+451iGbZWCgp6Ka/BZt6dgOBJjSsAnwUfgg=
code.achtarmig.org/pas/ui v0.0.0-20250504162027-fbb39ad09295/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250504163359-c5823941f5de h1:QtXmasvjhZJhM9OMzLrzg2t5KnleQJDlryU5nV4SNwI=
code.achtarmig.org/pas/ui v0.0.0-20250504163359-c5823941f5de/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510123925-70468693fff8 h1:BNXtJ9igWRUvLHEnKh5aPqkLl3fc/Ac8DTxKuv0yPHc=
code.achtarmig.org/pas/ui v0.0.0-20250510123925-70468693fff8/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510125712-789b656761c6 h1:L1eIHKdnlpUDsNh7jMPA6xoOm/ImXokeDqoYvdk/3vQ=
code.achtarmig.org/pas/ui v0.0.0-20250510125712-789b656761c6/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510134444-ef0b491dc1fb h1:ZN+XIPVRf89U62M/fE0rFMklqw5Ly6tLk57fTpsp4as=
code.achtarmig.org/pas/ui v0.0.0-20250510134444-ef0b491dc1fb/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510134646-e5a55632c22d h1:nJGLQOFwGRkERiN9x4UMG2fyb1DmdLZrEjGIAe1ND7U=
code.achtarmig.org/pas/ui v0.0.0-20250510134646-e5a55632c22d/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510135554-2605d777003e h1:bKkN2NNnzCtfcLvCMvtpjW0yxwt9531wCPnykSUhZys=
code.achtarmig.org/pas/ui v0.0.0-20250510135554-2605d777003e/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510184256-35a0aab89b29 h1:MCHb7zoyC7RDzqoid99cRcFEOvgyPz++pNlc7zrTuto=
code.achtarmig.org/pas/ui v0.0.0-20250510184256-35a0aab89b29/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510184612-1bcb7d9999a8 h1:W3l3XlITKMWocvH1NvkTT6qiDsjeYWVVZ7Z0s12EsGM=
code.achtarmig.org/pas/ui v0.0.0-20250510184612-1bcb7d9999a8/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510184917-9351a88fc4a4 h1:kE+KISIECBxpAKl160aJrwwB/VevHPY2f4o+kd46n8o=
code.achtarmig.org/pas/ui v0.0.0-20250510184917-9351a88fc4a4/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510185314-cd715ae2581d h1:AE8Nm2o/rzv1gA+x4/tQg1Dql5yXB+rsx7DBhctFhsU=
code.achtarmig.org/pas/ui v0.0.0-20250510185314-cd715ae2581d/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510185935-a3e4c3080809 h1:SorDBnZy8K858ZlyqjnDKQ0A2/sokXHWTEeEwYP/Y6U=
code.achtarmig.org/pas/ui v0.0.0-20250510185935-a3e4c3080809/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510190018-7925a85133bd h1:WLV/G50Eq2hmn9NKORB1IlGTCpemT7cALCmAXCjpc6Y=
code.achtarmig.org/pas/ui v0.0.0-20250510190018-7925a85133bd/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510191623-95ee9bd6e555 h1:ib8e/1Som5oJ2xN2JFoZ4YYMPmpb2ubOxNQgnRcIRAo=
code.achtarmig.org/pas/ui v0.0.0-20250510191623-95ee9bd6e555/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510191713-c2bb3765e103 h1:YNP0RwIwMFUcva48HYGMDCh4kMPRjc4Ro5r/KzNwP/0=
code.achtarmig.org/pas/ui v0.0.0-20250510191713-c2bb3765e103/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510192244-e26d63f0c10d h1:ISxGDw+9SV1EXdW8wV/GaBbReIPS/GlmVo/Hd27cdVI=
code.achtarmig.org/pas/ui v0.0.0-20250510192244-e26d63f0c10d/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510194823-67183feea29d h1:WSY4zHK4c3l9TctKstaOwW9tI6hDlgK9RrxwOAswStg=
code.achtarmig.org/pas/ui v0.0.0-20250510194823-67183feea29d/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510195045-1ebf277e7b80 h1:AhVQdQPzelUyujK8gHFzdBbyXmxKercHQMGaZd1o9GY=
code.achtarmig.org/pas/ui v0.0.0-20250510195045-1ebf277e7b80/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510195147-dd8180018555 h1:sERMsf3AvPOoV81S6tVi71RY2uARjuOdEM735V67T6k=
code.achtarmig.org/pas/ui v0.0.0-20250510195147-dd8180018555/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510195254-844d8b86cd65 h1:9sulVyGp0gbBqzYGyxLsfi0ia5VKeaoTuqoC6uHrx2Y=
code.achtarmig.org/pas/ui v0.0.0-20250510195254-844d8b86cd65/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510195449-a4edaa18b12b h1:Lw2ODGz5WeSsuSElyB+emJexL3OUFAIAKgLSVpTDfXY=
code.achtarmig.org/pas/ui v0.0.0-20250510195449-a4edaa18b12b/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250510200645-d30582aba20f h1:w6hwfaooh0R0iFAm4zBkvEYAY9hU+UfUfqiQ02HAecA=
code.achtarmig.org/pas/ui v0.0.0-20250510200645-d30582aba20f/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511101857-c9522c929e52 h1:W1lARZUamuhbTg9ijdvlDItpoRTa3zFIOPKrSxeqqcU=
code.achtarmig.org/pas/ui v0.0.0-20250511101857-c9522c929e52/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511102211-fbb465629817 h1:I95XjYlW95GPlhBoVvyEYub64NRL+tXoTRXOOW1DWS8=
code.achtarmig.org/pas/ui v0.0.0-20250511102211-fbb465629817/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511104020-73c99e4079db h1:3YngqYBJsfj3Lq91y/70vx6lVddtaFbNKhfFuNeS6f4=
code.achtarmig.org/pas/ui v0.0.0-20250511104020-73c99e4079db/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511104107-3ce0ae192e71 h1:+PYrXO0d0yll+YzrGapWUdHWL5Rz3zHupjtb8n240kE=
code.achtarmig.org/pas/ui v0.0.0-20250511104107-3ce0ae192e71/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511104937-72d3894969da h1:/lnKZuj9ejYlvsCkuwTh+4DFtyNoVPYBxzrvnhktgMQ=
code.achtarmig.org/pas/ui v0.0.0-20250511104937-72d3894969da/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511105443-5c1f838d4a0f h1:QDn3alVreFX0vcjQRb2+wwdPJBAIBo+i3hKJTyjBq6o=
code.achtarmig.org/pas/ui v0.0.0-20250511105443-5c1f838d4a0f/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511151203-13674fd646aa h1:/i5zED2WIpbFet891Bo06cgnz2HWXN5Zm3ZSj1Hf90c=
code.achtarmig.org/pas/ui v0.0.0-20250511151203-13674fd646aa/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511153040-e11277d114d5 h1:ynqYEdYJp0o/+U6tMAIiWBG6XxwR1lNRuYCiMOp25HY=
code.achtarmig.org/pas/ui v0.0.0-20250511153040-e11277d114d5/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511153246-1bbaa9a9c064 h1:vQDWG+vKlZvkwRqKpNXjDzwplJ9+7BiKGqpO79NL89A=
code.achtarmig.org/pas/ui v0.0.0-20250511153246-1bbaa9a9c064/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511154145-4fd1fd0ddc07 h1:wRG5adpk4tkQTd7XVwFpDRT5YIMcwwlAyE3noERdQ3I=
code.achtarmig.org/pas/ui v0.0.0-20250511154145-4fd1fd0ddc07/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511154410-2b973a9a73be h1:eBv/xQjbJSuZn2P+tSHF0uyaHytiNfuAMO+jTObSNyA=
code.achtarmig.org/pas/ui v0.0.0-20250511154410-2b973a9a73be/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511161328-dd31f33492f4 h1:PptkC6SxYcHgjhFpCuAhxXzzSBI8vStJgrxHKq8uDDw=
code.achtarmig.org/pas/ui v0.0.0-20250511161328-dd31f33492f4/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511161424-eefb1ef0cc64 h1:L8OXWZJMcXfLczw7K8L0aRw/+Fc1Cni/e8IN6+8KTb8=
code.achtarmig.org/pas/ui v0.0.0-20250511161424-eefb1ef0cc64/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511162939-f3eb6979ea6a h1:5Vi25SRFYolW33Z5kuR24WuGTlrYX+3kNz8sN2o6/XE=
code.achtarmig.org/pas/ui v0.0.0-20250511162939-f3eb6979ea6a/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511163155-3a5297d15113 h1:DfPcOFyP8Cb2OZdIZ0Iut5MaYCQ4uAbCEXR6ARJQpfY=
code.achtarmig.org/pas/ui v0.0.0-20250511163155-3a5297d15113/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511164038-2cd675ad25b0 h1:z3Iv3TZ2tMwz7u8FfXJy1IOVSDAKlNyEcznTkDmktl0=
code.achtarmig.org/pas/ui v0.0.0-20250511164038-2cd675ad25b0/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250511170323-e2f03337de02 h1:tlzr0yK00spUfOvOGKW+rrcJkwEzoVQ38ITSJ7Bls9Q=
code.achtarmig.org/pas/ui v0.0.0-20250511170323-e2f03337de02/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250512111133-6e9e1a71e19a h1:EH516+SqXOQRObBuE7eF0dPmmWM3y62nt3BY2YWvHEU=
code.achtarmig.org/pas/ui v0.0.0-20250512111133-6e9e1a71e19a/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250513102739-4e7567276b04 h1:2Z6/NpVxFMQXx6XSUQzD0oXjtmXqAmgulmk8A4QnVRQ=
code.achtarmig.org/pas/ui v0.0.0-20250513102739-4e7567276b04/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250513140013-21a745c1c568 h1:mpBvvdzCNFvSIaQZsZqrKa1Hsv7wPS8NKxYyYRzMQOk=
code.achtarmig.org/pas/ui v0.0.0-20250513140013-21a745c1c568/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250513142047-00f7ddea00a7 h1:xLyy3vImxIekNtRDUKxCKY8JznlLU35tFWAYYCM2NeY=
code.achtarmig.org/pas/ui v0.0.0-20250513142047-00f7ddea00a7/go.mod h1:2stpDl/L6Zgd4a/r+fDMsMMuF59aKQbAIeByX1UqiQo=
code.achtarmig.org/pas/ui v0.0.0-20250513143630-9e4d6dc54a7b h1:nwMTMHUGJ8lR7Zfe2EWV5ejurX7ekPIdp9CY8XRVBvI=
code.achtarmig.org/pas/ui v0.0.0-20250513143630-9e4d6dc54a7b/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250513143807-63cda742ff1d h1:ysS1jekxniyT2X+6Xs1d7ACyf6zp2P6RvGKQkBgYtcQ=
code.achtarmig.org/pas/ui v0.0.0-20250513143807-63cda742ff1d/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250513144145-668a268206b5 h1:8kp9Eni8pPzIcrSEscPvv80Vts6g6cQveYn8AbCjua0=
code.achtarmig.org/pas/ui v0.0.0-20250513144145-668a268206b5/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250513144308-65cccdc5bbfe h1:sCD7tNfcLIIWbdzcgP61gl4KYB66XiXZUuC4jyFSfRA=
code.achtarmig.org/pas/ui v0.0.0-20250513144308-65cccdc5bbfe/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250513144523-6606ec845bba h1:8VTJw2g4KGPNB0JwjqK6dD4A3DhmkciHtMbJetnIW2k=
code.achtarmig.org/pas/ui v0.0.0-20250513144523-6606ec845bba/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514120506-952c80d0f738 h1:wFboIbcnfFQH6/Qbkj+UHnllCO9QYo/lwd2BKj6AJyc=
code.achtarmig.org/pas/ui v0.0.0-20250514120506-952c80d0f738/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514122252-e4f1d325fae8 h1:pj9Q/9f+IEDPGwOMFdzbXlfwyHXYq79tGg5tPVMojkg=
code.achtarmig.org/pas/ui v0.0.0-20250514122252-e4f1d325fae8/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514122424-5e3d340ca863 h1:+A/EogWV8HgLVlIwD1Kg8GgMU5tGrPJU1Vxq4vyObQw=
code.achtarmig.org/pas/ui v0.0.0-20250514122424-5e3d340ca863/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514123644-7dcce853ff26 h1:ee7R2Ju5TprjvWRRocQBgRX9kaVViaQQPKUNXnkyAk8=
code.achtarmig.org/pas/ui v0.0.0-20250514123644-7dcce853ff26/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514124305-a96fa2289ecb h1:LJppDfp+snlTT0GvpbI/56+pLFEz3pz/VSwPn03MLZg=
code.achtarmig.org/pas/ui v0.0.0-20250514124305-a96fa2289ecb/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514125154-c6cdc00606d3 h1:t9yVH033nfQb0rL/WYWcYZv9/uU5bIDzSijmIAmfmYQ=
code.achtarmig.org/pas/ui v0.0.0-20250514125154-c6cdc00606d3/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514130353-23c3e2c1ba34 h1:NzbVq44g+3kQ+ZW+NQ2q4zZWCxfg8UeG1niB7lxZTGk=
code.achtarmig.org/pas/ui v0.0.0-20250514130353-23c3e2c1ba34/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514130600-a6eda5b72022 h1:YAFvQtdvALH2QNuoW3br6o5/2Us/jlYs2cOGDreGx8M=
code.achtarmig.org/pas/ui v0.0.0-20250514130600-a6eda5b72022/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514131843-bc2592f71ec6 h1:UkKJX5xyAq/6uc5rjlqWHa1p7OjGmBvyoMcwa+JrCgg=
code.achtarmig.org/pas/ui v0.0.0-20250514131843-bc2592f71ec6/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250514132050-3b11d4bdb25e h1:7cYgy4IYq1ACBef2wNz+k8dZgcPk+WWtiYvE8531S6Y=
code.achtarmig.org/pas/ui v0.0.0-20250514132050-3b11d4bdb25e/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250515103640-ddb21adf0d29 h1:2vUjuMTAVs/8pmGQVOYpybDY4LLQBePmczbwZHfkGYw=
code.achtarmig.org/pas/ui v0.0.0-20250515103640-ddb21adf0d29/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250515105216-53b01f136224 h1:PWWH4D+yaBCitO24B4gKMYXV7QTlP78UdYq8Ji59hto=
code.achtarmig.org/pas/ui v0.0.0-20250515105216-53b01f136224/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250515105337-c5a46ed2a62d h1:tolI3Hxb8enAyKaBcZWDIUCTtEZBrTjWDun6qGqRRpM=
code.achtarmig.org/pas/ui v0.0.0-20250515105337-c5a46ed2a62d/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250515105849-6f9f30e64064 h1:H78/VvWx090mQX7dKEdGzL90vvTzUwOgYmDoQKh7yvA=
code.achtarmig.org/pas/ui v0.0.0-20250515105849-6f9f30e64064/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250516145820-afcad1b404f9 h1:lOYW70hhGlVXYV0w3soR3K+erlp+O7br+6zhhGDr9JE=
code.achtarmig.org/pas/ui v0.0.0-20250516145820-afcad1b404f9/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250516150330-0d4a4f187e99 h1:SQQUM1ZsQXStnzkDgC869AmUHvuoc10rLV0a0UWQuxY=
code.achtarmig.org/pas/ui v0.0.0-20250516150330-0d4a4f187e99/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250516150408-103956f4ad18 h1:UlnzGHkmabY6BRj7mWDq4aIQdu9kzu62aNLULB2Ndzo=
code.achtarmig.org/pas/ui v0.0.0-20250516150408-103956f4ad18/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250516183309-055656de4f20 h1:+Ilsu1StGBv3Jk4w6g13XSH1uNdAqiKOcNgZCfyyj/E=
code.achtarmig.org/pas/ui v0.0.0-20250516183309-055656de4f20/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250516183430-2a5f949482b3 h1:K0RlHqhiWd3yr3RPYUhhVaQLJLIMjwtIQ7SwDE1zkuM=
code.achtarmig.org/pas/ui v0.0.0-20250516183430-2a5f949482b3/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
code.achtarmig.org/pas/ui v0.0.0-20250517190325-787754158160 h1:nhr5BUMdLRJrj/DnO4LZdsPwgIz3vYvaf08LdND7Eu8=
code.achtarmig.org/pas/ui v0.0.0-20250517190325-787754158160/go.mod h1:4SnZejrC0bLr2Kq1yt4TBis8lo2hHA8K0m/0B2l6Uo0=
github.com/brunoga/deep v1.2.4 h1:Aj9E9oUbE+ccbyh35VC/NHlzzjfIVU69BXu2mt2LmL8=
github.com/brunoga/deep v1.2.4/go.mod h1:GDV6dnXqn80ezsLSZ5Wlv1PdKAWAO4L5PnKYtv2dgaI=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
@ -6,8 +218,8 @@ github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=

10
main.go
View File

@ -5,18 +5,28 @@ import (
"api-cds-search/cmd/router"
"api-cds-search/cmd/search"
"api-cds-search/cmd/ui"
"api-cds-search/cmd/view"
"fmt"
"net/http"
"code.achtarmig.org/pas/ui/initialize"
"code.achtarmig.org/pas/ui/log"
)
func main() {
initialize.Init()
database.Load()
err := search.Load()
if err != nil {
panic(err)
}
ui.Load()
view.Load()
log.SetPrintError(true)
r := router.Load()
fmt.Println("Listening on :8080")