mirror of
https://github.com/Ocelot-Social-Community/ocelot.social.git
synced 2026-04-06 01:25:18 +00:00
422 lines
11 KiB
Vue
422 lines
11 KiB
Vue
<template>
|
|
<div class="roadmap">
|
|
<div class="roadmap-legend">
|
|
<span class="roadmap-legend-item">
|
|
<span class="roadmap-legend-dot roadmap-legend-dot--done"></span> {{ t.done }}
|
|
</span>
|
|
<span class="roadmap-legend-item">
|
|
<span class="roadmap-legend-dot roadmap-legend-dot--in-progress"></span> {{ t.inProgress }}
|
|
</span>
|
|
<span class="roadmap-legend-item">
|
|
<span class="roadmap-legend-dot roadmap-legend-dot--planned"></span> {{ t.planned }}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="roadmap-timeline">
|
|
<div
|
|
v-for="(item, index) in items"
|
|
:key="item.id"
|
|
class="roadmap-station"
|
|
:class="'roadmap-station--' + item.status"
|
|
>
|
|
<!-- Durchgehende Linie von diesem Marker zum nächsten -->
|
|
<div v-if="index < items.length - 1" class="roadmap-connector" :class="'roadmap-connector--' + connectorColor(index)"></div>
|
|
|
|
<!-- Station-Marker -->
|
|
<div class="roadmap-marker" :class="'roadmap-marker--' + item.status">
|
|
<span v-if="item.status === 'done'" class="roadmap-marker-icon">✓</span>
|
|
<span v-else-if="item.status === 'in-progress'" class="roadmap-marker-pulse"></span>
|
|
</div>
|
|
|
|
<!-- Inhalt -->
|
|
<div class="roadmap-content">
|
|
<div class="roadmap-content-header">
|
|
<strong class="roadmap-content-title">{{ item.title[locale] }}</strong>
|
|
<span class="roadmap-content-badge" :class="'roadmap-content-badge--' + item.status">
|
|
{{ statusLabel(item.status) }}
|
|
</span>
|
|
</div>
|
|
<p class="roadmap-content-description">{{ item.description[locale] }}</p>
|
|
<div v-if="item.issues && item.issues.length" class="roadmap-content-issues">
|
|
<a
|
|
v-for="issue in item.issues"
|
|
:key="issue"
|
|
:href="'https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/' + issue"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
>#{{ issue }}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { useRouteLocale } from "vuepress/client"
|
|
|
|
const stripSlashes = s => s.replace(/^\/+|\/+$/g, '')
|
|
const locale = stripSlashes(useRouteLocale().value) || 'de'
|
|
|
|
const items = [
|
|
{
|
|
id: 1,
|
|
title: {
|
|
de: 'Gruppen-Chat',
|
|
en: 'Group Chat',
|
|
es: 'Chat de grupo',
|
|
fr: 'Chat de groupe',
|
|
},
|
|
description: {
|
|
de: 'Chaträume für Gruppen, damit Mitglieder in Echtzeit miteinander kommunizieren können.',
|
|
en: 'Chat rooms for groups so members can communicate with each other in real time.',
|
|
es: 'Salas de chat para grupos para que los miembros puedan comunicarse en tiempo real.',
|
|
fr: 'Salons de discussion pour les groupes afin que les membres puissent communiquer en temps réel.',
|
|
},
|
|
status: 'done',
|
|
issues: [],
|
|
},
|
|
{
|
|
id: 2,
|
|
title: {
|
|
de: 'Vue 2 → Vue 3 Migration',
|
|
en: 'Vue 2 → Vue 3 Migration',
|
|
es: 'Migración de Vue 2 → Vue 3',
|
|
fr: 'Migration Vue 2 → Vue 3',
|
|
},
|
|
description: {
|
|
de: 'Migration des Frontends auf Vue 3 für bessere Performance und Zukunftssicherheit.',
|
|
en: 'Migration of the frontend to Vue 3 for better performance and future-proofing.',
|
|
es: 'Migración del frontend a Vue 3 para un mejor rendimiento y preparación para el futuro.',
|
|
fr: 'Migration du frontend vers Vue 3 pour de meilleures performances et une pérennité assurée.',
|
|
},
|
|
status: 'in-progress',
|
|
issues: [6384],
|
|
},
|
|
{
|
|
id: 3,
|
|
title: {
|
|
de: 'Veranstaltungen verbessern',
|
|
en: 'Improve Events',
|
|
es: 'Mejorar eventos',
|
|
fr: 'Améliorer les événements',
|
|
},
|
|
description: {
|
|
de: 'Erweiterte Veranstaltungsfunktionen wie Teilnehmerlisten, Kalenderintegration und Erinnerungen.',
|
|
en: 'Enhanced event features such as attendee lists, calendar integration, and reminders.',
|
|
es: 'Funciones avanzadas de eventos como listas de asistentes, integración de calendario y recordatorios.',
|
|
fr: 'Fonctionnalités avancées pour les événements : listes de participants, intégration de calendrier et rappels.',
|
|
},
|
|
status: 'planned',
|
|
issues: [],
|
|
},
|
|
{
|
|
id: 4,
|
|
title: {
|
|
de: 'SSO / LDAP / SAML',
|
|
en: 'SSO / LDAP / SAML',
|
|
es: 'SSO / LDAP / SAML',
|
|
fr: 'SSO / LDAP / SAML',
|
|
},
|
|
description: {
|
|
de: 'Single Sign-On-Anbindung für Organisationen mit bestehender Benutzerverwaltung.',
|
|
en: 'Single sign-on integration for organizations with existing user management.',
|
|
es: 'Integración de inicio de sesión único para organizaciones con gestión de usuarios existente.',
|
|
fr: 'Intégration de l\'authentification unique pour les organisations disposant d\'une gestion des utilisateurs existante.',
|
|
},
|
|
status: 'planned',
|
|
issues: [3200],
|
|
},
|
|
{
|
|
id: 5,
|
|
title: {
|
|
de: 'Push-Benachrichtigungen',
|
|
en: 'Push Notifications',
|
|
es: 'Notificaciones push',
|
|
fr: 'Notifications push',
|
|
},
|
|
description: {
|
|
de: 'Sofortige Benachrichtigungen auf dem Gerät bei neuen Beiträgen, Kommentaren oder Nachrichten.',
|
|
en: 'Instant notifications on your device for new posts, comments, or messages.',
|
|
es: 'Notificaciones instantáneas en el dispositivo para nuevas publicaciones, comentarios o mensajes.',
|
|
fr: 'Notifications instantanées sur l\'appareil pour les nouvelles publications, commentaires ou messages.',
|
|
},
|
|
status: 'planned',
|
|
issues: [4327],
|
|
},
|
|
{
|
|
id: 6,
|
|
title: {
|
|
de: 'Gruppenverwaltung (Löschung, Moderation)',
|
|
en: 'Group Management (Deletion, Moderation)',
|
|
es: 'Gestión de grupos (eliminación, moderación)',
|
|
fr: 'Gestion des groupes (suppression, modération)',
|
|
},
|
|
description: {
|
|
de: 'Erweiterte Verwaltungsfunktionen für Gruppen, einschließlich Löschung und Moderationswerkzeuge.',
|
|
en: 'Advanced management features for groups, including deletion and moderation tools.',
|
|
es: 'Funciones avanzadas de gestión de grupos, incluyendo eliminación y herramientas de moderación.',
|
|
fr: 'Fonctionnalités avancées de gestion des groupes, y compris la suppression et les outils de modération.',
|
|
},
|
|
status: 'planned',
|
|
issues: [5388, 7702],
|
|
},
|
|
{
|
|
id: 7,
|
|
title: {
|
|
de: 'Beitrags-Sichtbarkeit & Entwürfe',
|
|
en: 'Post Visibility & Drafts',
|
|
es: 'Visibilidad de publicaciones y borradores',
|
|
fr: 'Visibilité des publications et brouillons',
|
|
},
|
|
description: {
|
|
de: 'Beiträge als Entwurf speichern und die Sichtbarkeit einzelner Beiträge steuern.',
|
|
en: 'Save posts as drafts and control the visibility of individual posts.',
|
|
es: 'Guardar publicaciones como borradores y controlar la visibilidad de publicaciones individuales.',
|
|
fr: 'Enregistrer des publications comme brouillons et contrôler la visibilité des publications individuelles.',
|
|
},
|
|
status: 'planned',
|
|
issues: [2198, 4965],
|
|
},
|
|
]
|
|
|
|
const i18n = {
|
|
de: { done: 'Erledigt', inProgress: 'In Arbeit', planned: 'Geplant' },
|
|
en: { done: 'Done', inProgress: 'In Progress', planned: 'Planned' },
|
|
es: { done: 'Completado', inProgress: 'En curso', planned: 'Planificado' },
|
|
fr: { done: 'Terminé', inProgress: 'En cours', planned: 'Planifié' },
|
|
}
|
|
|
|
const t = i18n[locale] || i18n.de
|
|
|
|
const statusLabel = (status) => {
|
|
switch (status) {
|
|
case 'done': return t.done
|
|
case 'in-progress': return t.inProgress
|
|
case 'planned': return t.planned
|
|
default: return t.planned
|
|
}
|
|
}
|
|
|
|
// Farbe der Verbindungslinie zwischen Station[index] und Station[index+1]
|
|
const connectorColor = (index) => {
|
|
const current = items[index].status
|
|
const next = items[index + 1].status
|
|
if (current === 'done' && next === 'done') return 'done'
|
|
if (current === 'done' && next === 'in-progress') return 'to-active'
|
|
if (current === 'in-progress') return 'from-active'
|
|
return 'planned'
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.roadmap {
|
|
margin: 1.5rem 0;
|
|
}
|
|
|
|
/* === Legende === */
|
|
.roadmap-legend {
|
|
display: flex;
|
|
gap: 20px;
|
|
flex-wrap: wrap;
|
|
margin-bottom: 28px;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.roadmap-legend-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
color: var(--vp-c-text-2, #666);
|
|
}
|
|
|
|
.roadmap-legend-dot {
|
|
width: 12px;
|
|
height: 12px;
|
|
border-radius: 50%;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.roadmap-legend-dot--done {
|
|
background: #eab308;
|
|
}
|
|
|
|
.roadmap-legend-dot--in-progress {
|
|
background: #6366f1;
|
|
}
|
|
|
|
.roadmap-legend-dot--planned {
|
|
background: #059669;
|
|
}
|
|
|
|
/* === Timeline === */
|
|
.roadmap-timeline {
|
|
position: relative;
|
|
padding-left: 0;
|
|
}
|
|
|
|
.roadmap-station {
|
|
position: relative;
|
|
display: grid;
|
|
grid-template-columns: 24px 1fr;
|
|
grid-template-rows: auto;
|
|
column-gap: 20px;
|
|
min-height: 80px;
|
|
}
|
|
|
|
/* === Verbindungslinie zwischen Stationen === */
|
|
.roadmap-connector {
|
|
position: absolute;
|
|
left: 12px;
|
|
transform: translateX(-50%);
|
|
top: 28px;
|
|
bottom: -28px;
|
|
width: 3px;
|
|
z-index: 1;
|
|
}
|
|
|
|
.roadmap-connector--done,
|
|
.roadmap-connector--to-active,
|
|
.roadmap-connector--from-active,
|
|
.roadmap-connector--planned {
|
|
background: #34d399;
|
|
}
|
|
|
|
/* === Marker === */
|
|
.roadmap-marker {
|
|
grid-column: 1;
|
|
grid-row: 1;
|
|
align-self: start;
|
|
margin-top: 16px;
|
|
width: 24px;
|
|
height: 24px;
|
|
border-radius: 50%;
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: relative;
|
|
z-index: 2;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.roadmap-marker--done {
|
|
background: #eab308;
|
|
border: 3px solid #eab308;
|
|
color: #fff;
|
|
font-size: 14px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.roadmap-marker--in-progress {
|
|
background: #6366f1;
|
|
border: 3px solid #6366f1;
|
|
box-shadow: 0 0 0 5px rgba(99, 102, 241, 0.2);
|
|
}
|
|
|
|
.roadmap-marker-pulse {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
background: #fff;
|
|
animation: pulse 2s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0%, 100% { transform: scale(1); opacity: 1; }
|
|
50% { transform: scale(1.3); opacity: 0.6; }
|
|
}
|
|
|
|
.roadmap-marker--planned {
|
|
background: var(--vp-c-bg, #fff);
|
|
border: 3px solid #059669;
|
|
}
|
|
|
|
/* === Inhalt === */
|
|
.roadmap-content {
|
|
grid-column: 2;
|
|
grid-row: 1;
|
|
padding: 16px 16px 24px 0;
|
|
}
|
|
|
|
.roadmap-content-header {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: baseline;
|
|
gap: 10px;
|
|
}
|
|
|
|
.roadmap-content-title {
|
|
font-size: 1.05em;
|
|
color: var(--vp-c-text-1, #213547);
|
|
}
|
|
|
|
.roadmap-content-badge {
|
|
font-size: 0.75em;
|
|
padding: 2px 10px;
|
|
border-radius: 12px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.02em;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.roadmap-content-badge--done {
|
|
background: #fef9c3;
|
|
color: #854d0e;
|
|
}
|
|
|
|
.roadmap-content-badge--in-progress {
|
|
background: #e0e7ff;
|
|
color: #4338ca;
|
|
}
|
|
|
|
.roadmap-content-badge--planned {
|
|
background: #d1fae5;
|
|
color: #065f46;
|
|
}
|
|
|
|
.roadmap-content-description {
|
|
margin: 6px 0 0 0;
|
|
font-size: 0.9em;
|
|
color: var(--vp-c-text-2, #666);
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.roadmap-content-issues {
|
|
display: flex;
|
|
gap: 8px;
|
|
margin-top: 6px;
|
|
font-size: 0.82em;
|
|
}
|
|
|
|
.roadmap-content-issues a {
|
|
color: var(--vp-c-accent-bg);
|
|
text-decoration: none;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.roadmap-content-issues a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
|
|
/* === Responsive === */
|
|
@media (max-width: 600px) {
|
|
.roadmap-station {
|
|
column-gap: 14px;
|
|
}
|
|
|
|
.roadmap-content {
|
|
padding: 8px 0 20px 0;
|
|
}
|
|
|
|
.roadmap-content-title {
|
|
font-size: 0.95em;
|
|
}
|
|
|
|
.roadmap-station--in-progress .roadmap-content {
|
|
padding-left: 4px;
|
|
}
|
|
}
|
|
</style>
|