eintopf.info@v0.13.16/web/placelist.go (about)

     1  // Copyright (C) 2022 The Eintopf authors
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  
    16  package web
    17  
    18  import (
    19  	"encoding/json"
    20  	"net/http"
    21  	"sort"
    22  	"strings"
    23  	"text/template"
    24  
    25  	"eintopf.info/service/indexo"
    26  	"eintopf.info/service/place"
    27  	"eintopf.info/service/search"
    28  )
    29  
    30  // PlaceListPage renders the grouplist page.
    31  func (renderer *Renderer) PlaceListPage(w http.ResponseWriter, r *http.Request) {
    32  	query := r.URL.Query().Get("query")
    33  	result, err := renderer.search.Search(r.Context(), &search.Options{
    34  		Query: query,
    35  		Sort:  "name",
    36  		Filters: []search.Filter{
    37  			&search.TermsFilter{Field: "type", Terms: []string{"place"}},
    38  			&search.BoolFilter{Field: "listed", Value: true},
    39  		},
    40  	})
    41  	if err != nil {
    42  		renderer.errorPage(w, r, err)
    43  		return
    44  	}
    45  
    46  	alphabet := defaultAlphabet()
    47  	places := []PlaceDocument{}
    48  	for _, hit := range result.Hits {
    49  		g := PlaceDocument{}
    50  		err := hit.Unmarshal(&g)
    51  		if err != nil {
    52  			renderer.errorPage(w, r, err)
    53  			return
    54  		}
    55  		places = append(places, g)
    56  
    57  		for _, letter := range alphabet {
    58  			if []rune(letter.Letter)[0] == g.StartLetterRune() {
    59  				letter.HasItems = true
    60  				break
    61  			}
    62  		}
    63  	}
    64  	sort.Slice(places, func(i, j int) bool {
    65  		return strings.ToLower(places[i].Name) < strings.ToLower(places[j].Name)
    66  	})
    67  
    68  	currentLetter := rune('A')
    69  
    70  	err = renderer.renderPage(w, r, "placelist", map[string]any{
    71  		"Query":    query,
    72  		"Places":   places,
    73  		"Alphabet": alphabet,
    74  	}, template.FuncMap{
    75  		"isCurrentLetter": func(letter rune) bool {
    76  			if currentLetter <= letter {
    77  				currentLetter = currentLetter + letter - currentLetter + 1
    78  				return true
    79  			}
    80  			return false
    81  		},
    82  	})
    83  	if err != nil {
    84  		renderer.errorPage(w, r, err)
    85  		return
    86  	}
    87  }
    88  
    89  type PlaceDocument indexo.PlaceDocument
    90  
    91  func (g PlaceDocument) StartLetter() string {
    92  	return strings.ToUpper(string([]rune(g.Name)[0]))
    93  }
    94  
    95  func (g PlaceDocument) StartLetterRune() rune {
    96  	return []rune(g.StartLetter())[0]
    97  }
    98  
    99  func (p PlaceDocument) MapMarker() mapMarker {
   100  	return mapMarker{ID: p.ID, Name: p.Name, Lat: p.Lat, Lng: p.Lng}
   101  }
   102  
   103  type mapMarker struct {
   104  	ID   string  `json:"id"`
   105  	Name string  `json:"name"`
   106  	Lat  float64 `json:"lat"`
   107  	Lng  float64 `json:"lng"`
   108  }
   109  
   110  func placestoMapMarkers(places []PlaceDocument) string {
   111  	c := []mapMarker{}
   112  	for _, p := range places {
   113  		if p.Lat != 0 && p.Lng != 0 {
   114  			c = append(c, p.MapMarker())
   115  		}
   116  	}
   117  	data, err := json.Marshal(c)
   118  	if err != nil {
   119  		return ""
   120  	}
   121  	return string(data)
   122  }
   123  
   124  func placeDocumentToMapMarker(p PlaceDocument) string {
   125  	c := []mapMarker{p.MapMarker()}
   126  	data, err := json.Marshal(c)
   127  	if err != nil {
   128  		return ""
   129  	}
   130  	return string(data)
   131  }
   132  
   133  func placeToMapMarker(p *place.Place) string {
   134  	c := []mapMarker{{ID: p.ID, Name: p.Name, Lat: p.Lat, Lng: p.Lng}}
   135  	data, err := json.Marshal(c)
   136  	if err != nil {
   137  		return ""
   138  	}
   139  	return string(data)
   140  }