Merge branch 'staging' into production

This commit is contained in:
murmeldin 2025-04-17 00:49:37 +02:00
commit 8745fcccd0
12 changed files with 397 additions and 226 deletions

67
assets/js/clubstatus.js Normal file
View file

@ -0,0 +1,67 @@
const spaceapiUrl = "https://spaceapi.hamburg.ccc.de"
const interval_ms = 60000
console.log("clubstatus.js geladen!"); /* TODO: ENTFERNEN */
function timeDistanceDE(pastDate) {
const seconds = Math.floor((Date.now() - pastDate.getTime()) / 1000)
const minutes = Math.floor(seconds / 60)
const hours = Math.floor(minutes / 60)
const days = Math.floor(hours / 24)
if (days = 1) return `since ${days}d`
if (days > 1) return `since ${days}d`
if (hours = 1) return `since ${hours}h`
if (hours > 1) return `since ${hours}h`
if (minutes = 1) return `since ${minutes}min`
if (minutes > 1) return `since ${minutes}min`
return `gerade eben`
}
function updateRoomState(openState, lastChangeTimestamp) {
const roomstate = document.querySelector('#clubstatus-badge')
const statusItem = roomstate.querySelector(".state")
const durationItem = roomstate.querySelector(".duration")
if (!statusItem || !durationItem) return
roomstate.classList.remove("open", "closed", "unknown")
statusItem.classList.remove("open", "closed", "unknown")
if (openState === null || lastChangeTimestamp === null) {
statusItem.textContent = "unbekannt"
statusItem.classList.add("unknown")
durationItem.textContent = "(since unbekannt)"
} else {
const changeDate = new Date(lastChangeTimestamp * 1000)
const sinceText = timeDistanceDE(changeDate)
if (openState) {
statusItem.textContent = "open"
statusItem.classList.add("open")
} else {
statusItem.textContent = "closed"
statusItem.classList.add("closed")
}
durationItem.textContent = `(${sinceText})`
}
}
function fetchRoomState() {
fetch(spaceapiUrl)
.then(response => response.json())
.then(data => {
const openState = data?.state?.open ?? null
const lastChange = data?.state?.lastchange ?? null
updateRoomState(openState, lastChange)
})
.catch(err => {
console.error("Fehler beim Laden der SpaceAPI:", err)
updateRoomState(null, null)
})
}
// Initialer Abruf + dann regelmäßig
fetchRoomState()
setInterval(fetchRoomState, interval_ms)

View file

@ -1,92 +1,89 @@
theme = 'blowfish'
baseURL = 'https://oururl.de/'
defaultContentLanguage = 'de'
theme = "blowfish"
baseURL = "https://oururl.de/"
defaultContentLanguage = "de"
relativeURLs = true
canonifyURLs = true
pluralizeListTitles = false
enableRobotsTXT = true
summaryLength = 0
buildDrafts = false
buildFuture = false
enableEmoji = true
[pagination]
pagerSize = 100
[imaging]
anchor = 'Center'
anchor = "Center"
[taxonomies]
tag = 'tags'
category = 'categories'
author = 'authors'
series = 'series'
tag = "tags"
category = "categories"
author = "authors"
series = "series"
[sitemap]
changefreq = 'daily'
filename = 'sitemap.xml'
changefreq = "daily"
filename = "sitemap.xml"
priority = 0.5
[permalinks]
post = '/post/:year/:month/:day/:title/'
post = "/post/:year/:month/:day/:title/"
[outputs]
home = ['html', 'rss', 'json']
section = ['html', 'Calendar', 'rss', 'xml']
page = ['html', 'Calendar']
home = ["html", "rss", "json"]
section = ["html", "Calendar", "rss", "xml"]
page = ["html", "Calendar"]
# Output Formats Configuration
[outputFormats.Calendar]
mediaType = 'text/calendar'
baseName = 'index'
mediaType = "text/calendar"
baseName = "index"
isPlainText = true
notAlternative = true
[outputFormats.XML]
mediaType = 'application/xml'
baseName = 'index'
mediaType = "application/xml"
baseName = "index"
isPlainText = true
[outputFormats.RSS]
mediaType = 'application/rss+xml'
mediaType = "application/rss+xml"
# Media Types Configuration
[mediaTypes]
[mediaTypes.'text/calendar']
suffixes = ['ics']
suffixes = ["ics"]
[mediaTypes.'application/rss+xml']
suffixes = ['xml', 'rss']
suffixes = ["xml", "rss"]
[related]
threshold = 0
toLower = false
[[related.indices]]
name = 'tags'
name = "tags"
weight = 100
[[related.indices]]
name = 'categories'
name = "categories"
weight = 100
[[related.indices]]
name = 'series'
name = "series"
weight = 50
[[related.indices]]
name = 'authors'
name = "authors"
weight = 20
[[related.indices]]
name = 'date'
name = "date"
weight = 10
[[related.indices]]
applyFilter = false
name = 'fragmentrefs'
type = 'fragments'
name = "fragmentrefs"
type = "fragments"
weight = 10

