diff --git a/cmd/database/table/cdsViewField.go b/cmd/database/table/cdsViewField.go index 87ec0f2..711b23e 100644 --- a/cmd/database/table/cdsViewField.go +++ b/cmd/database/table/cdsViewField.go @@ -50,6 +50,25 @@ func GetCDSViewFields(CDSViewTechnicalName string) (*[]CDSViewField, error) { return &fields, nil } +//go:embed sql/query_cds_view_number_of_fields.sql +var query_cds_view_number_of_fields string + +func GetCDSViewNumberOfFields(CDSViewTechnicalName string) (int, error) { + rows, err := database.DB.Query(query_cds_view_number_of_fields, CDSViewTechnicalName) + if err != nil { + return 0, err + } + + var numberOfFields int = 0 + for rows.Next() { + err := rows.Scan(&numberOfFields) + if err != nil { + return 0, err + } + } + return numberOfFields, nil +} + //go:embed sql/insert_or_replace_cds_view_field.sql var insert_or_replace_cds_view_field string diff --git a/cmd/database/table/sql/query_all_keywords.sql b/cmd/database/table/sql/query_all_keywords.sql index e0535f3..9a10fc3 100644 --- a/cmd/database/table/sql/query_all_keywords.sql +++ b/cmd/database/table/sql/query_all_keywords.sql @@ -1,16 +1,16 @@ -select +select distinct CDSViewTechnicalName as CDSViewTechnicalName, lower(FieldName) as keyword from CDSViewField UNION -select +select distinct CDSViewTechnicalName as CDSViewTechnicalName, lower(Description) as keyword from CDSViewField UNION -select +select distinct TechnicalName as CDSViewTechnicalName, lower(TechnicalName) as keyword from @@ -22,7 +22,7 @@ select from CDSView UNION -select +select distinct TechnicalName as CDSViewTechnicalName, lower(DisplayName) as keyword from diff --git a/cmd/database/table/sql/query_cds_view_number_of_fields.sql b/cmd/database/table/sql/query_cds_view_number_of_fields.sql new file mode 100644 index 0000000..77f778a --- /dev/null +++ b/cmd/database/table/sql/query_cds_view_number_of_fields.sql @@ -0,0 +1,6 @@ +SELECT + count(*) as NumberOfFields +FROM + CDSViewField +WHERE + CDSViewTechnicalName = ? diff --git a/cmd/handler/cds.go b/cmd/handler/cds.go new file mode 100644 index 0000000..1edfd9c --- /dev/null +++ b/cmd/handler/cds.go @@ -0,0 +1,23 @@ +package handler + +import ( + "api-cds-search/cmd/model" + "api-cds-search/cmd/ui" + "fmt" + "net/http" +) + +func GetCDSField(w http.ResponseWriter, r *http.Request) { + CDSViewTechnicalName := r.URL.Query().Get("CDSViewTechnicalName") + fields, err := model.GetCDSViewModelFields(CDSViewTechnicalName) + if err != nil { + fmt.Println(err) + return + } + + err = ui.Template.ExecuteTemplate(w, "fields", fields) + if err != nil { + fmt.Println(err) + return + } +} diff --git a/cmd/model/cdsView.go b/cmd/model/cdsView.go index 313118a..b8ea10f 100644 --- a/cmd/model/cdsView.go +++ b/cmd/model/cdsView.go @@ -19,6 +19,7 @@ package model import ( "api-cds-search/cmd/database/table" + "encoding/base64" "fmt" "strings" @@ -35,24 +36,14 @@ type CDSViewFieldModel struct { type CDSViewModel struct { *table.CDSView - StateTitle string - Fields *[]CDSViewFieldModel + StateTitle string + TechnicalNameEncoded string + NumberOfFields int } var englishCases = cases.Title(language.English) -func GetCDSViewModel(TechnicalName string) (*CDSViewModel, error) { - var model CDSViewModel - - cdsView, err := table.GetCDSView(TechnicalName) - if err != nil { - return nil, err - } - - model.CDSView = cdsView - - model.StateTitle = englishCases.String(model.State) - +func GetCDSViewModelFields(TechnicalName string) (*[]CDSViewFieldModel, error) { fields, err := table.GetCDSViewFields(TechnicalName) if err != nil { return nil, err @@ -71,7 +62,26 @@ func GetCDSViewModel(TechnicalName string) (*CDSViewModel, error) { fieldsModel = append(fieldsModel, fieldModel) } - model.Fields = &fieldsModel + return &fieldsModel, nil +} + +func GetCDSViewModel(TechnicalName string) (*CDSViewModel, error) { + var model CDSViewModel + + cdsView, err := table.GetCDSView(TechnicalName) + if err != nil { + return nil, err + } + + model.CDSView = cdsView + + model.StateTitle = englishCases.String(model.State) + model.TechnicalNameEncoded = strings.Replace(base64.StdEncoding.EncodeToString([]byte(model.TechnicalName)), "=", "", -1) + + model.NumberOfFields, err = table.GetCDSViewNumberOfFields(TechnicalName) + if err != nil { + return nil, err + } return &model, nil } diff --git a/cmd/model/results.go b/cmd/model/results.go index 8bba7f8..dae6ec0 100644 --- a/cmd/model/results.go +++ b/cmd/model/results.go @@ -21,17 +21,26 @@ type ResultsModel struct { SearchTerm string CurrentPage int MaxPage int - Views []CDSViewModel + Views []ResultView +} + +type ResultView struct { + CDSViewModel + Score float32 } type ResultsModelBuffer struct { - Views []CDSViewModel + Views []ResultView } func NewResultsModel() *ResultsModel { return &ResultsModel{} } -func (r *ResultsModel) AppendResultsModelViews(cdsView *CDSViewModel) { - r.Views = append(r.Views, *cdsView) +func (r *ResultsModel) AppendResultsModelViews(cdsView *CDSViewModel, score float32) { + resultView := ResultView{ + CDSViewModel: *cdsView, + Score: score, + } + r.Views = append(r.Views, resultView) } diff --git a/cmd/router/router.go b/cmd/router/router.go index 003f24a..69ed84f 100644 --- a/cmd/router/router.go +++ b/cmd/router/router.go @@ -18,6 +18,7 @@ package router import ( + "api-cds-search/cmd/handler" "api-cds-search/cmd/search" "api-cds-search/cmd/ui" "fmt" @@ -34,6 +35,9 @@ func Load() *chi.Mux { r.Route("/search", func(r chi.Router) { r.Get("/", search.HandleSearch) }) + r.Route("/cds", func(r chi.Router) { + r.Get("/field/", handler.GetCDSField) + }) }) r.Handle("/ui/css/*", http.StripPrefix("/ui/css", http.FileServer(http.Dir("./cmd/ui/css")))) diff --git a/cmd/search/search.go b/cmd/search/search.go index 9acb844..acfec41 100644 --- a/cmd/search/search.go +++ b/cmd/search/search.go @@ -110,30 +110,40 @@ func BuildBuffer(searchTerm string) error { splitSearchTerms := strings.Split(searchTerm, " ") - splitSearchTerms = append(splitSearchTerms, searchTerm) - splitSearchTerms = append(splitSearchTerms, strings.ReplaceAll(searchTerm, " ", searchTerm)) + if len(splitSearchTerms) > 1 { + splitSearchTerms = append(splitSearchTerms, searchTerm) + splitSearchTerms = append(splitSearchTerms, strings.ReplaceAll(searchTerm, " ", "")) + } var fuzzyResults []fuzzyResult for viewName, targets := range searchTargets { totalHits := 0 + perfectHits := 0 + var totalDistance float32 for i, splitSearchTerm := range splitSearchTerms { + if splitSearchTerm == "" { + continue + } ranks := fuzzy.RankFindFold(splitSearchTerm, targets) hits := len(ranks) - if hits == 0 { - if i < len(splitSearchTerm)-3 { - totalDistance += 500 - } - continue + /*if hits == 0 { + if i < len(splitSearchTerm)-3 { + totalDistance += 500 } + continue + }*/ totalHits += hits var averageDistance float32 = 0 for _, rank := range ranks { averageDistance += float32(rank.Distance) + if i >= len(splitSearchTerms)-2 && rank.Distance == 0 { + perfectHits += 1 + } } totalDistance += averageDistance / float32(hits) @@ -144,7 +154,7 @@ func BuildBuffer(searchTerm string) error { CDSViewTechnicalName: viewName, hits: totalHits, averageDistance: totalDistance, - score: totalDistance / float32(totalHits), + score: (float32(len(targets)) / float32(totalHits)) / float32(perfectHits), }) } } @@ -160,6 +170,11 @@ func BuildBuffer(searchTerm string) error { } else if a.score < b.score { return -1 } + if a.CDSViewTechnicalName > b.CDSViewTechnicalName { + return 1 + } else if a.CDSViewTechnicalName < b.CDSViewTechnicalName { + return -1 + } return 0 }) @@ -192,14 +207,22 @@ func HandleSearch(w http.ResponseWriter, r *http.Request) { defer buffer.mu.Unlock() page := GetPage(r) + var maxPage int + if buffer.hits <= pageStep { + maxPage = 0 + } else { + maxPage = (buffer.hits / pageStep) + } - maxPage := (buffer.hits / pageStep) - 1 if page+1 > maxPage { page = maxPage } 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 { @@ -207,7 +230,7 @@ func HandleSearch(w http.ResponseWriter, r *http.Request) { continue } - resultsModel.AppendResultsModelViews(cdsView) + resultsModel.AppendResultsModelViews(cdsView, result.score) } resultsModel.SearchTerm = searchTerm diff --git a/cmd/ui/css/styles.css b/cmd/ui/css/styles.css index 79ca640..3adb48a 100644 --- a/cmd/ui/css/styles.css +++ b/cmd/ui/css/styles.css @@ -120,6 +120,10 @@ body { min-width: calc(14 * var(--base_length)); } +.min-w24 { + min-width: calc(24 * var(--base_length)); +} + .max-w1 { max-width: calc(1 * var(--base_length)); } diff --git a/cmd/ui/html/search-result.html b/cmd/ui/html/search-result.html index 10a3bb3..f87e059 100644 --- a/cmd/ui/html/search-result.html +++ b/cmd/ui/html/search-result.html @@ -1,14 +1,20 @@ {{block "results" .}} -