Updated design and backend

This commit is contained in:
Edgar P. Burkhart 2022-01-27 17:43:06 +01:00
parent b5d909f832
commit 8b9ce75959
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227
7 changed files with 158 additions and 67 deletions

View file

@ -1,6 +1,7 @@
import argparse
import configparser
import logging
import locale
## dev imports
from pprint import pp
import sys
@ -23,6 +24,8 @@ args = parser.parse_args()
config = configparser.ConfigParser()
config.read(args.config)
locale.setlocale(locale.LC_ALL, config.get('locale', 'locale', fallback=None))
logging.basicConfig(level=config.get('logging', 'level', fallback='WARN'))
log = logging.getLogger('saturn')
@ -30,7 +33,9 @@ log.info('Starting saturn')
davclient = get_davclient(config['caldav'])
app = create_app(davclient)
app = create_app(
davclient,
)
if __name__ == '__main__':
app.run(

View file

@ -1,6 +1,9 @@
import re
from datetime import date, datetime, time
import caldav
from datetime import date, datetime
from .event import Event
def get_davclient(config):
@ -10,6 +13,15 @@ def get_davclient(config):
password=config.get('password', fallback=None),
)
def get_comparable_dt(event):
if type(event.dtstart.value) == date:
return datetime.combine(
event.dtstart.value,
time.min,
).timestamp()
else:
return event.dtstart.value.timestamp()
def get_events(davclient):
pri = davclient.principal()
@ -18,12 +30,7 @@ def get_events(davclient):
for cal in pri.calendars():
events += [event.instance.vevent
for event in cal.date_search(start=date.today())
if type(event.instance.vevent.dtstart.value) == datetime]
events_day += [event.instance.vevent
for event in cal.date_search(start=date.today())
if type(event.instance.vevent.dtstart.value) != datetime]
events.sort(key=lambda event:event.dtstart.value)
events_day.sort(key=lambda event:event.dtstart.value)
for event in cal.date_search(start=date.today())]
events.sort(key=get_comparable_dt)
return events, events_day
return [Event(event) for event in events]

47
saturn/calendar/event.py Normal file
View file

@ -0,0 +1,47 @@
import re
class Event:
def __init__(
self,
vobject,
):
for attr in [
'dtstart',
'dtend',
'summary',
'description',
'location',
'rrule',
]:
setattr(self, f'_{attr}',
getattr(getattr(vobject, attr, None), 'value', None))
@property
def dtstart(self):
return self._dtstart
@property
def dtend(self):
return self._dtend
@property
def summary(self):
return self._summary
@property
def description(self):
return self._description
@property
def location(self):
return self._location
@property
def freq(self):
if self._rrule is None: return None
return re.search(
r'FREQ=([A-Z]+?);',
self._rrule,
).group(1)

View file

@ -4,17 +4,18 @@ from datetime import date, datetime
from ..calendar import get_events
def create_app(davclient):
def create_app(
davclient,
):
app = flask.Flask(__name__)
@app.route('/')
def home():
events, events_day = get_events(davclient)
events = get_events(davclient)
return flask.render_template(
'index.html',
events = events,
events_day = events_day,
)
return app

View file

@ -1,7 +1,6 @@
body {
display: grid;
grid-template-columns:
1fr
1fr;
grid-template-rows:
auto
@ -22,13 +21,10 @@ body > * {
margin: 1rem;
display: grid;
grid-template-columns:
1fr
6rem
1fr;
grid-template-rows:
auto
auto
auto;
gap: .5rem;
row-gap: .5rem;
column-gap: 1rem;
background: var(--ui-01);
padding: 1rem;
}
@ -39,23 +35,33 @@ body > * {
grid-column: 1 / span 2;
}
.event > .date {
grid-row: 2;
grid-column: 1;
font-size: 1.1rem;
display: grid;
grid-template-columns: auto;
gap: 1rem;
text-align: center;
}
.event > .start-date {
grid-column: 1;
text-align: right;
.event > .date > div {
display: grid;
grid-template-columns: auto;
}
.event > .end-date {
.date .day {
font-size: 3em;
}
.date .time {
font-size: 1.5em;
}
.event .end-date,
.event .other {
color: var(--text-02);
}
.event > .info {
grid-column: 2;
}
.event > .description {
grid-column: 1;
}
.event > .other {
grid-column: 2;
}
.event > .description,
.event > .other > * {
padding-top: 1rem;
display: grid;
grid-template-columns: 1fr;
grid-template-rows:
1fr
auto;
gap: 1rem;
}

View file

@ -2,8 +2,10 @@
--ui-background: white;
--ui-01: var(--gray-10);
--text-01: var(--gray-100);
--text-02: var(--gray-70);
--gray-10: #f4f4f4;
--gray-70: #525252;
--gray-100: #161616;
}

View file

@ -3,6 +3,7 @@
{% block style %}
{{ super() }}
<link rel="stylesheet" href="/static/css/index.css" />
<link href="https://cdn.jsdelivr.net/npm/remixicon/fonts/remixicon.css" rel="stylesheet">
{% endblock %}
{% block body %}
@ -11,41 +12,63 @@
<div id="events">
{% for event in events %}
<div class="event">
<div class="summary">{{ event.summary.value }}</div>
<div class="date start-date">{{ event.dtstart.value.isoformat() }}</div>
<div class="date end-date">{{ event.dtend.value.isoformat() }}</div>
{% if event.description %}
<div class="description">{{ event.description.value }}</div>
<div class="summary">{{ event.summary }}</div>
<div class="date">
<div class="start-date">
<span class="weekday">
{{ event.dtstart.strftime('%A').capitalize() }}
</span>
<span class="day">
{{ event.dtstart.strftime('%d') }}
</span>
<span class="month">
{{ event.dtstart.strftime('%B').capitalize() }}
</span>
<span class="time">
{{ event.dtstart.strftime('%H:%M') }}
</span>
</div>
<div class="end-date">
{% if not event.dtend.date or event.dtend.date() != event.dtstart.date() %}
<span class="weekday">
{{ event.dtend.strftime('%A').capitalize() }}
</span>
<span class="day">
{{ event.dtend.strftime('%d') }}
</span>
{% endif %}
<div class="other">
{% if event.location %}
<div>{{ event.location.value }}</div>
{% endif %}
{% if event.rrule %}
<div>{{ event.rrule.value }}</div>
{% if event.dtend.month != event.dtstart.month %}
<span class="month">
{{ event.dtend.strftime('%B').capitalize() }}
</span>
{% endif %}
<span class="time">
{{ event.dtend.strftime('%H:%M') }}
</span>
</div>
</div>
{% endfor %}
</div>
<div id="events_day">
{% for event in events_day %}
<div class="event">
<div class="summary">{{ event.summary.value }}</div>
<div class="date start-date">{{ event.dtstart.value }}</div>
<div class="date end-date">{{ event.dtend.value }}</div>
<div class="info">
<div class="description">
{% if event.description %}
<div class="description">{{ event.description.value }}</div>
{{ event.description }}
{% endif %}
</div>
<div class="other">
{% if event.location %}
<div>{{ event.location.value }}</div>
<div>
<i class="ri-map-pin-line ri-fw ri-sm"></i>
{{ event.location }}
</div>
{% endif %}
{% if event.rrule %}
<div>{{ event.rrule.value }}</div>
{% if event.freq %}
<div>
<i class="ri-repeat-line ri-fw ri-sm"></i>
{{ event.freq}}
</div>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}