bmc_hub/app/shared/frontend/manual_modal.html
Christian ceb560e2f2 feat: Add bottom bar functionality with real-time updates and manual endpoint tests
- Implemented a new bottom bar feature in `bottom-bar.js` that fetches and displays various notifications and statuses in real-time.
- Added functions for handling visibility, state updates, and user interactions within the bottom bar.
- Introduced WebSocket connection for real-time updates and fallback polling mechanism.
- Created a manual testing script `test_manual.py` to validate API endpoints for the manual module.
- Included tests for various paths to ensure expected responses from the server.
2026-04-12 02:27:01 +02:00

106 lines
5.1 KiB
HTML

<!-- Manual Help Modal -->
<div class="modal fade" id="manualHelpModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg modal-dialog-scrollable">
<div class="modal-content" style="border-radius: 12px; border: none; background: var(--card-bg, #ffffff); box-shadow: 0 10px 40px rgba(0,0,0,0.2);">
<div class="modal-header border-bottom border-primary-subtle align-items-center">
<h5 class="modal-title">
<i class="bi bi-book ms-1 me-2 text-accent"></i> Hent Hjælp
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-0">
<div id="manualHelpLoading" class="text-center py-5 d-none">
<div class="spinner-border text-primary" role="status"></div>
<div class="mt-3 text-muted">Søger i vejledninger...</div>
</div>
<div id="manualHelpContent" class="m-0">
<!-- Dynamic content loads here -->
</div>
</div>
<div class="modal-footer border-top border-primary-subtle bg-body-tertiary">
<a href="/manual" class="btn btn-outline-primary btn-sm me-auto">
<i class="bi bi-search me-1"></i> Alle Vejledninger
</a>
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Luk</button>
</div>
</div>
</div>
</div>
<script>
let manualHelpModalInstance = null;
document.addEventListener("DOMContentLoaded", function() {
const el = document.getElementById('manualHelpModal');
if (el && typeof bootstrap !== "undefined") {
manualHelpModalInstance = new bootstrap.Modal(el);
}
});
async function openManualHelp(contextModule, contextTag = '') {
if (!manualHelpModalInstance) return;
const contentDiv = document.getElementById('manualHelpContent');
const loadingDiv = document.getElementById('manualHelpLoading');
const modalTitle = document.querySelector('#manualHelpModal .modal-title');
if (modalTitle) {
modalTitle.innerHTML = `<i class="bi bi-book ms-1 me-2 text-accent"></i> Hjælp til: ${contextModule}`;
}
contentDiv.classList.add('d-none');
loadingDiv.classList.remove('d-none');
manualHelpModalInstance.show();
try {
let url = `/api/v1/manual/context?module=${encodeURIComponent(contextModule)}`;
if (contextTag) {
url += `&tag=${encodeURIComponent(contextTag)}`;
}
const res = await fetch(url);
if (!res.ok) throw new Error('Netværksfejl');
const data = await res.json();
let html = '';
if (!data.results || data.results.length === 0) {
html = `<div class="p-4 text-center text-muted">
<i class="bi bi-emoji-frown fs-1 d-block mb-3 opacity-50"></i>
Der blev ikke fundet nogle specifikke vejledninger til "${contextModule}".<br>
Prøv at søge i den fulde manual.
</div>`;
} else {
html += '<div class="list-group list-group-flush">';
data.results.forEach(m => {
const diffBadge = m.difficulty === 'advanced'
? '<span class="badge bg-danger-subtle text-danger ms-2">Avanceret</span>'
: '<span class="badge bg-success-subtle text-success ms-2">Begynder</span>';
html += `
<a href="/manual/${m.slug}" target="_blank" class="list-group-item list-group-item-action p-4 border-0 border-bottom border-primary-subtle hover-bg-light py-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<h6 class="mb-0 text-primary fw-bold">
<i class="bi bi-file-text me-2"></i> ${m.title}
</h6>
<div>
${diffBadge}
<i class="bi bi-arrow-up-right-square ms-2 text-muted small"></i>
</div>
</div>
<p class="text-body-secondary small mb-0 ps-4">${m.summary || 'Ingen beskrivelse tilgængelig.'}</p>
</a>
`;
});
html += '</div>';
}
contentDiv.innerHTML = html;
} catch (e) {
contentDiv.innerHTML = `<div class="p-4 text-center text-danger"><i class="bi bi-exclamation-triangle mt-1 me-2"></i> Kunne ikke loade vejledninger. (${e.message})</div>`;
console.error('Fejl ved hentning af manual help:', e);
} finally {
loadingDiv.classList.add('d-none');
contentDiv.classList.remove('d-none');
}
}
</script>