Initial commit - Help Service for Coolify

This commit is contained in:
2025-12-17 10:08:16 +01:00
commit a998c47132
57 changed files with 7104 additions and 0 deletions

241
templates/topic.html Normal file
View File

@@ -0,0 +1,241 @@
{% extends "base.html" %}
{% block title %}{{ topic.title }}{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Breadcrumb -->
<nav aria-label="breadcrumb" class="mb-4">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">Startseite</a></li>
{% if parent_topic %}
<li class="breadcrumb-item"><a href="/topic/{{ parent_topic.id }}">{{ parent_topic.title }}</a></li>
{% endif %}
<li class="breadcrumb-item active">{{ topic.title }}</li>
</ol>
</nav>
<!-- Topic Header -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="d-flex align-items-center mb-3">
<i class="bi bi-{{ topic.icon|default('file-text') }} text-primary display-4 me-3"></i>
<div>
<h1 class="mb-1">{{ topic.title }}</h1>
<p class="text-muted mb-0">{{ topic.description }}</p>
</div>
</div>
{% if topic.tags %}
<div class="mt-3">
{% for tag in topic.tags %}
<span class="badge bg-secondary me-1">{{ tag }}</span>
{% endfor %}
</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Topic Content -->
<div class="row">
<div class="col-lg-9">
<div class="card">
<div class="card-body content-body">
{{ topic.content|safe }}
</div>
</div>
<!-- Child Topics / Subpages -->
{% if child_topics %}
<div class="card mt-4">
<div class="card-header bg-primary bg-opacity-10">
<h5 class="mb-0"><i class="bi bi-folder2-open me-2"></i>Unterseiten</h5>
</div>
<div class="card-body">
<div class="row">
{% for child in child_topics %}
<div class="col-md-6 mb-3">
<a href="/topic/{{ child.id }}" class="text-decoration-none">
<div class="card h-100 hover-shadow">
<div class="card-body py-3">
<div class="d-flex align-items-center">
<i class="bi bi-{{ child.icon|default('file-text') }} text-primary me-3 fs-4"></i>
<div>
<h6 class="mb-1">{{ child.title }}</h6>
{% if child.description %}
<small class="text-muted">{{ child.description }}</small>
{% endif %}
</div>
</div>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
<!-- Related Topics -->
{% if topic.related %}
<div class="card mt-4">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-link-45deg me-2"></i>Verwandte Themen</h5>
</div>
<div class="card-body">
<div class="row">
{% for related_id in topic.related %}
{% for section in content.sections %}
{% for t in section.topics %}
{% if t.id == related_id %}
<div class="col-md-6 mb-2">
<a href="/topic/{{ t.id }}" class="text-decoration-none">
<div class="d-flex align-items-center p-2 rounded hover-bg">
<i class="bi bi-{{ t.icon|default('file-text') }} text-primary me-2"></i>
<span>{{ t.title }}</span>
</div>
</a>
</div>
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
</div>
</div>
</div>
{% endif %}
</div>
<!-- Sidebar (Sticky) -->
<div class="col-lg-3">
<div class="toc-sidebar">
<!-- Table of Contents -->
{% if topic.toc %}
<div class="card mb-4 toc-card">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-list-ul me-2"></i>Inhalt</h6>
</div>
<div class="card-body py-2">
<nav class="toc-nav" id="toc-nav">
{% for item in topic.toc %}
<a href="#{{ item.id }}" class="toc-link {% if item.level == 3 %}toc-link-sub{% endif %}" data-target="{{ item.id }}">
{{ item.title }}
</a>
{% endfor %}
</nav>
</div>
</div>
{% endif %}
<!-- Quick Tips -->
{% if topic.tips %}
<div class="card">
<div class="card-header bg-success bg-opacity-25">
<h6 class="mb-0 text-success"><i class="bi bi-lightbulb me-2"></i>Tipps</h6>
</div>
<div class="card-body">
<ul class="list-unstyled mb-0">
{% for tip in topic.tips %}
<li class="mb-2">
<i class="bi bi-check-circle text-success me-1"></i>
{{ tip }}
</li>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
</div>
</div>
</div>
<!-- Navigation -->
<div class="row mt-4">
<div class="col-12">
<div class="d-flex justify-content-between">
<a href="/" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left me-2"></i>Zurueck zur Uebersicht
</a>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
// Scroll-Spy for TOC
document.addEventListener('DOMContentLoaded', function() {
const tocNav = document.getElementById('toc-nav');
if (!tocNav) return;
const tocLinks = tocNav.querySelectorAll('.toc-link');
if (tocLinks.length === 0) return;
// Get all headings that are in the TOC
const headingIds = Array.from(tocLinks).map(link => link.getAttribute('data-target'));
const headings = headingIds.map(id => document.getElementById(id)).filter(el => el);
if (headings.length === 0) return;
function updateActiveLink() {
const scrollPos = window.scrollY + 100; // Offset for better UX
let activeIndex = 0;
// Find the heading that is currently in view
for (let i = 0; i < headings.length; i++) {
if (headings[i].offsetTop <= scrollPos) {
activeIndex = i;
}
}
// Update active state
tocLinks.forEach((link, index) => {
if (index === activeIndex) {
link.classList.add('active');
} else {
link.classList.remove('active');
}
});
}
// Throttle scroll events
let ticking = false;
window.addEventListener('scroll', function() {
if (!ticking) {
window.requestAnimationFrame(function() {
updateActiveLink();
ticking = false;
});
ticking = true;
}
});
// Initial update
updateActiveLink();
// Smooth scroll with offset when clicking TOC links
tocLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('data-target');
const target = document.getElementById(targetId);
if (target) {
const offset = 20;
const targetPos = target.offsetTop - offset;
window.scrollTo({
top: targetPos,
behavior: 'smooth'
});
}
});
});
});
</script>
{% endblock %}