View file

@ -8,10 +8,8 @@
colorScheme = "fira" # "congo"
defaultAppearance = "dark" # valid options: light or dark
autoSwitchAppearance = false
enableSearch = true
enableCodeCopy = false
replyByEmail = false
# mainSections = ["section1", "section2"]
@ -21,14 +19,11 @@ replyByEmail = false
disableImageOptimization = false
disableTextInHeader = false
backgroundImageWidth = 1200
# defaultBackgroundImage = "/img/cccb-im-winter.jpg" # used as default for background images
defaultFeaturedImage = "/img/avatar-CCCB-Logo.png" # used as default for featured images in all articles
# highlightCurrentMenuArea = true
smartTOC = true
smartTOCHideUnfocusedChildren = true
giteaDefaultServer = "https://git.fsfe.org"
forgejoDefaultServer = "https://git.berlin.ccc.de"
@ -117,7 +112,6 @@ forgejoDefaultServer = "https://git.berlin.ccc.de"
series = "series"
tag = "tags"
[term]
showHero = false
# heroStyle = "background" # valid options: basic, big, background, thumbAndBackground

1
content/404.md Normal file
View file

@ -0,0 +1 @@
Leider existiert diese Seite nicht.

View file

@ -1,6 +1,27 @@
---
description: "Startseite CCCB mit Kurzkalender"
---
/* this section will be enabled when the cccb spaceapi is public
<div style="display: flex; justify-content: center;">
<div id="clubstatus-badge">spacestatus unknown</div>
</div>
<style>
#clubstatus-badge {
position: relative;
background-color: #2ecc71;
flex: initial;
color: white;
padding: 0.25em 0.6em;
font-size: 0.75rem;
border-radius: 1em;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
font-weight: bold;
}
</style>
*/
### Nächste Veranstaltungen:

View file

