forked from OpenBokeron/Web
Compare commits
11 Commits
main
...
web/main-2
| Author | SHA1 | Date | |
|---|---|---|---|
| dc97c1d67a | |||
| ea2777dee1 | |||
| 247efcb058 | |||
| 050fd7dcce | |||
| b451fdfaf2 | |||
| 58cb5fb5ee | |||
| d4b972cc4e | |||
| 326e76aac4 | |||
| 66027471f6 | |||
| 2d509e352d | |||
| f6ed158b0f |
@@ -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)
|
||||
|
||||
@@ -10,3 +10,368 @@ img.icon {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
.forum-banner {
|
||||
margin: 3rem 0 2.5rem;
|
||||
padding: 2rem 1.25rem 1.5rem;
|
||||
background: #2a2a2a;
|
||||
border: 1px solid #3a3a3a;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
|
||||
.forum-banner__content {
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.forum-banner h3 {
|
||||
padding: 1rem 1rem 1rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.forum-banner p {
|
||||
margin-top: 0;
|
||||
color: #cfcfcf;
|
||||
}
|
||||
|
||||
|
||||
.forum-banner__button {
|
||||
display: inline-block;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
background: #1faa00;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
42
content/en/activities/_index.md
Normal file
42
content/en/activities/_index.md
Normal 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>
|
||||
@@ -6,15 +6,41 @@ title: Contact
|
||||
If you are at the ETSII of the University of Malaga (UMA), don't hesitate to look for us! OpenBokeron members
|
||||
are easy to find in the hallways, classrooms and laboratories.
|
||||
|
||||
No luck meeting us in person? Don't worry! You can always contact us through email
|
||||
Haven’t managed to find us in person? No worries — there are several ways to get in touch and take part in the community.
|
||||
|
||||
---
|
||||
|
||||
## Ways to participate
|
||||
|
||||
#### 💬 Community forum
|
||||
We have created a forum as the main meeting point for the community: to share ideas, ask questions,
|
||||
organize activities, or simply introduce yourself.
|
||||
|
||||
https://openbokeron.org/flarum
|
||||
|
||||
This is the best place to start if you’re not sure where to begin.
|
||||
|
||||
---
|
||||
|
||||
#### 📢 Telegram
|
||||
We also have a Telegram group where the community has been chatting informally for a long time, in real time.
|
||||
|
||||
https://t.me/+-0oloTKiIo00ZmM0
|
||||
|
||||
Ideal for quick conversations or keeping up with what’s happening.
|
||||
|
||||
#### ✉️ Email
|
||||
If you prefer a more direct or private way of contacting us, you can email us at:
|
||||
|
||||
[openbokeron@geeklab.es](mailto:openbokeron@geeklab.es)
|
||||
|
||||
We'd be happy to answer your questions, get suggestions, or just chat about free software!
|
||||
---
|
||||
|
||||
### Our social media
|
||||
Don't miss the latest news, events and projects from Open Bokeron on Twitter!
|
||||
Follow us on our account [@OpenBokeron](https://twitter.com/OpenBokeron)
|
||||
#### 🐦 Social media
|
||||
We share news, events, and updates on our X (formerly Twitter) account:
|
||||
|
||||
Here we share real-time updates, curiosities and everything related to the world of free software.
|
||||
https://twitter.com/OpenBokeron
|
||||
|
||||
You can also talk to our community using Telegram with [this link](https://t.me/+-0oloTKiIo00ZmM0)
|
||||
---
|
||||
|
||||
We’ll be happy to answer your questions, receive suggestions, or just chat about free software!
|
||||
|
||||
19
content/en/posts/forum.md
Normal file
19
content/en/posts/forum.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "We have launched the Open Bokeron community forum"
|
||||
description: "We have created a forum to make participation easier and bring the community to life."
|
||||
date: 2026-01-25T12:00:00+01:00
|
||||
---
|
||||
|
||||
We have launched a **community forum** for Open Bokeron to make participation easier and create a more welcoming space for discussion and collaboration.
|
||||
|
||||
The forum is intended as an informal meeting point where anyone can:
|
||||
- Introduce themselves and meet other members
|
||||
- Suggest workshops, talks, or projects
|
||||
- Ask for help or share knowledge
|
||||
- Discuss free software, privacy, and technology in general
|
||||
|
||||
👉 **You can access the forum here:**
|
||||
https://openbokeron.org/flarum
|
||||
|
||||
If you’re not sure where to start, just drop by and say hello.
|
||||
Everyone is welcome!
|
||||
42
content/es/activities/_index.md
Normal file
42
content/es/activities/_index.md
Normal 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>
|
||||
@@ -7,18 +7,42 @@ Si te encuentras en la Escuela Técnica Superior de Ingeniería Informática y T
|
||||
(UMA), ¡no dudes en buscarnos! Los miembros de Open Bokeron
|
||||
son fáciles de encontrar por los pasillos, aulas y laboratorios.
|
||||
|
||||
¿No has tenido ocasión de encontrarnos en persona? No pasa nada: hay varias formas de ponerte en contacto y participar en la comunidad.
|
||||
|
||||
¿No has tenido suerte encontrándonos en persona? ¡No te preocupes! Siempre puedes ponerte en contacto con
|
||||
nosotros a través de nuestro correo electrónico [openbokeron@geeklab.es](mailto:openbokeron@geeklab.es)
|
||||
---
|
||||
|
||||
¡Estaremos encantados de responder a tus preguntas, recibir tus sugerencias o simplemente charlar sobre software libre!
|
||||
## Formas de participar
|
||||
|
||||
### Nuestras redes sociales
|
||||
¡No te pierdas las últimas noticias, eventos y proyectos de Open Bokeron en Twitter! Síguenos en nuestra cuenta
|
||||
oficial [@OpenBokeron](https://twitter.com/OpenBokeron)
|
||||
#### 💬 Foro de la comunidad
|
||||
Hemos creado un foro como punto de encuentro principal para la comunidad: proponer ideas, hacer preguntas o simplemente presentarte.
|
||||
|
||||
Aquí compartimos actualizaciones en tiempo real, curiosidades y todo lo relacionado con el mundo del software libre.
|
||||
https://openbokeron.org/flarum
|
||||
|
||||
También puedes charlar con nosotros y toda la comunidad open source usando Telegram con [este enlace](https://t.me/+-0oloTKiIo00ZmM0)
|
||||
Es el mejor sitio para empezar si no sabes por dónde.
|
||||
|
||||
¡Os esperamos!
|
||||
---
|
||||
|
||||
#### 📢 Telegram
|
||||
Disponemos de un grupo de Telegram donde la comunidad lleva tiempo charlando de forma más informal y en tiempo real.
|
||||
|
||||
https://t.me/+-0oloTKiIo00ZmM0
|
||||
|
||||
Ideal para conversaciones rápidas o estar al tanto de lo que va surgiendo.
|
||||
|
||||
---
|
||||
|
||||
#### ✉️ Correo electrónico
|
||||
Si prefieres un contacto más directo o privado, puedes escribirnos a:
|
||||
|
||||
[openbokeron@geeklab.es](mailto:openbokeron@geeklab.es)
|
||||
|
||||
---
|
||||
|
||||
#### 🐦 Redes sociales
|
||||
Compartimos noticias, eventos y actualizaciones en nuestra cuenta de Twitter:
|
||||
|
||||
https://twitter.com/OpenBokeron
|
||||
|
||||
---
|
||||
|
||||
¡Estaremos encantados de responder a tus preguntas, recibir sugerencias o simplemente charlar sobre software libre!
|
||||
|
||||
19
content/es/posts/foro.md
Normal file
19
content/es/posts/foro.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "Abrimos el foro de Open Bokeron"
|
||||
description: "Hemos creado un foro para facilitar la participación y dar vida a la comunidad."
|
||||
date: 2026-01-25T12:00:00+01:00
|
||||
---
|
||||
|
||||
En Open Bokeron hemos puesto en marcha un **foro de la comunidad** con el objetivo de facilitar la participación y crear un espacio más cercano donde charlar, proponer ideas y organizar actividades.
|
||||
|
||||
El foro está pensado como un punto de encuentro informal, donde cualquiera puede:
|
||||
- Presentarse y conocer a otras personas de la asociación
|
||||
- Proponer talleres, charlas o proyectos
|
||||
- Pedir ayuda o resolver dudas
|
||||
- Comentar sobre software libre, privacidad y tecnología en general
|
||||
|
||||
👉 **Puedes acceder al foro aquí:**
|
||||
https://openbokeron.org/flarum
|
||||
|
||||
Si te apetece participar pero no sabes por dónde empezar, pásate por el foro y saluda.
|
||||
¡Toda aportación es bienvenida!
|
||||
17
hugo.toml
17
hugo.toml
@@ -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
|
||||
|
||||
@@ -4,3 +4,6 @@ motto = "Free your source, free your mind"
|
||||
# Project
|
||||
finished = "Finished"
|
||||
unfinished = "Ongoing"
|
||||
forumTitle = "New: Community forum"
|
||||
forumDesc = "We have created a forum to make participation easier. Come say hello!"
|
||||
forumBtn = "Go to the forum"
|
||||
|
||||
@@ -2,3 +2,6 @@ motto = "Libera tu código, libera tu mente"
|
||||
|
||||
finished = "Finalizado"
|
||||
unfinished = "En progreso"
|
||||
forumTitle = "Nuevo: Foro de la comunidad"
|
||||
forumDesc = "Hemos creado un foro para que sea más fácil participar. ¡Pásate y saluda!"
|
||||
forumBtn = "Entrar al foro"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{{ define "main" }}
|
||||
{{ .Content }}
|
||||
{{ partial "forum-banner.html" . }}
|
||||
{{ .Content }}
|
||||
{{ end }}
|
||||
|
||||
7
layouts/partials/forum-banner.html
Normal file
7
layouts/partials/forum-banner.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<section class="forum-banner">
|
||||
<div class="forum-banner__content">
|
||||
<h3>{{ i18n "forumTitle" }}</h3>
|
||||
<p>{{ i18n "forumDesc" }}</p>
|
||||
<a class="forum-banner__button" href="/flarum">{{ i18n "forumBtn" }}</a>
|
||||
</div>
|
||||
</section>
|
||||
235
static/assets/js/activities.js
Normal file
235
static/assets/js/activities.js
Normal 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 = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
'"': """,
|
||||
"'": "'",
|
||||
};
|
||||
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();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user