Add pagination for past events
This commit is contained in:
@@ -12,7 +12,7 @@ from fastapi.responses import FileResponse, RedirectResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from pydantic import BaseModel, BeforeValidator, validator
|
||||
from sqlalchemy import create_engine, select
|
||||
from sqlalchemy import create_engine, func, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from meal_manager.grist import sync_with_grist
|
||||
@@ -93,12 +93,13 @@ SessionDep = Annotated[Session, Depends(get_session)]
|
||||
UserDep = Annotated[dict, Depends(get_user)]
|
||||
StrictUserDep = Annotated[dict, Depends(partial(get_user, allow_none=False))]
|
||||
|
||||
PAGE_SIZE = 18
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def index(request: Request, session: SessionDep, user: UserDep):
|
||||
"""Displays coming events and a button to register new ones"""
|
||||
now = datetime.now()
|
||||
# TODO: Once we refactored to use SQLAlchemy directly, we can probably do a nicer filtering on the date alone
|
||||
statement = (
|
||||
select(Event)
|
||||
.order_by(Event.event_time)
|
||||
@@ -108,7 +109,14 @@ async def index(request: Request, session: SessionDep, user: UserDep):
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="index.html",
|
||||
context={"events": events, "current_page": "home", "now": now, "user": user},
|
||||
context={
|
||||
"now": now,
|
||||
"total_pages": 1,
|
||||
"page": {
|
||||
"page_number": 1,
|
||||
"events": events,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -117,20 +125,39 @@ async def robots_txt():
|
||||
return FileResponse("src/meal_manager/static/robots.txt", media_type="text/plain")
|
||||
|
||||
|
||||
@app.get("/past_events")
|
||||
async def past_events(request: Request, session: SessionDep):
|
||||
@app.get("/past_events/{page_number}")
|
||||
async def past_events(request: Request, session: SessionDep, page_number: int):
|
||||
|
||||
now = datetime.now()
|
||||
# TODO: Once we refactored to use SQLAlchemy directly, we can probably do a nicer filtering on the date alone
|
||||
|
||||
statement = (
|
||||
select(Event)
|
||||
.order_by(Event.event_time)
|
||||
.where(Event.event_time < now - timedelta(days=1))
|
||||
.order_by(Event.event_time.desc())
|
||||
.offset((page_number - 1) * PAGE_SIZE)
|
||||
.limit(PAGE_SIZE)
|
||||
)
|
||||
events = session.scalars(statement)
|
||||
|
||||
num_past_events = (
|
||||
session.query(func.count(Event.id))
|
||||
.where(Event.event_time < func.datetime("now", "-1 day"))
|
||||
.scalar()
|
||||
)
|
||||
assert num_past_events is not None, "num_past_events should not be None"
|
||||
total_pages = num_past_events // PAGE_SIZE + 1
|
||||
|
||||
return templates.TemplateResponse(
|
||||
request=request,
|
||||
name="index.html",
|
||||
context={"events": events, "current_page": "past", "now": now},
|
||||
context={
|
||||
"now": now,
|
||||
"total_pages": total_pages,
|
||||
"page": {
|
||||
"page_number": page_number,
|
||||
"events": events,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<a class="nav-link {% if current_page == 'home' %}active{% endif %}" {% if current_page == 'home' %}aria-current="page"{% endif %} href="/">Kommende</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if current_page == 'past' %}active{% endif %}" {% if current_page == 'past' %}aria-current="page"{% endif %} href="/past_events">Vergangene</a>
|
||||
<a class="nav-link {% if current_page == 'past' %}active{% endif %}" {% if current_page == 'past' %}aria-current="page"{% endif %} href="/past_events/1/">Vergangene</a>
|
||||
</li>
|
||||
<!-- <li class="nav-item">-->
|
||||
<!-- <a class="nav-link {% if current_page == 'preise' %}active{% endif %}" {% if current_page == 'preise' %}aria-current="page"{% endif %} href="/preise">Preise</a>-->
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
|
||||
|
||||
|
||||
{% for event in events %}
|
||||
{% for event in page.events %}
|
||||
<div class="col">
|
||||
<div class="card h-100 shadow-sm">
|
||||
<div class="card-body">
|
||||
@@ -49,13 +49,37 @@
|
||||
</div>
|
||||
<p class="text-muted mb-3"><i class="bi bi-calendar"></i> {{ event.event_time.strftime('%A, %d.%m.%Y') }}</p>
|
||||
<p class="card-text">{{ event.description }}</p>
|
||||
<a href="event/{{ event.id }}" class="btn btn-sm {% if event.registration_deadline > now %}btn-primary{% else %}btn-secondary{% endif %}">{% if event.registration_deadline > now %}Zur Anmeldung{% else %}Details ansehen{% endif %}</a>
|
||||
<a href="/event/{{ event.id }}" class="btn btn-sm {% if event.registration_deadline > now %}btn-primary{% else %}btn-secondary{% endif %}">{% if event.registration_deadline > now %}Zur Anmeldung{% else %}Details ansehen{% endif %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if total_pages and total_pages > 1 %}
|
||||
<nav aria-label="Event pagination">
|
||||
<ul class="pagination justify-content-center my-4">
|
||||
<li class="page-item {% if page.page_number <= 1 %}disabled{% endif %}">
|
||||
<a class="page-link" href="{% if page.page_number == 'home' %}/?page={{ page.page_number - 1 }}{% else %}/past_events/{{ page.page_number - 1 }}/{% endif %}" aria-label="Previous">
|
||||
<span aria-hidden="true">«</span>
|
||||
<span class="visually-hidden">Zurück</span>
|
||||
</a>
|
||||
</li>
|
||||
{% for p in range(1, total_pages + 1) %}
|
||||
<li class="page-item {% if page.page_number == p %}active{% endif %}">
|
||||
<a class="page-link" href="{% if page.page_number == 'home' %}/?page={{ p }}{% else %}/past_events/{{ p }}/{% endif %}">{{ p }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li class="page-item {% if page.page_number >= total_pages %}disabled{% endif %}">
|
||||
<a class="page-link" href="{% if page.page_number == 'home' %}/?page={{ page.page_number + 1 }}{% else %}/past_events/{{ page.page_number + 1 }}/{% endif %}" aria-label="Next">
|
||||
<span aria-hidden="true">»</span>
|
||||
<span class="visually-hidden">Weiter</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
<!-- Modal -->
|
||||
{{ macros.login_info_modal() }}
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user