24 Commits

Author SHA1 Message Date
b451fdfaf2 Merge pull request 'Update README with current status' (#21) from feature/main-UpdateREADME into main
Reviewed-on: #21
2026-01-23 14:22:13 +01:00
58cb5fb5ee Update README with current status 2026-01-23 14:21:59 +01:00
d4b972cc4e Merge pull request 'feature/main-19-ActivitiesTab' (#20) from feature/main-19-ActivitiesTab into main
Reviewed-on: #20
Reviewed-by: Pablo Ferreiro <me@pabloferreiro.es>
2026-01-20 20:22:44 +01:00
326e76aac4 Delete files 2026-01-19 09:01:34 +01:00
66027471f6 Limit scope 2026-01-19 09:01:23 +01:00
2d509e352d Delete limit 2026-01-18 21:55:07 +01:00
f6ed158b0f Add Activities tab 2026-01-18 21:49:53 +01:00
404d2cb716 Merge pull request 'Update index.md' (#16) from feature/main-UpdateMainPage into main
Reviewed-on: #16
2026-01-16 19:40:03 +01:00
9bc8d09525 Update index.md 2026-01-16 19:38:49 +01:00
00b79db0d2 Merge pull request 'Fix typo in title' (#15) from fix/main-FixTypo into main
Reviewed-on: #15
2026-01-15 21:10:06 +01:00
45d8af4fb2 Fix typo in title 2026-01-15 21:09:53 +01:00
8de18ffea9 Merge pull request 'fix/main-AddNewLine' (#14) from fix/main-AddNewLine into main
Reviewed-on: #14
2026-01-15 18:27:37 +01:00
11378e5fd5 Add new line 2026-01-15 18:27:02 +01:00
2a4c4d731e Add new line 2026-01-15 18:25:47 +01:00
b6d125741c Merge pull request 'Update index.md' (#13) from feature/main-8-UpdateIndex into main
Reviewed-on: #13
2026-01-15 17:04:10 +01:00
7fe8f12838 Update title 2026-01-15 17:03:37 +01:00
f65b89909e Actualizar content/en/_index.md 2026-01-15 16:51:22 +01:00
d522f0da20 Update index.md 2026-01-15 16:48:04 +01:00
a6dc310cbf Merge pull request 'Add new project - Podcasteando' (#12) from feature/main-PodcastNewPost into main
Reviewed-on: #12
2026-01-13 09:21:44 +01:00
3b370c08c3 Add new project 2026-01-13 09:20:46 +01:00
a251170939 Merge pull request 'Update footer' (#11) from bugfix/main-UpdateFooter into main
Reviewed-on: #11
2026-01-11 19:21:53 +01:00
87b8ea9aa1 Update footer 2026-01-11 19:21:15 +01:00
4d47a1cfe9 Merge pull request 'Update year footer' (#4) from feature-update-footer into main
Reviewed-on: #4
2026-01-11 11:05:15 +01:00
8f3dd749fc Update year footer 2026-01-11 10:26:22 +01:00
14 changed files with 738 additions and 23 deletions

View File

@@ -1,11 +1,7 @@
*WIP*
# Website for Open Bokeron
This repo hosts the website for Open Bokeron which is a student organization in University of Málaga whose aim is to promote the use of free(as in freedom) software.
The philosophy with this website for now is to KISS(keep it stupid simple) using only HTML5 & CSS 3.
## Developer preview
You need [Hugo](https://gohugo.io/) installed.
@@ -18,7 +14,7 @@ hugo server
## TODO
- [x] Add our logo on the website, favicon.
- [ ] Add content describing our association and other pages as needed.
- [x] Add content describing our association and other pages as needed.
- [x] Work on SEO (OpenGraph, Twitter meta tags...)
- [x] Multilingual support(English + Spanish)
- [x] Support for RSS (index.xml)

View File

@@ -1,12 +1,340 @@
/* Override colors from CSS library */
:root {
--accent: green;
--accent-hover: darkgreen;
--accent: green;
--accent-hover: darkgreen;
}
/* Custom style for the logo */
img.icon {
max-width: 128px;
max-height: 128px;
margin-top: 10px;
max-width: 128px;
max-height: 128px;
margin-top: 10px;
}
:root {
--activity-bg: transparent;
--activity-panel: rgba(255, 255, 255, 0.03);
--activity-card: rgba(255, 255, 255, 0.04);
--activity-border: rgba(255, 255, 255, 0.08);
--activity-muted: rgba(255, 255, 255, 0.58);
--activity-accent: rgba(255, 255, 255, 0.82);
--activity-accent-soft: rgba(255, 255, 255, 0.1);
--activity-warning: #b9986a;
--activity-tag: rgba(255, 255, 255, 0.06);
}
.activities-shell {
margin-top: 2.5rem;
padding: 0;
background: transparent;
border: none;
border-radius: 0;
box-shadow: none;
}
.activities-header {
display: flex;
flex-wrap: wrap;
gap: 2rem;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 2.5rem;
}
.activities-kicker {
letter-spacing: 0.14em;
text-transform: uppercase;
font-size: 0.62rem;
color: var(--activity-muted);
margin-bottom: 0.6rem;
}
.activities-title {
margin-top: 0;
margin-bottom: 0.8rem;
font-size: clamp(1.7rem, 2vw + 1.2rem, 2.4rem);
}
.activities-lead {
max-width: 38rem;
color: var(--activity-muted);
}
.activities-actions {
display: flex;
flex-wrap: wrap;
gap: 0.8rem;
align-items: center;
}
.activities-actions .button {
background: transparent;
border: 1px solid var(--activity-border);
color: #e7e9ec;
padding: 0.45rem 0.9rem;
border-radius: 999px;
transition: all 0.2s ease;
}
.activities-actions .button:hover {
border-color: rgba(255, 255, 255, 0.22);
color: #f5f7fa;
}
.activities-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.25rem;
}
.activity-card {
border-radius: 12px;
padding: 1.25rem;
background: var(--activity-card);
border: 1px solid var(--activity-border);
position: relative;
overflow: hidden;
min-height: 210px;
display: flex;
flex-direction: column;
gap: 0.8rem;
transition: border-color 0.2s ease;
}
.activity-card:hover {
border-color: rgba(255, 255, 255, 0.18);
}
.activity-card h3 {
margin: 0;
font-size: 1.1rem;
}
.activity-card p {
margin: 0;
color: var(--activity-muted);
font-size: 0.92rem;
}
.activity-head {
display: flex;
justify-content: space-between;
align-items: center;
gap: 0.5rem;
}
.activity-status {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-size: 0.7rem;
padding: 0.18rem 0.5rem;
border-radius: 999px;
background: rgba(255, 255, 255, 0.12);
color: rgba(255, 255, 255, 0.8);
}
.activity-status::before {
content: "●";
font-size: 0.6rem;
}
.activity-status.status-closed {
background: rgba(185, 152, 106, 0.25);
color: var(--activity-warning);
}
.activity-status.status-cooking {
background: green;
color: #f5f7fa;
}
.activity-meta {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
font-size: 0.75rem;
color: var(--activity-muted);
}
.activity-tags {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
}
.activity-tags .activity-tag:nth-child(n + 3) {
display: none;
}
.activity-tag {
padding: 0.2rem 0.5rem;
border-radius: 999px;
background: var(--activity-tag);
color: #d5d9e0;
font-size: 0.68rem;
}
.activity-link {
margin-top: auto;
color: #f5f7fa;
font-weight: 600;
text-decoration: none;
}
.activity-link:hover {
text-decoration: underline;
}
.activities-section {
margin-bottom: 2.5rem;
}
.activities-section-head {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
gap: 0.8rem;
margin-bottom: 1.2rem;
}
.activities-section-head h3 {
margin: 0;
font-size: 1.05rem;
}
.activities-section-head p {
margin: 0;
color: var(--activity-muted);
font-size: 0.88rem;
}
.activities-ideas {
list-style: none;
margin: 0;
padding: 0;
display: grid;
gap: 0.75rem;
}
.activities-idea {
padding: 0.75rem 0.9rem;
border-radius: 10px;
border: 1px solid var(--activity-border);
background: var(--activity-panel);
display: flex;
flex-wrap: wrap;
gap: 0.6rem 1rem;
justify-content: space-between;
align-items: center;
color: #e0e5ea;
font-size: 0.92rem;
}
.activities-idea a {
color: #f5f7fa;
font-weight: 600;
text-decoration: none;
}
.activities-idea a:hover {
text-decoration: underline;
}
.activities-footer {
margin-top: 2.4rem;
padding: 1.4rem 1.6rem;
border-radius: 16px;
background: var(--activity-panel);
border: 1px solid var(--activity-border);
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.activities-footer p {
margin: 0;
color: var(--activity-muted);
}
.activities-footer .button {
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.22);
color: #f5f7fa;
padding: 0.5rem 1.1rem;
border-radius: 999px;
}
.skeleton {
position: relative;
overflow: hidden;
}
.skeleton::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(110deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.08));
animation: shimmer 1.8s infinite;
}
@keyframes shimmer {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
.activities-empty {
grid-column: 1 / -1;
padding: 1.5rem;
text-align: center;
background: var(--activity-panel);
border-radius: 12px;
border: 1px dashed var(--activity-border);
color: var(--activity-muted);
}
.activities-fallback {
margin-top: 1.2rem;
padding: 1rem 1.2rem;
border-radius: 12px;
border: 1px solid var(--activity-border);
color: var(--activity-muted);
font-size: 0.9rem;
}
.activities-fallback a {
color: #f5f7fa;
}
@media (max-width: 720px) {
.activities-shell {
padding: 0;
}
.activities-actions {
width: 100%;
}
.activities-actions .button {
width: 100%;
text-align: center;
}
.activities-idea {
flex-direction: column;
align-items: flex-start;
}
.activities-footer {
flex-direction: column;
align-items: flex-start;
}
}

View File

@@ -3,12 +3,17 @@ title: Welcome
---
## About us
Have you ever been curious about Linux and don't know where to begin with?
Do you want to know more about open source?
Are you interested in technology and the way software shapes our everyday lives?
Do you want to contribute to the cause?
Do you want to support the cause?
Welcome to OpenBokeron! 👋
Would you like to discover free and ethical alternatives to the proprietary software we use every day?
We're a group of students from the ETSII (UMA) that promotes free software.
Would you like to learn, share knowledge and take part in open projects?
Welcome to Open Bokeron! 👋
We are an association of students from the School of Computer Engineering at the University of Málaga, dedicated to promoting free software and open-source software, fostering a more open, accessible and collaborative approach to technology.
We encourage the use of free tools, raise awareness of alternatives to proprietary software, and create a space where people can learn, experiment and contribute, regardless of their technical background or prior experience.

View File

@@ -0,0 +1,42 @@
---
title: Activities in progress
---
See what we are preparing and the current status of each proposal. Everything lives in our public Gitea board.
<div class="activities-shell" data-activities-root>
<header class="activities-header">
<div class="activities-actions">
<a class="button" href="https://openbokeron.uma.es/gitea/OpenBokeron/-/projects/5" target="_blank" rel="noopener">View board</a>
<a class="button" href="https://openbokeron.uma.es/gitea/OpenBokeron/Actividades/issues" target="_blank" rel="noopener">View issues</a>
</div>
</header>
<section class="activities-section" data-activities-working>
<div class="activities-section-head">
<h3>In development</h3>
</div>
<div class="activities-grid" data-activities-grid>
<article class="activity-card skeleton">
<div class="activity-head">
<span class="activity-status">Loading</span>
</div>
<h3>Loading...</h3>
</article>
</div>
</section>
<section class="activities-section" data-activities-ideas>
<div class="activities-section-head">
<h3>Backlog</h3>
</div>
<ul class="activities-ideas" data-activities-ideas-list>
<li class="activities-idea skeleton">Loading...</li>
</ul>
</section>
<footer class="activities-footer">
<p>Looking for past activities? You will find them in the Projects tab.</p>
<p>Want to propose something new? Drop by the Contact tab, we do not bite.</p>
</footer>
</div>

View File

@@ -0,0 +1,22 @@
---
title: Participation in Podcasteando con amigos
description: We took part in a live episode about cybersecurity and digital privacy.
image: assets/podcast/cartel.jpg
date: 2026-01-10T11:30:00+01:00
place: Libreria Luces (Malaga)
finished: true
---
# Podcasteando con amigos podcast
We participated in a live episode to talk about cybersecurity and digital privacy.
You can see the announcement in the post: [Podcasteando con amigos](/posts/podcast/).
Podcast website: https://www.podcasteando.es
Instagram: https://www.instagram.com/podcasteandoconamigos
![First image](/assets/podcast/podcast1.jpg)
![Second image](/assets/podcast/podcast2.jpg)
YouTube reupload link: [YouTube](https://www.youtube.com/live/bVM5rPlCPBM)

View File

@@ -3,13 +3,15 @@ title: Bienvenido
---
## Sobre nosotros
¿Has tenido curiosidad sobre Linux y no sabes por dónde empezar?
¿Quieres conocer más sobre el software libre?
¿Te interesa la tecnología y la forma en la que el software influye en nuestro día a día?
¿Quieres aportar a la causa?
¿Quieres descubrir alternativas libres y éticas al software propietario que usamos a diario?
¿Te gustaría aprender, compartir conocimientos y participar en proyectos abiertos?
¡Bienvenido a Open Bokeron! 👋
Somos un grupo de estudiantes de la ETSI Informática de la UMA que nos dedicamos a
promocionar el software libre.
Somos una asociación de estudiantes de la ETSI Informática de la Universidad de Málaga dedicada a promover el software libre y el código abierto, fomentando una tecnología más abierta, accesible y colaborativa.
Impulsamos el uso de herramientas libres, damos a conocer alternativas al software propietario y creamos un espacio donde aprender, experimentar y contribuir, independientemente de tu nivel técnico o experiencia previa.

View File

@@ -0,0 +1,42 @@
---
title: Actividades en marcha
---
Descubre lo que estamos preparando y en qué punto está cada propuesta. Todo esto se coordina en nuestro tablero público de Gitea.
<div class="activities-shell" data-activities-root>
<header class="activities-header">
<div class="activities-actions">
<a class="button" href="https://openbokeron.uma.es/gitea/OpenBokeron/-/projects/5" target="_blank" rel="noopener">Ver tablero</a>
<a class="button" href="https://openbokeron.uma.es/gitea/OpenBokeron/Actividades/issues" target="_blank" rel="noopener">Ver issues</a>
</div>
</header>
<section class="activities-section" data-activities-working>
<div class="activities-section-head">
<h3>En desarrollo</h3>
</div>
<div class="activities-grid" data-activities-grid>
<article class="activity-card skeleton">
<div class="activity-head">
<span class="activity-status">Cargando</span>
</div>
<h3>Cargando...</h3>
</article>
</div>
</section>
<section class="activities-section" data-activities-ideas>
<div class="activities-section-head">
<h3>En el tintero</h3>
</div>
<ul class="activities-ideas" data-activities-ideas-list>
<li class="activities-idea skeleton">Cargando...</li>
</ul>
</section>
<footer class="activities-footer">
<p> ¿Buscas las Actividades ya realizadas? Las tienes en la pestaña de Proyectos ;) </p>
<p>¿Quieres proponer algo nuevo? Pásate por la pestaña Contacto, no mordemos.</p>
</footer>
</div>

View File

@@ -0,0 +1,22 @@
---
title: 'Participación en Podcasteando con amigos'
description: 'Participamos en un episodio en directo sobre ciberseguridad y privacidad digital.'
image: 'assets/podcast/cartel.jpg'
date: 2026-01-10T11:30:00+01:00
place: 'Librería Luces (Málaga)'
finished: true
---
# Podcast con Podcasteando con amigos
Participamos en un episodio en directo para hablar de ciberseguridad y privacidad digital.
Puedes ver el anuncio en el post: [Podcasteando con amigos](/posts/podcast/).
Web del podcast: https://www.podcasteando.es
Instagram: https://www.instagram.com/podcasteandoconamigos
![Primera imagen](/assets/podcast/podcast1.jpg)
![Segunda imagen](/assets/podcast/podcast2.jpg)
Enlace al resubido en YouTube: [YouTube](https://www.youtube.com/live/bVM5rPlCPBM)

View File

@@ -1,5 +1,5 @@
baseURL = 'https://openbokeron.uma.es'
title = 'OpenBokeron'
title = 'Open Bokeron'
timeZone = 'Europe/Madrid'
@@ -34,6 +34,12 @@ buildFuture = true
url = "/en/projects"
weight = 30
[[languages.en.menu.main]]
identifier = "activities"
name = "Activities"
url = "/en/activities"
weight = 35
[[languages.en.menu.main]]
identifier = "contact"
name = "Contact"
@@ -65,6 +71,12 @@ buildFuture = true
url = "/es/projects"
weight = 30
[[languages.es.menu.main]]
identifier = "activities"
name = "Actividades"
url = "/es/activities"
weight = 35
[[languages.es.menu.main]]
identifier = "contact"
name = "Contacto"
@@ -76,3 +88,8 @@ buildFuture = true
[params]
[params.social]
twitter = 'OpenBokeron'
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="{{ or site.Language.LanguageCode site.Language.Lang }}" dir="{{ or site.Language.LanguageDirection `ltr` }}">
<html lang="{{ or site.Language.LanguageCode site.Language.Lang }}"
dir="{{ or site.Language.LanguageDirection `ltr` }}">
<head>
{{ partial "head.html" . -}}
@@ -15,6 +16,9 @@
<footer>
{{ partial "footer.html" . -}}
</footer>
{{ if eq .Section "activities" }}
<script src="/assets/js/activities.js" defer></script>
{{ end }}
</body>
</html>

View File

@@ -1,4 +1,4 @@
<p>&#127279; 2024 Open Bokeron.</p>
<p>&#127279; 2024-2026 Open Bokeron.</p>
<p>
Made with <span style="color: #e25555;">&#9829;</span> in
<a href="https://openbokeron.uma.es/gitea/OpenBokeron/Web">Gitea</a>

View File

@@ -0,0 +1,235 @@
const ACTIVITIES_CONFIG = {
apiBase: "https://openbokeron.uma.es/gitea/api/v1",
repo: "OpenBokeron/Actividades",
state: "open",
};
const ACTIVITY_LABELS = {
cooking: "cocinando",
};
const ACTIVITY_BADGES = {
es: {
cooking: "Cocinando",
},
en: {
cooking: "Cooking",
},
};
const ACTIVITY_BADGE_STYLE = {
cooking: "status-cooking",
};
const ACTIVITY_CTA = {
es: "Ver en Gitea",
en: "View on Gitea",
};
const ACTIVITY_EMPTY = {
es: "Ahora mismo no hay actividades abiertas. Vuelve pronto o mira el tablero completo.",
en: "There are no open activities right now. Come back soon or check the full board.",
};
const FALLBACK_TEXT = {
es: "Oops, la hemos liado al querer cargar el tablero. Puedes verlo directamente en Gitea:",
en: "Oops, we messed up while trying to load the board. You can still open it in Gitea:",
};
const FALLBACK_LINK = {
es: "Abrir tablero",
en: "Open board",
};
const LANGUAGE_LABELS = {
es: {
milestone: "Hito",
comments: "comentarios",
updated: "Actualizado",
noCooking: "No hay actividades en desarrollo. Mira el tablero completo.",
noIdeas: "No hay ideas nuevas ahora mismo.",
},
en: {
milestone: "Milestone",
comments: "comments",
updated: "Updated",
noCooking: "No activities in development. Check the full board.",
noIdeas: "There are no new ideas right now.",
},
};
const escapeHtml = (value) => {
if (value === null || value === undefined) {
return "";
}
return String(value).replace(/[&<>"']/g, (char) => {
const map = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#39;",
};
return map[char] || char;
});
};
const container = document.querySelector("[data-activities-root]");
if (container) {
const grid = container.querySelector("[data-activities-grid]");
const lang = document.documentElement.lang.startsWith("es") ? "es" : "en";
const labels = LANGUAGE_LABELS[lang];
const fetchActivities = async () => {
const url = `${ACTIVITIES_CONFIG.apiBase}/repos/${ACTIVITIES_CONFIG.repo}/issues?state=${ACTIVITIES_CONFIG.state}`;
const response = await fetch(url, {
headers: {
Accept: "application/json",
},
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
return response.json();
};
const formatDate = (value) => {
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return value;
}
return new Intl.DateTimeFormat(lang, {
year: "numeric",
month: "short",
day: "numeric",
}).format(date);
};
const getLabelNames = (issue) => (issue.labels || []).map((label) => label.name.toLowerCase());
const hasLabel = (issue, label) => getLabelNames(issue).includes(label);
const renderTags = (tags) => {
if (!tags || tags.length === 0) {
return "";
}
return tags
.filter((label) => label.name.toLowerCase() !== ACTIVITY_LABELS.cooking)
.slice(0, 3)
.map((label) => `<span class="activity-tag">${label.name}</span>`)
.join("");
};
const getBadge = (issue) => {
if (hasLabel(issue, ACTIVITY_LABELS.cooking)) {
return {
text: ACTIVITY_BADGES[lang].cooking,
className: ACTIVITY_BADGE_STYLE.cooking,
};
}
return null;
};
const renderActivity = (issue) => {
const tags = renderTags(issue.labels);
const milestone = issue.milestone?.title;
const updated = formatDate(issue.updated_at);
const badge = getBadge(issue);
const comments = issue.comments || 0;
return `
<article class="activity-card">
<div class="activity-head">
${badge ? `<span class="activity-status ${badge.className}">${badge.text}</span>` : ""}
</div>
<h3>${escapeHtml(issue.title)}</h3>
<p>${issue.body ? escapeHtml(issue.body.replace(/\s+/g, " ").slice(0, 140) + "...") : ""}</p>
<div class="activity-meta">
<span>${labels.updated} ${updated}</span>
<span>${comments} ${labels.comments}</span>
<span>#${issue.number}</span>
</div>
${milestone ? `<div class="activity-meta">${labels.milestone}: ${milestone}</div>` : ""}
${tags ? `<div class="activity-tags">${tags}</div>` : ""}
<a class="activity-link" href="${issue.html_url}" target="_blank" rel="noopener">${ACTIVITY_CTA[lang]}</a>
</article>
`;
};
const renderIdeas = (ideas) => {
const ideasList = container.querySelector("[data-activities-ideas-list]");
if (!ideasList) {
return;
}
if (!ideas || ideas.length === 0) {
ideasList.innerHTML = `<li class="activities-idea">${labels.noIdeas}</li>`;
return;
}
ideasList.innerHTML = ideas
.map(
(issue) => `
<li class="activities-idea">
<div>
<strong>${escapeHtml(issue.title)}</strong>
<span class="activity-meta">#${issue.number}</span>
</div>
<a href="${issue.html_url}" target="_blank" rel="noopener">${ACTIVITY_CTA[lang]}</a>
</li>
`
)
.join("");
};
const renderActivities = (issues) => {
if (!issues || issues.length === 0) {
grid.innerHTML = `<div class="activities-empty">${ACTIVITY_EMPTY[lang]}</div>`;
renderIdeas([]);
return;
}
const cooking = issues.filter((issue) => hasLabel(issue, ACTIVITY_LABELS.cooking));
const ideas = issues.filter((issue) => !hasLabel(issue, ACTIVITY_LABELS.cooking));
const cookingTitles = new Set(cooking.map((issue) => issue.title));
const filteredIdeas = ideas.filter((issue) => !cookingTitles.has(issue.title));
if (cooking.length === 0) {
grid.innerHTML = `<div class="activities-empty">${labels.noCooking}</div>`;
} else {
grid.innerHTML = cooking.map(renderActivity).join("");
}
renderIdeas(filteredIdeas);
};
const renderFallback = () => {
grid.innerHTML = `
<div class="activities-empty">
${FALLBACK_TEXT[lang]}
<a href="https://openbokeron.uma.es/gitea/OpenBokeron/-/projects/5" target="_blank" rel="noopener">${FALLBACK_LINK[lang]}</a>
</div>
`;
const ideasList = container.querySelector("[data-activities-ideas-list]");
if (ideasList) {
ideasList.innerHTML = `<li class="activities-idea">${labels.noIdeas}</li>`;
}
};
fetchActivities()
.then((issues) => {
const sorted = [...issues].sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at));
renderActivities(sorted);
})
.catch(() => {
renderFallback();
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB