inaktive veranstaltungen zeigen keinen teilnahmeberreich mehr, veranstaltungsortsuche verbessert
This commit is contained in:
+26
-3
@@ -2,6 +2,7 @@ import os
|
|||||||
import uuid
|
import uuid
|
||||||
import secrets
|
import secrets
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import re
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
@@ -1147,6 +1148,7 @@ def concert_detail(request: Request, concert_id: int):
|
|||||||
]
|
]
|
||||||
attending_users = [item for item in attendance if item["status"] == "attending"]
|
attending_users = [item for item in attendance if item["status"] == "attending"]
|
||||||
ticket_seekers = [item for item in attendance if item["status"] == "ticket_search"]
|
ticket_seekers = [item for item in attendance if item["status"] == "ticket_search"]
|
||||||
|
maybe_users = [item for item in attendance if item["status"] == "maybe"]
|
||||||
current_attendance = next(
|
current_attendance = next(
|
||||||
(item["status"] for item in attendance if item["user_id"] == user["id"]),
|
(item["status"] for item in attendance if item["user_id"] == user["id"]),
|
||||||
None,
|
None,
|
||||||
@@ -1165,6 +1167,8 @@ def concert_detail(request: Request, concert_id: int):
|
|||||||
attending_count=len(attending_users),
|
attending_count=len(attending_users),
|
||||||
ticket_seekers=ticket_seekers,
|
ticket_seekers=ticket_seekers,
|
||||||
ticket_seeker_count=len(ticket_seekers),
|
ticket_seeker_count=len(ticket_seekers),
|
||||||
|
maybe_users=maybe_users,
|
||||||
|
maybe_count=len(maybe_users),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -1606,6 +1610,12 @@ def search_venues(q: str):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
query_tokens = [
|
||||||
|
token
|
||||||
|
for token in re.findall(r"[a-z0-9]+", q.lower())
|
||||||
|
if len(token) >= 3
|
||||||
|
]
|
||||||
|
token_match = " AND ".join("name ILIKE %s" for _ in query_tokens) or "FALSE"
|
||||||
|
|
||||||
|
|
||||||
# ========================================================
|
# ========================================================
|
||||||
@@ -1616,7 +1626,7 @@ def search_venues(q: str):
|
|||||||
|
|
||||||
with connection.cursor() as cursor:
|
with connection.cursor() as cursor:
|
||||||
|
|
||||||
cursor.execute("""
|
cursor.execute(f"""
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
@@ -1633,6 +1643,7 @@ def search_venues(q: str):
|
|||||||
name ILIKE %s
|
name ILIKE %s
|
||||||
OR city ILIKE %s
|
OR city ILIKE %s
|
||||||
OR street ILIKE %s
|
OR street ILIKE %s
|
||||||
|
OR ({token_match})
|
||||||
ORDER BY
|
ORDER BY
|
||||||
CASE
|
CASE
|
||||||
WHEN LOWER(name) = LOWER(%s)
|
WHEN LOWER(name) = LOWER(%s)
|
||||||
@@ -1653,11 +1664,13 @@ def search_venues(q: str):
|
|||||||
|
|
||||||
f"%{q}%",
|
f"%{q}%",
|
||||||
|
|
||||||
|
*[f"%{token}%" for token in query_tokens],
|
||||||
|
|
||||||
q,
|
q,
|
||||||
|
|
||||||
f"{q}%",
|
f"{q}%",
|
||||||
|
|
||||||
f"%{q}%"
|
f"%{q}%",
|
||||||
|
|
||||||
))
|
))
|
||||||
|
|
||||||
@@ -1717,9 +1730,11 @@ def search_venues(q: str):
|
|||||||
"User-Agent": "PinguConcerts/1.0"
|
"User-Agent": "PinguConcerts/1.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
external_query = re.sub(r"\bhall\b", "halle", q, flags=re.IGNORECASE)
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
|
|
||||||
"q": q,
|
"q": external_query,
|
||||||
|
|
||||||
"format": "jsonv2",
|
"format": "jsonv2",
|
||||||
|
|
||||||
@@ -1876,6 +1891,14 @@ def search_venues(q: str):
|
|||||||
|
|
||||||
score = 0
|
score = 0
|
||||||
|
|
||||||
|
name_tokens = re.findall(r"[a-z0-9]+", name_lower)
|
||||||
|
matched_tokens = sum(
|
||||||
|
any(candidate.startswith(token) or token.startswith(candidate)
|
||||||
|
for candidate in name_tokens)
|
||||||
|
for token in query_tokens
|
||||||
|
)
|
||||||
|
score += matched_tokens * 30
|
||||||
|
|
||||||
|
|
||||||
if name_lower == query_lower:
|
if name_lower == query_lower:
|
||||||
|
|
||||||
|
|||||||
@@ -196,7 +196,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
<section class="attendance-section" id="attendance">
|
{% if not concert.is_past %}
|
||||||
|
|
||||||
|
<section class="attendance-section" id="attendance">
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
🐧 Wer ist dabei?
|
🐧 Wer ist dabei?
|
||||||
@@ -241,6 +243,7 @@
|
|||||||
<details class="attendance-list">
|
<details class="attendance-list">
|
||||||
<summary>
|
<summary>
|
||||||
{{ attending_count }} Zusage{% if attending_count != 1 %}n{% endif %}
|
{{ attending_count }} Zusage{% if attending_count != 1 %}n{% endif %}
|
||||||
|
· {{ maybe_count }} Vielleicht
|
||||||
· {{ ticket_seeker_count }} sucht Ticket
|
· {{ ticket_seeker_count }} sucht Ticket
|
||||||
</summary>
|
</summary>
|
||||||
|
|
||||||
@@ -260,6 +263,20 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>? Vielleicht</h3>
|
||||||
|
|
||||||
|
{% if maybe_users %}
|
||||||
|
<ul>
|
||||||
|
{% for maybe_user in maybe_users %}
|
||||||
|
<li>{{ maybe_user.name }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p>Noch keine Vielleicht-Angaben.</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3>🎟️ Sucht ein Ticket</h3>
|
<h3>🎟️ Sucht ein Ticket</h3>
|
||||||
|
|
||||||
@@ -277,7 +294,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<section class="comments-section" id="comments">
|
<section class="comments-section" id="comments">
|
||||||
|
|
||||||
|
|||||||
@@ -389,6 +389,27 @@ const selectedVenue =
|
|||||||
|
|
||||||
|
|
||||||
let searchTimeout = null;
|
let searchTimeout = null;
|
||||||
|
let venueRequestController = null;
|
||||||
|
|
||||||
|
|
||||||
|
function clearVenueSelection() {
|
||||||
|
|
||||||
|
[
|
||||||
|
"venue-id",
|
||||||
|
"venue-name",
|
||||||
|
"venue-city",
|
||||||
|
"venue-street",
|
||||||
|
"venue-postal-code",
|
||||||
|
"venue-country",
|
||||||
|
"venue-latitude",
|
||||||
|
"venue-longitude"
|
||||||
|
].forEach(
|
||||||
|
id => {
|
||||||
|
document.getElementById(id).value = "";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
venueSearch.addEventListener(
|
venueSearch.addEventListener(
|
||||||
@@ -410,6 +431,8 @@ venueSearch.addEventListener(
|
|||||||
selectedVenue.style.display =
|
selectedVenue.style.display =
|
||||||
"none";
|
"none";
|
||||||
|
|
||||||
|
clearVenueSelection();
|
||||||
|
|
||||||
|
|
||||||
if (query.length < 2) {
|
if (query.length < 2) {
|
||||||
|
|
||||||
@@ -426,7 +449,7 @@ venueSearch.addEventListener(
|
|||||||
);
|
);
|
||||||
|
|
||||||
},
|
},
|
||||||
300
|
450
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -443,9 +466,18 @@ async function searchVenues(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
if (venueRequestController) {
|
||||||
|
venueRequestController.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
venueRequestController = new AbortController();
|
||||||
|
|
||||||
const response =
|
const response =
|
||||||
await fetch(
|
await fetch(
|
||||||
`/api/venues/search?q=${encodeURIComponent(query)}`
|
`/api/venues/search?q=${encodeURIComponent(query)}`,
|
||||||
|
{
|
||||||
|
signal: venueRequestController.signal
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -554,6 +586,10 @@ async function searchVenues(
|
|||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
|
if (error.name === "AbortError") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
console.error(
|
console.error(
|
||||||
"Venue search failed:",
|
"Venue search failed:",
|
||||||
error
|
error
|
||||||
|
|||||||
Reference in New Issue
Block a user