eintopf.info@v0.13.16/web/place.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 "fmt" 20 "net/http" 21 "net/url" 22 "text/template" 23 24 "eintopf.info/internal/xerror" 25 "eintopf.info/internal/xtime" 26 "eintopf.info/service/eventsearch" 27 "eintopf.info/service/search" 28 29 "github.com/go-chi/chi/v5" 30 ) 31 32 // PlacePage renders a place page. 33 func (renderer *Renderer) PlacePage(w http.ResponseWriter, r *http.Request) { 34 id := chi.URLParam(r, "id") 35 if id == "" { 36 renderer.errorPage(w, r, xerror.NotFoundError{Err: fmt.Errorf("place not found: empty id"), Type: "place"}) 37 return 38 } 39 id, err := url.QueryUnescape(id) 40 if err != nil { 41 renderer.errorPage(w, r, xerror.NotFoundError{Err: fmt.Errorf("place not found: invalid id=%s", id), Type: "place"}) 42 return 43 } 44 result, err := renderer.search.Search(r.Context(), &search.Options{ 45 Filters: []search.Filter{ 46 &search.TermsFilter{Field: "type", Terms: []string{"place"}}, 47 &search.TermsFilter{Field: "id", Terms: []string{id}}, 48 }, 49 }) 50 if err != nil { 51 renderer.errorPage(w, r, err) 52 return 53 } 54 if len(result.Hits) != 1 { 55 renderer.errorPage(w, r, xerror.NotFoundError{Err: fmt.Errorf("place not found: id=%s", id), Type: "place"}) 56 return 57 } 58 59 place := PlaceDocument{} 60 err = result.Hits[0].Unmarshal(&place) 61 if err != nil { 62 renderer.errorPage(w, r, fmt.Errorf("unmarshal place: id=%s: %w", id, err)) 63 return 64 } 65 66 pastEvents, err := renderer.eventSearch.Search(r.Context(), eventsearch.Options{ 67 Sort: "date", 68 SortDescending: true, 69 PageSize: 5, 70 Filters: []eventsearch.Filter{ 71 eventsearch.ListedFilter{Listed: true}, 72 eventsearch.PlaceIDFilter{PlaceID: id}, 73 eventsearch.StartRangeFilter{StartMax: xtime.NowInLocation(renderer.tz)}, 74 eventsearch.MultidayRangeFilter{MultidayMax: iptr(1)}, 75 }, 76 }) 77 if err != nil { 78 renderer.errorPage(w, r, fmt.Errorf("search past events: placeID=%s: %w", id, err)) 79 return 80 } 81 82 futureEvents, err := renderer.eventSearch.Search(r.Context(), eventsearch.Options{ 83 Sort: "date", 84 PageSize: 5, 85 Filters: []eventsearch.Filter{ 86 eventsearch.ListedFilter{Listed: true}, 87 eventsearch.PlaceIDFilter{PlaceID: id}, 88 eventsearch.StartRangeFilter{StartMin: xtime.NowInLocation(renderer.tz)}, 89 eventsearch.MultidayRangeFilter{MultidayMax: iptr(1)}, 90 }, 91 }) 92 if err != nil { 93 renderer.errorPage(w, r, fmt.Errorf("search future events: placeID=%s: %w", id, err)) 94 return 95 } 96 97 metaTags := MetaTags{Title: place.Name, Description: place.Description, Image: place.Image, NotPublished: !place.Published} 98 99 err = renderer.renderPage(w, r, "place", map[string]any{ 100 "Place": place, 101 "Options": eventListOptions{}, 102 "PastEvents": pastEvents.Events, 103 "FutureEvents": futureEvents.Events, 104 "Meta": metaTags, 105 }, template.FuncMap{ 106 "placeShouldRenderMap": func(p PlaceDocument) bool { 107 if p.Lat == 0 || p.Lng == 0 { 108 return false 109 } 110 return true 111 }, 112 }) 113 if err != nil { 114 renderer.errorPage(w, r, err) 115 return 116 } 117 }