From 179bc7f334c4c45d4ce3f40bcdb623b51197d140 Mon Sep 17 00:00:00 2001 From: abl Date: Sun, 17 Mar 2024 16:18:14 +0100 Subject: [PATCH 1/2] added sport category --- .../publisher/event/html/model/SearchDTO.kt | 3 +- .../event/html/service/EventService.kt | 5 +++ .../src/main/resources/static/js/main.js | 20 +++++---- .../resources/templates/layout/drawer.hbs | 18 +++++++- .../base/boudicca/model/EventCategory.kt | 6 ++- .../collectors/AlpenvereinCollector.kt | 1 + .../collectors/LinzTermineCollector.kt | 42 +++++++++++++++++-- 7 files changed, 80 insertions(+), 15 deletions(-) diff --git a/boudicca.base/publisher-event-html/src/main/kotlin/base/boudicca/publisher/event/html/model/SearchDTO.kt b/boudicca.base/publisher-event-html/src/main/kotlin/base/boudicca/publisher/event/html/model/SearchDTO.kt index 010a825e..627eabf5 100644 --- a/boudicca.base/publisher-event-html/src/main/kotlin/base/boudicca/publisher/event/html/model/SearchDTO.kt +++ b/boudicca.base/publisher-event-html/src/main/kotlin/base/boudicca/publisher/event/html/model/SearchDTO.kt @@ -15,6 +15,7 @@ data class SearchDTO( @RequestParam("durationLonger", required = false) var durationLonger: Double?, @RequestParam("bandName", required = false) var bandName: String?, @RequestParam("includeRecurring", required = false) var includeRecurring: Boolean?, + @RequestParam("sportParticipation", required = false) var sportParticipation: String?, ) { - constructor() : this(null, null, null, null, null, null, null, null, null, null, null, null) + constructor() : this(null, null, null, null, null, null, null, null, null, null, null, null, null) } \ No newline at end of file diff --git a/boudicca.base/publisher-event-html/src/main/kotlin/base/boudicca/publisher/event/html/service/EventService.kt b/boudicca.base/publisher-event-html/src/main/kotlin/base/boudicca/publisher/event/html/service/EventService.kt index 20e884fb..f9a1c8de 100644 --- a/boudicca.base/publisher-event-html/src/main/kotlin/base/boudicca/publisher/event/html/service/EventService.kt +++ b/boudicca.base/publisher-event-html/src/main/kotlin/base/boudicca/publisher/event/html/service/EventService.kt @@ -100,6 +100,9 @@ class EventService @Autowired constructor( if (additionalFilter.isNotBlank()) { queryParts.add(additionalFilter) } + if (!searchDTO.sportParticipation.isNullOrBlank()) { + queryParts.add(equals("sport.participation", searchDTO.sportParticipation!!)) + } return and(queryParts) } @@ -188,6 +191,7 @@ class EventService @Autowired constructor( EventCategory.MUSIC -> "music" EventCategory.ART -> "miscArt" EventCategory.TECH -> "tech" + EventCategory.SPORT -> "sport" EventCategory.ALL -> "???" EventCategory.OTHER -> null } @@ -209,6 +213,7 @@ class EventService @Autowired constructor( EventCategory.MUSIC -> "Musik" EventCategory.ART -> "Kunst" EventCategory.TECH -> "Technologie" + EventCategory.SPORT -> "Sport" EventCategory.ALL -> "Alle" EventCategory.OTHER -> "Andere" else -> "???" diff --git a/boudicca.base/publisher-event-html/src/main/resources/static/js/main.js b/boudicca.base/publisher-event-html/src/main/resources/static/js/main.js index 950de69b..bf920334 100644 --- a/boudicca.base/publisher-event-html/src/main/resources/static/js/main.js +++ b/boudicca.base/publisher-event-html/src/main/resources/static/js/main.js @@ -8,8 +8,7 @@ document.addEventListener("DOMContentLoaded", () => { const resetSearchFormButton = document.getElementById("resetSearchForm"); const loadMoreButton = document.getElementById("loadMoreButton"); const categorySelect = document.getElementById("category"); - const bandNameSelect = document.getElementById("bandName"); - const musicFieldSet = document.getElementById("musicFieldSet"); + const categoryFieldSets = document.querySelectorAll("[data-category-wanted]"); loadMoreButton.addEventListener("click", () => { onLoadMoreSearch(); @@ -131,11 +130,18 @@ document.addEventListener("DOMContentLoaded", () => { const onCategoryChange = () => { let category = categorySelect.value; - if (category === "MUSIC") { - musicFieldSet.classList.remove("hidden"); - } else { - bandNameSelect.selectedIndex = 0; - musicFieldSet.classList.add("hidden"); + for (fieldSet of categoryFieldSets) { + if (fieldSet.dataset["categoryWanted"] === category) { + fieldSet.classList.remove("hidden"); + } else { + for (select of fieldSet.querySelectorAll("select")) { + select.selectedIndex = 0; + } + for (input of fieldSet.querySelectorAll("input")) { + input.value = ""; + } + fieldSet.classList.add("hidden"); + } } }; categorySelect.addEventListener("change", onCategoryChange); diff --git a/boudicca.base/publisher-event-html/src/main/resources/templates/layout/drawer.hbs b/boudicca.base/publisher-event-html/src/main/resources/templates/layout/drawer.hbs index 3fc9ce14..86d486d9 100644 --- a/boudicca.base/publisher-event-html/src/main/resources/templates/layout/drawer.hbs +++ b/boudicca.base/publisher-event-html/src/main/resources/templates/layout/drawer.hbs @@ -151,7 +151,7 @@ -
+
Musik
+
+ Sport +
+ +
+
+
Accessibility
diff --git a/boudicca.base/semantic-conventions/src/main/kotlin/base/boudicca/model/EventCategory.kt b/boudicca.base/semantic-conventions/src/main/kotlin/base/boudicca/model/EventCategory.kt index ce66461f..b9d52034 100644 --- a/boudicca.base/semantic-conventions/src/main/kotlin/base/boudicca/model/EventCategory.kt +++ b/boudicca.base/semantic-conventions/src/main/kotlin/base/boudicca/model/EventCategory.kt @@ -24,10 +24,12 @@ enum class EventCategory(val types: Set) { "museen", "museum", "ausstellung", - "musical" + "musical", + "brauchtum", ) ), - TECH(setOf("techmeetup", "technology", "technologie")); + TECH(setOf("techmeetup", "technology", "technologie")), + SPORT(setOf("sport", "football", "soccer")); companion object { fun getForType(type: String?): EventCategory? { diff --git a/boudicca.events/eventcollectors/src/main/kotlin/events/boudicca/eventcollector/collectors/AlpenvereinCollector.kt b/boudicca.events/eventcollectors/src/main/kotlin/events/boudicca/eventcollector/collectors/AlpenvereinCollector.kt index 2e30b5fd..0b35ff68 100644 --- a/boudicca.events/eventcollectors/src/main/kotlin/events/boudicca/eventcollector/collectors/AlpenvereinCollector.kt +++ b/boudicca.events/eventcollectors/src/main/kotlin/events/boudicca/eventcollector/collectors/AlpenvereinCollector.kt @@ -46,6 +46,7 @@ class AlpenvereinCollector : TwoStepEventCollector("alpenverein") { data[SemanticKeys.URL] = event data[SemanticKeys.SOURCES] = event data[SemanticKeys.TYPE] = "sport" + data["sport.participation"] = "active" data[SemanticKeys.DESCRIPTION] = eventSite.select("div.elementBoxSheet div.elementText").text() if (endDate != null) { diff --git a/boudicca.events/eventcollectors/src/main/kotlin/events/boudicca/eventcollector/collectors/LinzTermineCollector.kt b/boudicca.events/eventcollectors/src/main/kotlin/events/boudicca/eventcollector/collectors/LinzTermineCollector.kt index 2d8f1721..6643b1c7 100644 --- a/boudicca.events/eventcollectors/src/main/kotlin/events/boudicca/eventcollector/collectors/LinzTermineCollector.kt +++ b/boudicca.events/eventcollectors/src/main/kotlin/events/boudicca/eventcollector/collectors/LinzTermineCollector.kt @@ -81,6 +81,8 @@ class LinzTermineCollector : EventCollector { } else { "" } + val additionalProperties = mapAdditionalProperties(event) + for (date in event.dates) { mappedEvents.add( Event( @@ -88,7 +90,7 @@ class LinzTermineCollector : EventCollector { date.first, mapOf( SemanticKeys.ENDDATE to date.second.format(DateTimeFormatter.ISO_DATE_TIME), - SemanticKeys.TYPE to (event.type ?: ""), + SemanticKeys.TYPE to mapEventType(event.type), SemanticKeys.DESCRIPTION to description, SemanticKeys.PICTUREURL to pictureUrl, SemanticKeys.REGISTRATION to (if (event.freeOfCharge) "FREE" else "TICKET"), @@ -96,7 +98,7 @@ class LinzTermineCollector : EventCollector { SemanticKeys.LOCATION_NAME to (location?.name ?: event.locationFallbackName), //they do not include all locations in their location.xml files -.- SemanticKeys.SOURCES to event.url + "\n" + eventsBaseUrl + "\n" + locationBaseUrl - ).filter { it.value.isNotBlank() } + ).plus(additionalProperties).filter { it.value.isNotBlank() } ) ) } @@ -104,6 +106,19 @@ class LinzTermineCollector : EventCollector { return mappedEvents } + private fun mapAdditionalProperties(event: LinzTermineEvent): Map { + val additionalProperties = mutableMapOf() + + if (event.type?.first == 401) { + additionalProperties["sport.participation"] = "watch" + } + if (event.type?.first == 402) { + additionalProperties["sport.participation"] = "active" + } + + return additionalProperties + } + private fun parseEvents(): List { val formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd kk:mm:ss") @@ -133,7 +148,7 @@ class LinzTermineCollector : EventCollector { LinzTermineEvent( it.attr("id").toInt(), it.select("title").text(), - it.select("tags").first()?.child(0)?.text(), + findTag(it), it.select("date").map { Pair( LocalDateTime.parse(it.attr("dFrom"), formatter).atZone(ZoneId.of("Europe/Vienna")) @@ -151,6 +166,15 @@ class LinzTermineCollector : EventCollector { }.distinctBy { it.id } } + private fun findTag(event: Element): Pair? { + val tagElement = event.select("tags").first()?.child(0) + return if (tagElement != null) { + Pair(tagElement.attr("id").toInt(), tagElement.text()) + } else { + null + } + } + private fun findLocationId(event: Element): Int? { val idAttr = event.select("location").attr("id") return if (!idAttr.isNullOrBlank()) { @@ -184,6 +208,16 @@ class LinzTermineCollector : EventCollector { }.associateBy { it.id } } + private fun mapEventType(eventType: Pair?): String { + if (eventType == null) { + return "" + } + if (eventType.first == 401 || eventType.first == 402) { + return "sport" + } + return eventType.second + } + private fun loadXml(s: String): Document { return Jsoup.parse(fetcher.fetchUrl(s), Parser.xmlParser()) } @@ -197,7 +231,7 @@ class LinzTermineCollector : EventCollector { data class LinzTermineEvent( val id: Int, val name: String, - val type: String?, + val type: Pair?, val dates: List>, val freeOfCharge: Boolean, val url: String, From f9fe0a3af150d916c98427ae62b3ed0464bf87cc Mon Sep 17 00:00:00 2001 From: abl Date: Sun, 17 Mar 2024 16:21:18 +0100 Subject: [PATCH 2/2] added new sport category to SEMANTIC_CONVENTIONS --- SEMANTIC_CONVENTIONS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SEMANTIC_CONVENTIONS.md b/SEMANTIC_CONVENTIONS.md index ecd13994..e6352473 100644 --- a/SEMANTIC_CONVENTIONS.md +++ b/SEMANTIC_CONVENTIONS.md @@ -56,6 +56,7 @@ We use certain data types for the properties we expect. * `MUSIC`: concerts or other events where the main focus is music * `TECH`: event with technology as the focus * `ART`: art exhibitions, comedy, theater, ... +* `SPORT`: everything to do with sports, either watching them or actively participate ### Location Properties