@ -4,14 +4,12 @@
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<article role="main" class="blog-post">
<article class="max-w-prose mx-auto">
<h1 class="text-2xl font-bold">{{ .Title }}</h1>
<h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral pb-4">{{ .Title }}</h1>
{{ if .Params.subtitle }}
<h2 class="text-xl">{{ .Params.subtitle }}</h2>
<h2 class="text-xl opacity-70">{{ .Params.subtitle }}</h2>
{{ end }}
<div class="mt-4 border p-4 bg-secondary-bg rounded">
{{ partial "talk-infobox" . }}
</div>
<div class="mt-4 content">
{{ .Content }}
@ -19,11 +17,18 @@
</article>
{{ if .Params.tags }}
<div class="blog-tags">
<div class="blog-tags max-w-prose mx-auto mt-4 flex flex-wrap gap-4 border-2 p-5 pt-7 mt-6 rounded-lg opacity-75 drop-shadow-md">
<p class="opacity-50">Tags:</p>
<br>
{{ range .Params.tags }}
<a href="{{ $.Site.LanguagePrefix | absURL }}/tags/{{ . | urlize }}/">{{ . }}</a>&nbsp;
<a
href="{{ $.Site.LanguagePrefix | absURL }}/tags/{{ . | urlize }}/"
class="inline-block px-3 py-1 rounded-lg text-sm font-semibold border-2 dark:bg-neutral-700 border-dotted shadow-lg shadow-blue-500/50"
>
{{ . }}
</a>
{{ end }}
</div><!--/.blog-tags-->
</div>
{{ end }}
{{ if .Site.Params.socialShare }}
@ -37,18 +42,31 @@
</article><!--/.blog-post-->
{{ if ne .Type "page" }}
<ul class="pager blog-pager">
<ul class="pager blog-pager flex justify-between items-center mt-6 list-none p-0">
{{ if .PrevInSection }}
<li class="previous">
<a href="{{ .PrevInSection.Permalink }}" data-toggle="tooltip" data-placement="top" title="{{ .PrevInSection.Title }}">&larr; {{ i18n "previousPost" }}</a>
</li><!--/.previous-->
<a
href="{{ .PrevInSection.Permalink }}"
class="inline-block px-4 py-2 text-lg font-semibold bg-neutral-200 dark:bg-neutral-700 rounded hover:bg-neutral-300 dark:hover:bg-neutral-600 transition-colors"
title="{{ .PrevInSection.Title }}"
>
&larr; {{ i18n "previousPost" }}
</a>
</li>
{{ end }}
{{ if .NextInSection }}
<li class="next">
<a href="{{ .NextInSection.Permalink }}" data-toggle="tooltip" data-placement="top" title="{{ .NextInSection.Title }}">{{ i18n "nextPost" }} &rarr;</a>
</li><!--/.next-->
<a
href="{{ .NextInSection.Permalink }}"
class="inline-block px-4 py-2 text-lg font-semibold bg-neutral-200 dark:bg-neutral-700 rounded hover:bg-neutral-300 dark:hover:bg-neutral-600 transition-colors"
title="{{ .NextInSection.Title }}"
>
{{ i18n "nextPost" }} &rarr;
</a>
</li>
{{ end }}
</ul><!--/.pager .blog-pager-->
</ul>
{{ end }}

View file

@ -0,0 +1,3 @@
{{ $js := resources.Get "js/clubstatus.js" | resources.Minify | resources.Fingerprint }}
<script src="{{ $js.RelPermalink }}" integrity="{{ $js.Data.Integrity }}"></script>

View file

