Improve sidebar embed look and feel

This commit is contained in:
Fabian Müller 2022-11-21 03:45:43 +01:00
parent 05f985d611
commit cba66c794e
10 changed files with 156 additions and 73 deletions

View File

@ -1,4 +1,31 @@
import re
from jinja2 import pass_eval_context
from markupsafe import Markup, escape
from starlette.templating import Jinja2Templates from starlette.templating import Jinja2Templates
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory="templates")
@pass_eval_context
def nl2br(eval_ctx, value):
br = "<br>\n"
if eval_ctx.autoescape:
value = escape(value)
br = Markup(br)
result = "\n\n".join(
# need to convert p to Markup again after applying re.split(...)
f"<p>{br.join(Markup(p).splitlines())}</p>"
for p in re.split(r"(?:\r\n|\r(?!\n)|\n){2,}", value)
)
if eval_ctx.autoescape:
result = Markup(result)
return result
templates.env.filters["nl2br"] = nl2br

View File

@ -8,7 +8,7 @@ router = APIRouter()
@router.get("/events.ics") @router.get("/events.ics")
async def events(): async def events_ics():
return Response( return Response(
await get_data(), await get_data(),
headers={ headers={

View File

@ -15,8 +15,7 @@ from fabcal.routers import templates
router = APIRouter() router = APIRouter()
@router.get("/embed-sidebar.html", response_class=HTMLResponse) async def generate_response(request: Request, template_name: str, **additional_context):
async def embed(request: Request, max_width: str = None):
events = await get_future_events() events = await get_future_events()
grouped_events = list(group_by_date(events).items()) grouped_events = list(group_by_date(events).items())
@ -32,8 +31,19 @@ async def embed(request: Request, max_width: str = None):
def base64_encode(s: str): def base64_encode(s: str):
return base64.b64encode(s.encode()).decode() return base64.b64encode(s.encode()).decode()
context = {
"request": request,
"grouped_events": grouped_events,
"dir": dir,
"localized_abbreviated_month": localized_abbreviated_month,
"localized_abbreviated_weekday": localized_abbreviated_weekday,
"base64_encode": base64_encode,
}
context.update(additional_context)
return templates.TemplateResponse( return templates.TemplateResponse(
"embed-sidebar.html", template_name,
context={ context={
"request": request, "request": request,
"grouped_events": grouped_events, "grouped_events": grouped_events,
@ -43,3 +53,8 @@ async def embed(request: Request, max_width: str = None):
"base64_encode": base64_encode, "base64_encode": base64_encode,
}, },
) )
@router.get("/sidebar/embed.html", response_class=HTMLResponse)
async def embed_sidebar(request: Request):
return await generate_response(request, "sidebar/embed.html")

View File

@ -26,7 +26,6 @@ body {
display: flex; display: flex;
align-items: stretch; align-items: stretch;
flex-direction: row; flex-direction: row;
background-color: white;
} }
.calendar-date-date { .calendar-date-date {
@ -36,6 +35,7 @@ body {
margin-right: 8px; margin-right: 8px;
flex: 35px 0 0; flex: 35px 0 0;
height: 100%; height: 100%;
background-color: white;
} }
.calendar-date-month { .calendar-date-month {
background-color: var(--calendar-fablab-red); background-color: var(--calendar-fablab-red);
@ -96,6 +96,12 @@ body {
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
} }
.calendar-event-description p {
margin-bottom: 0.5em;
}
.calendar-event-description p:last-child {
margin-bottom: 0;
}
.calendar-event-type { .calendar-event-type {
flex: 0 0 12px; flex: 0 0 12px;
margin: -5px -5px -5px 0; margin: -5px -5px -5px 0;

View File

@ -1,68 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
{#- TODO: replace with locally served files #}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
<link rel="stylesheet" href="{{ url_for('static', path='style.css') }}" type="text/css"/>
<link rel="stylesheet" href="{{ url_for('static', path='roboto.css') }}" type="text/css"/>
<title>Embeddable calendar</title>
</head>
<body{% if max_width %} style="max-width: {{ max_width }}"{% endif %}>
<div class="calendar">
{% for start_date, events in grouped_events[:3] %}
<div class="calendar-date">
<div class="calendar-date-date">
<div class="calendar-date-month">
{{ start_date.strftime("%b") }}
</div>
<div class="calendar-date-day">
{{ start_date.strftime("%d") }}
</div>
<div class="calendar-date-weekday">
{{ start_date.strftime("%a") }}
</div>
</div>
<div class="calendar-events">
{% for event in events %}
<div class="calendar-event" title="{{ event.summary }}{% if event.description %} &mdash; {{ event.description }}{% endif %}">
<div class="calendar-event-time">
<div class="calendar-event-starttime">{{ event.start.strftime("%H:%M") }}</div>
<div class="calendar-event-timesep"></div>
<div class="calendar-event-endtime">{{ event.end.strftime("%H:%M") }}</div>
</div>
<div class="calendar-event-description">
{% if event.description or event.location %}
<details class="calendar-event-details">
<summary>{{ event.summary }}</summary>
<div class="calendar-popover-content">
{% if event.description %}
<div class="calendar-popover-entry">
{#- description doesn't need an icon, just wastes space #}
<div class="calendar-popover-entry-text">{{ event.description }}</div>
</div>
{% endif %}
{% if event.location %}
<div class="calendar-popover-entry">
<div class="calendar-popover-entry-icon"><i class="fa-solid fa-location-dot"></i></div>
<div class="calendar-popover-entry-text">{{ event.location }}</div>
</div>
{% endif %}
</div>
</details>
{% else %}
<span>{{ event.summary }}</span>
{% endif %}
</div>
<div class="calendar-event-type" style="background-color: {{ event.color }};"></div>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</body>
</html>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="de">
<head>
{% block header %}
{#- TODO: replace with locally served files #}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
<link rel="stylesheet" href="{{ url_for('static', path='style.css') }}" type="text/css"/>
<link rel="stylesheet" href="{{ url_for('static', path='roboto.css') }}" type="text/css"/>
<title>Embeddable calendar</title>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="de">
<head>
{#- TODO: replace with locally served files #}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
<link rel="stylesheet" href="{{ url_for('static', path='style.css') }}" type="text/css"/>
<link rel="stylesheet" href="{{ url_for('static', path='roboto.css') }}" type="text/css"/>
<title>Embeddable calendar</title>
</head>
<body>
<div class="calendar">
{% include "sidebar/includes/header.html" %}
{% include "sidebar/includes/events-list.html" %}
{% include "sidebar/includes/footer.html" %}
</div>
</body>
</html>

View File

@ -0,0 +1,57 @@
{% for start_date, events in grouped_events %}
<div class="calendar-date">
<div class="calendar-date-date">
<div class="calendar-date-month">
{{ start_date.strftime("%b") }}
</div>
<div class="calendar-date-day">
{{ start_date.strftime("%d") }}
</div>
<div class="calendar-date-weekday">
{{ start_date.strftime("%a") }}
</div>
</div>
<div class="calendar-events">
{% for event in events %}
<div class="calendar-event" title="{{ event.summary }}{% if event.description %} &mdash; {{ event.description }}{% endif %}">
<div class="calendar-event-time">
<div class="calendar-event-starttime">{{ event.start.strftime("%H:%M") }}</div>
<div class="calendar-event-timesep"></div>
<div class="calendar-event-endtime">{{ event.end.strftime("%H:%M") }}</div>
</div>
<div class="calendar-event-description">
{% if event.description or event.location %}
<details class="calendar-event-details">
<summary>{{ event.summary | urlize }}</summary>
<div class="calendar-popover-content">
{% if event.description %}
<div class="calendar-popover-entry">
{#- description doesn't need an icon, just wastes space #}
<div class="calendar-popover-entry-text">{{ event.description | urlize | nl2br }}</div>
</div>
{% endif %}
{% if event.location %}
<div class="calendar-popover-entry">
<div class="calendar-popover-entry-icon"><i class="fa-solid fa-location-dot"></i></div>
<div class="calendar-popover-entry-text">{{ event.location | urlize | nl2br }}</div>
</div>
{% endif %}
</div>
</details>
{% else %}
<span>{{ event.summary }}</span>
{% endif %}
</div>
{%- if "AusbauLab" in event.categories %}
<div class="calendar-event-type calendar-event-type-ausbau"></div>
{%- elif event.color %}
<div class="calendar-event-type" style="background-color: {{ event.color }};"></div>
{%- else %}
<div class="calendar-event-type calendar-event-type-unknown"></div>
{%- endif %}
</div>
{% endfor %}
</div>
</div>
{% endfor %}

View File

@ -0,0 +1,3 @@
<div class="calendar-subscription-buttons">
<a href="{{ url_for('events_ics') }}"><i class="fa-solid fa-calendar"></i> Kalender abonnieren</a>
</div>

View File

@ -0,0 +1 @@
<h3>Veranstaltungen</h3>