Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
All services: admin-v2, studio-v2, website, ai-compliance-sdk, consent-service, klausur-service, voice-service, and infrastructure. Large PDFs and compiled binaries excluded via .gitignore.
217 lines
8.1 KiB
TypeScript
217 lines
8.1 KiB
TypeScript
'use client'
|
|
|
|
import { useState, useEffect } from 'react'
|
|
import { PagePurpose } from '@/components/common/PagePurpose'
|
|
import { getModuleByHref } from '@/lib/navigation'
|
|
import { ExternalLink, Maximize2, Minimize2, RefreshCw, Search, BookOpen, ArrowRight } from 'lucide-react'
|
|
|
|
// Quick links to important documentation sections
|
|
const quickLinks = [
|
|
{ name: 'Architektur', path: '#architektur', icon: '🏗️' },
|
|
{ name: 'Klausur-Service', path: 'services/klausur-service/', icon: '📝' },
|
|
{ name: 'AI-Compliance-SDK', path: 'services/ai-compliance-sdk/', icon: '🔒' },
|
|
{ name: 'Voice-Service', path: 'services/voice-service/', icon: '🎤' },
|
|
{ name: 'Agent-Core', path: 'services/agent-core/', icon: '🤖' },
|
|
{ name: 'CI/CD Pipeline', path: 'development/ci-cd-pipeline/', icon: '🚀' },
|
|
]
|
|
|
|
export default function DocsPage() {
|
|
const [isFullscreen, setIsFullscreen] = useState(false)
|
|
const [isLoading, setIsLoading] = useState(true)
|
|
const [currentPath, setCurrentPath] = useState('')
|
|
const moduleInfo = getModuleByHref('/development/docs')
|
|
|
|
// Determine docs URL based on environment
|
|
// Use same-origin proxy at /docs/ to avoid mixed content issues (HTTPS -> HTTP)
|
|
const getDocsUrl = () => {
|
|
if (typeof window !== 'undefined') {
|
|
// Use same-origin proxy path to avoid mixed content issues
|
|
const protocol = window.location.protocol
|
|
const hostname = window.location.hostname
|
|
const port = window.location.port
|
|
return `${protocol}//${hostname}${port ? ':' + port : ''}/docs`
|
|
}
|
|
return '/docs'
|
|
}
|
|
|
|
const docsUrl = getDocsUrl()
|
|
|
|
const handleIframeLoad = () => {
|
|
setIsLoading(false)
|
|
}
|
|
|
|
const navigateTo = (path: string) => {
|
|
setCurrentPath(path)
|
|
setIsLoading(true)
|
|
}
|
|
|
|
const toggleFullscreen = () => {
|
|
setIsFullscreen(!isFullscreen)
|
|
}
|
|
|
|
const openInNewTab = () => {
|
|
window.open(`${docsUrl}/${currentPath}`, '_blank')
|
|
}
|
|
|
|
const refreshDocs = () => {
|
|
setIsLoading(true)
|
|
// Force iframe reload by toggling key
|
|
setCurrentPath(currentPath + '?refresh=' + Date.now())
|
|
setTimeout(() => setCurrentPath(currentPath), 100)
|
|
}
|
|
|
|
if (isFullscreen) {
|
|
return (
|
|
<div className="fixed inset-0 z-50 bg-white">
|
|
{/* Fullscreen Toolbar */}
|
|
<div className="absolute top-0 left-0 right-0 h-12 bg-slate-900 flex items-center justify-between px-4 z-10">
|
|
<div className="flex items-center gap-2 text-white">
|
|
<BookOpen className="w-5 h-5" />
|
|
<span className="font-semibold">Breakpilot Dokumentation</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
onClick={openInNewTab}
|
|
className="p-2 text-slate-300 hover:text-white hover:bg-slate-700 rounded transition-colors"
|
|
title="In neuem Tab oeffnen"
|
|
>
|
|
<ExternalLink className="w-4 h-4" />
|
|
</button>
|
|
<button
|
|
onClick={toggleFullscreen}
|
|
className="p-2 text-slate-300 hover:text-white hover:bg-slate-700 rounded transition-colors"
|
|
title="Vollbild beenden"
|
|
>
|
|
<Minimize2 className="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<iframe
|
|
src={`${docsUrl}/${currentPath}`}
|
|
className="w-full h-full pt-12"
|
|
title="Breakpilot Documentation"
|
|
onLoad={handleIframeLoad}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Page Purpose */}
|
|
{moduleInfo && (
|
|
<PagePurpose
|
|
title={moduleInfo.module.name}
|
|
purpose={moduleInfo.module.purpose}
|
|
audience={moduleInfo.module.audience}
|
|
architecture={{
|
|
services: ['MkDocs (Static Site)', 'Nginx (Port 8009)'],
|
|
databases: [],
|
|
}}
|
|
relatedPages={[
|
|
{ name: 'CI/CD', href: '/infrastructure/ci-cd', description: 'Deployment Pipeline' },
|
|
{ name: 'Architektur', href: '/architecture', description: 'System-Uebersicht' },
|
|
{ name: 'SBOM', href: '/infrastructure/sbom', description: 'Abhaengigkeiten' },
|
|
]}
|
|
collapsible={true}
|
|
defaultCollapsed={true}
|
|
/>
|
|
)}
|
|
|
|
{/* Quick Links */}
|
|
<div className="bg-white border border-slate-200 rounded-xl p-4">
|
|
<h3 className="text-sm font-semibold text-slate-700 mb-3 flex items-center gap-2">
|
|
<Search className="w-4 h-4" />
|
|
Schnellzugriff
|
|
</h3>
|
|
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-2">
|
|
{quickLinks.map((link) => (
|
|
<button
|
|
key={link.path}
|
|
onClick={() => navigateTo(link.path)}
|
|
className="flex items-center gap-2 px-3 py-2 text-sm bg-slate-50 hover:bg-slate-100 border border-slate-200 rounded-lg transition-colors text-left"
|
|
>
|
|
<span>{link.icon}</span>
|
|
<span className="truncate">{link.name}</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Toolbar */}
|
|
<div className="flex items-center justify-between bg-white border border-slate-200 rounded-xl p-3">
|
|
<div className="flex items-center gap-2">
|
|
<BookOpen className="w-5 h-5 text-slate-500" />
|
|
<span className="text-sm font-medium text-slate-700">
|
|
Breakpilot Dokumentation
|
|
</span>
|
|
<span className="text-xs text-slate-400">
|
|
(MkDocs Material)
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
onClick={refreshDocs}
|
|
className="p-2 text-slate-500 hover:text-slate-700 hover:bg-slate-100 rounded-lg transition-colors"
|
|
title="Aktualisieren"
|
|
>
|
|
<RefreshCw className={`w-4 h-4 ${isLoading ? 'animate-spin' : ''}`} />
|
|
</button>
|
|
<button
|
|
onClick={openInNewTab}
|
|
className="p-2 text-slate-500 hover:text-slate-700 hover:bg-slate-100 rounded-lg transition-colors"
|
|
title="In neuem Tab oeffnen"
|
|
>
|
|
<ExternalLink className="w-4 h-4" />
|
|
</button>
|
|
<button
|
|
onClick={toggleFullscreen}
|
|
className="p-2 text-slate-500 hover:text-slate-700 hover:bg-slate-100 rounded-lg transition-colors"
|
|
title="Vollbild"
|
|
>
|
|
<Maximize2 className="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Documentation Iframe */}
|
|
<div className="relative bg-white border border-slate-200 rounded-xl overflow-hidden" style={{ height: 'calc(100vh - 400px)', minHeight: '500px' }}>
|
|
{isLoading && (
|
|
<div className="absolute inset-0 bg-white flex items-center justify-center z-10">
|
|
<div className="flex flex-col items-center gap-3">
|
|
<div className="w-8 h-8 border-2 border-slate-300 border-t-slate-600 rounded-full animate-spin" />
|
|
<span className="text-sm text-slate-500">Dokumentation wird geladen...</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
<iframe
|
|
key={currentPath}
|
|
src={`${docsUrl}/${currentPath}`}
|
|
className="w-full h-full"
|
|
title="Breakpilot Documentation"
|
|
onLoad={handleIframeLoad}
|
|
/>
|
|
</div>
|
|
|
|
{/* Info Box */}
|
|
<div className="bg-slate-50 border border-slate-200 rounded-xl p-4">
|
|
<div className="flex items-start gap-3">
|
|
<div className="p-2 bg-slate-200 rounded-lg">
|
|
<ArrowRight className="w-4 h-4 text-slate-600" />
|
|
</div>
|
|
<div>
|
|
<h4 className="font-medium text-slate-800">Dokumentation bearbeiten</h4>
|
|
<p className="text-sm text-slate-600 mt-1">
|
|
Die Dokumentation befindet sich im Repository unter <code className="text-xs bg-slate-200 px-1.5 py-0.5 rounded">docs-src/</code>.
|
|
Nach Aenderungen muss der Docs-Container neu gebaut werden.
|
|
</p>
|
|
<div className="mt-2 text-xs text-slate-500 font-mono bg-slate-100 p-2 rounded">
|
|
rsync docs-src/ macmini:... && ssh macmini "docker compose build docs && docker compose up -d docs"
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|