@ -0,0 +1,70 @@
<footer id="site-footer" class="py-10 print:hidden">
{{/* Footer menu */}}
{{ if .Site.Params.footer.showMenu | default true }}
{{ if .Site.Menus.footer }}
<nav class="flex flex-row pb-4 text-base font-medium text-neutral-500 dark:text-neutral-400">
<ul class="flex flex-col list-none sm:flex-row">
{{ range .Site.Menus.footer }}
<li class="flex mb-1 ltr:text-right rtl:text-left sm:mb-0 ltr:sm:mr-7 ltr:sm:last:mr-0 rtl:sm:ml-7 rtl:sm:last:ml-0">
<a class="decoration-primary-500 hover:underline hover:decoration-2 hover:underline-offset-2 flex items-center" href="{{ .URL }}"
title="{{ .Title }}">
{{ if .Pre }}
<span {{ if and .Pre .Name}} class="mr-1" {{ end }}>
{{ partial "icon.html" .Pre }}
</span>
{{ end }}
{{ .Name | markdownify }}
</a>
</li>
{{ end }}
</ul>
</nav>
{{ end }}
{{ end }}
<div class="flex items-center justify-between">
{{/* Copyright */}}
{{ if .Site.Params.footer.showCopyright | default true }}
<p class="text-sm text-neutral-500 dark:text-neutral-400">
{{- with replace .Site.Params.copyright "{ year }" now.Year }}
{{ . | markdownify }}
{{- else }}
&copy;
{{ now.Format "2006" }}
{{ .Site.Params.Author.name | markdownify }}
{{- end }}
</p>
{{ end }}
{{/* Theme attribution */}}
{{ if .Site.Params.footer.showThemeAttribution | default true }}
<p class="text-xs text-neutral-500 dark:text-neutral-400">
{{ $hugo := printf `<a class="hover:underline hover:decoration-primary-400 hover:text-primary-500"
href="https://gohugo.io/" target="_blank" rel="noopener noreferrer">Hugo</a>`
}}
{{ $blowfish := printf `<a class="hover:underline hover:decoration-primary-400 hover:text-primary-500"
href="https://blowfish.page/" target="_blank" rel="noopener noreferrer">Blowfish</a>` }}
{{ i18n "footer.powered_by" (dict "Hugo" $hugo "Theme" $blowfish) | safeHTML }}
(<a class="hover:underline hover:decoration-primary-400 hover:text-primary-500"
href="https://git.berlin.ccc.de/cccb-website-team/www">Git-Repo</a>)
</p>
{{ end }}
</div>
<script>
{{ if not .Site.Params.disableImageZoom | default true }}
mediumZoom(document.querySelectorAll("img:not(.nozoom)"), {
margin: 24,
background: 'rgba(0,0,0,0.5)',
scrollOffset: 0,
})
{{ end }}
</script>
{{ $jsProcess := resources.Get "js/process.js" }}
{{ $jsProcess = $jsProcess | resources.Minify | resources.Fingerprint "sha512" }}
<script type="text/javascript" src="{{ $jsProcess.RelPermalink }}" integrity="{{ $jsProcess.Data.Integrity }}"></script>
{{/* Extend footer - eg. for extra scripts, etc. */}}
{{ if templates.Exists "partials/extend-footer.html" }}
{{ partialCached "extend-footer.html" . }}
{{ end }}
</footer>

View file

@ -1,4 +1,4 @@
<p>
<p class="mt-4 gap-4 border-2 p-5 pt-7 mt-6 rounded-lg shadow-lg opacity-75 drop-shadow-md">
{{ if isset .Page.Params "speaker_url" }}
<strong><i class="far fa-user fa-fw"></i></strong> <a href="{{ .Page.Params.Speaker_url }}">{{ .Page.Params.Speaker }}</a><br/>
{{ else }}
@ -11,14 +11,14 @@
{{ with (eq $.Page.Params.Language "en") }}
<strong><i class="fa fa-language fa-fw"></i>🌐 Language:</strong> Englisch/English<br/>
{{ end }}
<strong><i class="fa fa-map-marker fa-fw"></i>📍 Location:</strong> {{ partial "location" .Page.Params.Location }}
</p>
<strong><i class="fa fa-map-marker fa-fw"></i>📍 Location:</strong> {{ partial "location" .Page.Params.Location }}<br/>
{{ if isset .Page.Params "recording" }}
<p><strong><i class="fa fa-video fa-fw"></i>📹 Livestream: </strong> <a href="{{ .Page.Params.Recording }}">{{ .Page.Params.Recording }}</a></p>
<strong><i class="hover:underline hover:decoration-primary-400 hover:text-primary-500"></i>📹 Livestream: </strong> <a href="{{ .Page.Params.Recording }}">{{ .Page.Params.Recording }}</a></p>
{{ else }}
{{ if and (eq .Page.Params.Streaming true) (not (isset .Page.Params "recording" )) }}
<p><strong>Stream:</strong> <a href="https://streaming.media.ccc.de/datengarten">streaming.media.ccc.de/datengarten</a></p>
<p><strong>Stream:</strong> <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500" href="https://streaming.media.ccc.de/datengarten">streaming.media.ccc.de/datengarten</a></p>
{{ else }}
<p><strong><i class="fa fa-exclamation-triangle fa-fw"></i></strong> Dieser Vortrag wird <strong>nicht</strong> gestreamed</a>! / This talk will <strong>not</strong> be streamed!</p>
{{ end }}
{{ end }}
</p>