refacture all the things!
This commit is contained in:
parent
9a7b9ba2c0
commit
2e3a02af0c
|
@ -1,4 +1,4 @@
|
|||
name: Test deployment
|
||||
name: Release website
|
||||
|
||||
on:
|
||||
push:
|
63
README.md
63
README.md
|
@ -1,42 +1,51 @@
|
|||
![CCCB logo](static/img/logo.png)
|
||||
|
||||
# CCCB Website
|
||||
|
||||
This is the website of CCCB.
|
||||
This is the website of the CCCB.
|
||||
|
||||
## Getting started
|
||||
|
||||
Get Hugo: <https://gohugo.io/getting-started/installing>
|
||||
|
||||
Clone this repo
|
||||
```
|
||||
git clone https://github.com/cccb/www
|
||||
```
|
||||
|
||||
Switch directory
|
||||
```
|
||||
cd www
|
||||
```
|
||||
|
||||
Fetch Submodules
|
||||
```
|
||||
git submodule update --recursive --remote --init
|
||||
```
|
||||
1. Get Hugo: <https://gohugo.io/getting-started/installing>
|
||||
2. Clone this repo
|
||||
```shell
|
||||
git clone https://github.com/cccb/www
|
||||
```
|
||||
3. Switch directory
|
||||
```shell
|
||||
cd www
|
||||
```
|
||||
3. Fetch Submodules
|
||||
```shell
|
||||
git submodule update --recursive --remote --init
|
||||
```
|
||||
|
||||
### Run site locally
|
||||
|
||||
Run hugo webserver
|
||||
```
|
||||
Run hugo webserver:
|
||||
|
||||
```shell
|
||||
hugo serve
|
||||
```
|
||||
Point your browser to http://localhost:1313/
|
||||
|
||||
To ready your site for upload, run "./build.sh", which also generates all.ics and adds the calendar table to index.html
|
||||
Point your browser to: http://localhost:1313/
|
||||
|
||||
To ready your site for upload, run `./build.sh`, which also generates `all.ics` and adds the calendar table to `index.html`.
|
||||
Every change you make on the project will be reflected in your browser as long as `hugo serve` is running.
|
||||
|
||||
## Making a change
|
||||
|
||||
* Use your local dev setup (see Getting started) or via GitLab editor.
|
||||
* Make your change in `staging` branch.
|
||||
* Commit (and push) your change.
|
||||
* Gitlab CI is running pipeline. If successfull, check [Staging Website](https://staging.berlin.ccc.de/) if change is correct.
|
||||
* Create merge request to merge changes from `staging` to `production`. Ask somebody to check merge request or if small change, merge yourself.
|
||||
* Gitlab CI is running pipeline. If successfull, check [Website](https://berlin.ccc.de/) if change is correct.
|
||||
1. Use your local dev setup (see Getting started) or via GitHub editor.
|
||||
2. Make your change in `staging` branch.
|
||||
3. Commit (and push) your change.
|
||||
4. GitHub Actions is running the release workflow.
|
||||
- If successful, check [Staging Website](https://staging.berlin.ccc.de/) if change is correct.
|
||||
5. Create merge request to merge changes from `staging` to `production` branch. Ask somebody to check merge request or if small change, merge yourself.
|
||||
6. GitHub Actions is running the release workflow.
|
||||
- If successfull, check [Website](https://berlin.ccc.de/) if change is correct.
|
||||
7. Profit!
|
||||
|
||||
---
|
||||
|
||||
Made with ❤️ and [Hugo](https://gohugo.io).
|
||||
|
||||
|
|
12
TODO.md
12
TODO.md
|
@ -1,15 +1,14 @@
|
|||
Todo
|
||||
----
|
||||
# Todo
|
||||
|
||||
- DSGVO-compliant Datenschutzerklärung reinbasteln
|
||||
- Entscheiden, welche Seiten sonst noch konvertiert werden sollen und welche in die ewigen Datengründe gehen können
|
||||
|
||||
Done
|
||||
----
|
||||
# Done
|
||||
|
||||
- Template aussuchen
|
||||
- Rausfinden, wie man eine Seite konvertiert
|
||||
- hugo new page/mypage.md
|
||||
- pandoc -f mediawiki page.mw -t markdown >> page/mypage.md
|
||||
- `hugo new page/mypage.md`
|
||||
- `pandoc -f mediawiki page.mw -t markdown >> page/mypage.md`
|
||||
- Wichtigste Seiten konvertieren
|
||||
- Membership-Seite auf den aktuellen Stand der Wahrheit bringen
|
||||
- Ical template bauen
|
||||
|
@ -17,3 +16,4 @@ Done
|
|||
- Bestehende Datengarten-Termine konvertieren
|
||||
- ggf. template mit frontmatter
|
||||
- Theme forken, alle assets sollten lokal gehosted sein und nicht von irgendwelchen CDNs bezogen werden (HTTP/2 ftw!)
|
||||
|
||||
|
|
7
build.sh
7
build.sh
|
@ -1,7 +1,8 @@
|
|||
#!/usr/bin/env sh
|
||||
#!/bin/sh
|
||||
|
||||
hugo $(cat .hugo-params)
|
||||
tools/merge_cals.py
|
||||
upcoming="$(tools/gen_upcoming.py static/all.ics 20 5|tr '\n' ' ')"
|
||||
./tools/merge_cals.py
|
||||
upcoming="$(tools/gen_upcoming.py static/all.ics 20 5 | tr '\n' ' ')"
|
||||
cp static/all.ics public/all.ics
|
||||
sed -i "s#CALENDAR#$upcoming#g" public/index.html
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ mediaTypes:
|
|||
suffixes:
|
||||
- "xml"
|
||||
|
||||
|
||||
outputFormats:
|
||||
RSS:
|
||||
mediaType: "application/rss"
|
||||
|
@ -80,3 +79,4 @@ outputs:
|
|||
page:
|
||||
- "HTML"
|
||||
- "Calendar"
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
{{ range .Params.tags }}
|
||||
<a href="{{ $.Site.LanguagePrefix | absURL }}/tags/{{ . | urlize }}/">{{ . }}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div><!--/.blog-tags-->
|
||||
{{ end }}
|
||||
|
||||
{{ if .Site.Params.socialShare }}
|
||||
|
@ -19,24 +19,24 @@
|
|||
<section id="social-share">
|
||||
<ul class="list-inline footer-links">
|
||||
{{ partial "share-links" . }}
|
||||
</ul>
|
||||
</section>
|
||||
</ul><!--/.social-share-->
|
||||
</section><!--/.list-inline /.footer-links-->
|
||||
{{ end }}
|
||||
</article>
|
||||
</article><!--/.blog-post-->
|
||||
|
||||
{{ if ne .Type "page" }}
|
||||
<ul class="pager blog-pager">
|
||||
{{ if .PrevInSection }}
|
||||
<li class="previous">
|
||||
<a href="{{ .PrevInSection.Permalink }}" data-toggle="tooltip" data-placement="top" title="{{ .PrevInSection.Title }}">← {{ i18n "previousPost" }}</a>
|
||||
</li>
|
||||
</li><!--/.previous-->
|
||||
{{ end }}
|
||||
{{ if .NextInSection }}
|
||||
<li class="next">
|
||||
<a href="{{ .NextInSection.Permalink }}" data-toggle="tooltip" data-placement="top" title="{{ .NextInSection.Title }}">{{ i18n "nextPost" }} →</a>
|
||||
</li>
|
||||
</li><!--/.next-->
|
||||
{{ end }}
|
||||
</ul>
|
||||
</ul><!--/.pager /.blog-pager-->
|
||||
{{ end }}
|
||||
|
||||
|
||||
|
@ -44,16 +44,16 @@
|
|||
{{ if .Site.DisqusShortname }}
|
||||
<div class="disqus-comments">
|
||||
{{ template "_internal/disqus.html" . }}
|
||||
</div>
|
||||
</div><!--/.disqus-comments-->
|
||||
{{ end }}
|
||||
{{ if .Site.Params.staticman }}
|
||||
<div class="staticman-comments">
|
||||
{{ partial "staticman-comments.html" . }}
|
||||
</div>
|
||||
</div><!--/.staticman-comments-->
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.col-lg-8 /.col-lg-offset-2 /.col-md-10 /.col-md-offset-1-->
|
||||
</div><!--/.row-->
|
||||
</div><!--/.container-->
|
||||
{{ end }}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{{ $series := or (.Get 0) $.Page.Params.series }}
|
||||
<table>
|
||||
<tr>
|
||||
<th>No.</th>
|
||||
<th>Date</th>
|
||||
<th>Speaker</th>
|
||||
<th>Topic</th>
|
||||
<th>Video</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>No.</th>
|
||||
<th>Date</th>
|
||||
<th>Speaker</th>
|
||||
<th>Topic</th>
|
||||
<th>Video</th>
|
||||
</tr>
|
||||
{{ range $ind,$art := $.Site.Pages.ByDate.Reverse }}
|
||||
{{ if eq $art.Params.series $series }}
|
||||
<tr>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "Usage: $0 Mediawiki_Page_Name [page|post]"
|
||||
|
@ -7,9 +7,12 @@ fi
|
|||
|
||||
echo Converting $1...
|
||||
|
||||
page=$(echo $1 | sed 's,/,_,g'|tr '[:upper:]' '[:lower:]')
|
||||
page=$(echo $1 | sed 's,/,_,g' | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
hugo new $2/$page.md
|
||||
curl -s https://berlin.ccc.de/api.php\?action\=query\&prop\=revisions\&rvprop\=content\&format\=json\&titles\=$1 | \
|
||||
jq -r '.query.pages |..| objects|.["*"]'| sed '/null/d' | pandoc -f mediawiki -t markdown \
|
||||
curl -s "https://berlin.ccc.de/api.php?action=query&prop=revisions&rvprop=content&format=json&titles=$1" \
|
||||
| jq -r '.query.pages |..| objects|.["*"]' \
|
||||
| sed '/null/d' \
|
||||
| pandoc -f mediawiki -t markdown \
|
||||
>> content/$2/$page.md
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import sys
|
||||
import logging
|
||||
import locale
|
||||
from pprint import pprint
|
||||
from dateutil.parser import parse
|
||||
from datetime import datetime, timedelta
|
||||
from dateutil.rrule import rruleset, rrulestr
|
||||
|
@ -13,78 +12,82 @@ import icalendar
|
|||
|
||||
def vevent_to_event(event, rrstart=None):
|
||||
if rrstart == None:
|
||||
begin = parse(event['DTSTART'].to_ical())
|
||||
begin = parse(event["DTSTART"].to_ical())
|
||||
else:
|
||||
begin = rrstart
|
||||
return { "name": event['SUMMARY'].to_ical(), "url": event['URL'].to_ical(), "begin": begin }
|
||||
|
||||
return {
|
||||
"name": event["SUMMARY"].to_ical(),
|
||||
"url": event["URL"].to_ical(),
|
||||
"begin": begin
|
||||
}
|
||||
|
||||
|
||||
def parse_single_event(event, start, end):
|
||||
logging.info("Processing single event %s" % event['SUMMARY'].to_ical().decode('utf-8'))
|
||||
dtstart = parse(event['DTSTART'].to_ical())
|
||||
logging.info(f"Processing single event {event['SUMMARY'].to_ical().decode('utf-8')}")
|
||||
dtstart = parse(event["DTSTART"].to_ical())
|
||||
if dtstart >= start and dtstart < end:
|
||||
return vevent_to_event(event)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def parse_recurring_event(event, start, end):
|
||||
logging.info("Processing recurring event %s" % event['SUMMARY'].to_ical().decode('utf-8'))
|
||||
dtstart = parse(event['DTSTART'].to_ical())
|
||||
logging.info(f"Processing recurring event {event['SUMMARY'].to_ical().decode('utf-8')}")
|
||||
dtstart = parse(event["DTSTART"].to_ical())
|
||||
rs = rruleset()
|
||||
rs.rrule(rrulestr(event['RRULE'].to_ical().decode('utf-8'), dtstart=dtstart))
|
||||
if 'EXDATE' in event.keys():
|
||||
exdates = event['EXDATE']
|
||||
for exdate in exdates:
|
||||
rs.rrule(rrulestr(event["RRULE"].to_ical().decode("utf-8"), dtstart=dtstart))
|
||||
if "EXDATE" in event.keys():
|
||||
for exdate in event["EXDATE"]:
|
||||
rs.exdate(parse(exdate.to_ical()))
|
||||
|
||||
dates = list(rs)
|
||||
events = []
|
||||
for date in dates:
|
||||
for date in list(rs):
|
||||
if date >= start and date < end:
|
||||
events.append(vevent_to_event(event, date))
|
||||
|
||||
return events
|
||||
|
||||
|
||||
def find_events(icsfilestr, start, end, num):
|
||||
with open(icsfilestr, 'r') as icsfile:
|
||||
cal=icalendar.Calendar.from_ical(icsfile.read())
|
||||
with open(icsfilestr, "r") as icsfile:
|
||||
cal = icalendar.Calendar.from_ical(icsfile.read())
|
||||
|
||||
events=[]
|
||||
events = []
|
||||
for event in cal.subcomponents:
|
||||
if event.name == 'VEVENT':
|
||||
if 'RRULE' in event.keys():
|
||||
events = events + parse_recurring_event(event, start, end)
|
||||
else:
|
||||
ev = parse_single_event(event, start, end)
|
||||
if ev != None:
|
||||
if event.name == "VEVENT":
|
||||
if "RRULE" in event.keys():
|
||||
events.append(parse_recurring_event(event, start, end))
|
||||
elif ev := parse_single_event(event, start, end) != None:
|
||||
events.append(ev)
|
||||
|
||||
events = sorted(events, key=lambda k: k['begin'])
|
||||
events = sorted(events, key=lambda k: k["begin"])
|
||||
events = events[0:num]
|
||||
|
||||
return events
|
||||
|
||||
|
||||
def format_events(events):
|
||||
print('<table class="table table-condensed">')
|
||||
print("<table class=\"table table-condensed\">")
|
||||
for event in events:
|
||||
dateStr = event['begin'].strftime("%A, %d.%m um %H:%M Uhr")
|
||||
#print("<li><a href=\"%s\">%s: %s</a></li>" % (event['url'].decode('utf-8'), dateStr, event['name'].decode('utf-8')))
|
||||
print("<tr><td>%s</td><td><a href=\"%s\">%s</a></td></tr>"
|
||||
% (dateStr, event['url'].decode('utf-8'), event['name'].decode('utf-8')))
|
||||
print('</table>')
|
||||
print(
|
||||
"<tr>"
|
||||
f"<td>{event['begin'].strftime('%A, %d.%m um %H:%M Uhr')}</td>"
|
||||
f"<td><a href=\"{event['url'].decode('utf-8')}\">{event['name'].decode('utf-8')}</a></td>"
|
||||
"</tr>"
|
||||
)
|
||||
print("</table><!--/.table /.table-condensed-->")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: %s calendar max_days max_items" % sys.argv[0])
|
||||
print(f"Usage: {sys.argv[0]} calendar max_days max_items")
|
||||
sys.exit(-1)
|
||||
|
||||
locale.setlocale(locale.LC_TIME, "de_DE.UTF-8")
|
||||
calendar=sys.argv[1]
|
||||
max_days=int(sys.argv[2])
|
||||
max_items=int(sys.argv[3])
|
||||
calendar = sys.argv[1]
|
||||
max_days = int(sys.argv[2])
|
||||
max_items = int(sys.argv[3])
|
||||
|
||||
events=find_events(calendar, datetime.now(), datetime.now() + timedelta(days=max_days), max_items)
|
||||
now = datetime.now()
|
||||
events = find_events(calendar, now, now + timedelta(days=max_days), max_items)
|
||||
format_events(events)
|
||||
|
||||
|
|
|
@ -6,22 +6,22 @@ import pytz
|
|||
import icalendar
|
||||
|
||||
|
||||
cals = []
|
||||
calendars = []
|
||||
merged = icalendar.Calendar()
|
||||
merged.add('prodid', '-//CCCB Calendar Generator//berlin.ccc.de//')
|
||||
merged.add('version', '2.0')
|
||||
merged.add("prodid", "-//CCCB Calendar Generator//berlin.ccc.de//")
|
||||
merged.add("version", "2.0")
|
||||
|
||||
for icsfilestr in glob('public/*/**/*.ics', recursive=True):
|
||||
with open(icsfilestr, 'r') as icsfile:
|
||||
print('Importing', icsfilestr)
|
||||
cals.append(icalendar.Calendar.from_ical(icsfile.read()))
|
||||
for icsfilestr in glob("public/*/**/*.ics", recursive=True):
|
||||
with open(icsfilestr, "r") as icsfile:
|
||||
print(f"Importing {icsfilestr}")
|
||||
calendars.append(icalendar.Calendar.from_ical(icsfile.read()))
|
||||
|
||||
for cal in cals:
|
||||
for e in cal.subcomponents:
|
||||
merged.add_component(e)
|
||||
for calendar in calendars:
|
||||
for event in calendar.subcomponents:
|
||||
merged.add_component(event)
|
||||
|
||||
outfile = 'static/all.ics'
|
||||
with open(outfile, 'wb') as f:
|
||||
print(f'writing to {outfile}...')
|
||||
outfile = "static/all.ics"
|
||||
with open(outfile, "wb") as f:
|
||||
print(f"writing to {outfile}...")
|
||||
f.write(merged.to_ical())
|
||||
|
||||
|
|
Loading…
Reference in a new issue