A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
476 lines
15 KiB
HTML
476 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>BreakPilot Compliance SDK - Embed Demo</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
line-height: 1.6;
|
|
color: #1a1a2e;
|
|
background: linear-gradient(135deg, #f5f7fa 0%, #e4e8eb 100%);
|
|
min-height: 100vh;
|
|
}
|
|
|
|
header {
|
|
background: white;
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
padding: 1rem 2rem;
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 100;
|
|
}
|
|
|
|
.header-content {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.logo {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
.logo-icon {
|
|
width: 40px;
|
|
height: 40px;
|
|
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
|
border-radius: 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.logo-icon svg {
|
|
width: 24px;
|
|
height: 24px;
|
|
fill: white;
|
|
}
|
|
|
|
.logo-text {
|
|
font-weight: 700;
|
|
font-size: 1.25rem;
|
|
}
|
|
|
|
nav {
|
|
display: flex;
|
|
gap: 2rem;
|
|
}
|
|
|
|
nav a {
|
|
color: #64748b;
|
|
text-decoration: none;
|
|
font-weight: 500;
|
|
transition: color 0.2s;
|
|
}
|
|
|
|
nav a:hover {
|
|
color: #3b82f6;
|
|
}
|
|
|
|
main {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 3rem 2rem;
|
|
}
|
|
|
|
.hero {
|
|
text-align: center;
|
|
padding: 4rem 0;
|
|
}
|
|
|
|
.hero h1 {
|
|
font-size: 3rem;
|
|
font-weight: 800;
|
|
margin-bottom: 1rem;
|
|
background: linear-gradient(135deg, #1a1a2e 0%, #3b82f6 100%);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
}
|
|
|
|
.hero p {
|
|
font-size: 1.25rem;
|
|
color: #64748b;
|
|
max-width: 600px;
|
|
margin: 0 auto 2rem;
|
|
}
|
|
|
|
.demo-section {
|
|
background: white;
|
|
border-radius: 16px;
|
|
padding: 2rem;
|
|
margin-bottom: 2rem;
|
|
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
|
|
}
|
|
|
|
.demo-section h2 {
|
|
font-size: 1.5rem;
|
|
margin-bottom: 1rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.demo-section h2::before {
|
|
content: '';
|
|
width: 4px;
|
|
height: 24px;
|
|
background: #3b82f6;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.code-block {
|
|
background: #1a1a2e;
|
|
border-radius: 8px;
|
|
padding: 1.5rem;
|
|
overflow-x: auto;
|
|
margin: 1rem 0;
|
|
}
|
|
|
|
.code-block pre {
|
|
color: #e2e8f0;
|
|
font-family: 'Fira Code', 'Monaco', monospace;
|
|
font-size: 0.875rem;
|
|
line-height: 1.7;
|
|
}
|
|
|
|
.code-block .comment {
|
|
color: #64748b;
|
|
}
|
|
|
|
.code-block .keyword {
|
|
color: #c084fc;
|
|
}
|
|
|
|
.code-block .string {
|
|
color: #4ade80;
|
|
}
|
|
|
|
.code-block .property {
|
|
color: #60a5fa;
|
|
}
|
|
|
|
.feature-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
gap: 1.5rem;
|
|
margin-top: 2rem;
|
|
}
|
|
|
|
.feature-card {
|
|
background: #f8fafc;
|
|
border-radius: 12px;
|
|
padding: 1.5rem;
|
|
border: 1px solid #e2e8f0;
|
|
transition: transform 0.2s, box-shadow 0.2s;
|
|
}
|
|
|
|
.feature-card:hover {
|
|
transform: translateY(-4px);
|
|
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.feature-card h3 {
|
|
font-size: 1.125rem;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.feature-card p {
|
|
color: #64748b;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.75rem 1.5rem;
|
|
border-radius: 8px;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
transition: all 0.2s;
|
|
cursor: pointer;
|
|
border: none;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
|
|
color: white;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4);
|
|
}
|
|
|
|
.btn-secondary {
|
|
background: white;
|
|
color: #1a1a2e;
|
|
border: 2px solid #e2e8f0;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
border-color: #3b82f6;
|
|
color: #3b82f6;
|
|
}
|
|
|
|
.webcomponents-demo {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
gap: 1.5rem;
|
|
margin-top: 1.5rem;
|
|
}
|
|
|
|
footer {
|
|
text-align: center;
|
|
padding: 2rem;
|
|
color: #64748b;
|
|
font-size: 0.875rem;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<div class="header-content">
|
|
<div class="logo">
|
|
<div class="logo-icon">
|
|
<svg viewBox="0 0 24 24"><path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/></svg>
|
|
</div>
|
|
<span class="logo-text">BreakPilot SDK</span>
|
|
</div>
|
|
<nav>
|
|
<a href="#embed">Embed Script</a>
|
|
<a href="#components">Web Components</a>
|
|
<a href="#events">Events</a>
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<main>
|
|
<section class="hero">
|
|
<h1>Compliance SDK Demo</h1>
|
|
<p>
|
|
Integrieren Sie DSGVO-konforme Einwilligungsverwaltung, DSR-Portale und
|
|
Compliance-Features mit nur wenigen Zeilen Code.
|
|
</p>
|
|
<div style="display: flex; gap: 1rem; justify-content: center;">
|
|
<a href="#embed" class="btn btn-primary">Integration starten</a>
|
|
<a href="https://github.com/breakpilot/compliance-sdk" class="btn btn-secondary">GitHub</a>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="embed" class="demo-section">
|
|
<h2>1. Embed Script Integration</h2>
|
|
<p>Fuegen Sie das SDK mit einem einzigen Script-Tag zu Ihrer Website hinzu:</p>
|
|
|
|
<div class="code-block">
|
|
<pre><span class="comment"><!-- BreakPilot Compliance SDK --></span>
|
|
<span class="keyword"><script</span> <span class="property">src</span>=<span class="string">"https://cdn.breakpilot.app/sdk/v1/compliance.min.js"</span><span class="keyword">></script></span>
|
|
<span class="keyword"><script></span>
|
|
BreakPilotSDK.init({
|
|
<span class="property">apiEndpoint</span>: <span class="string">'https://compliance.example.com/api/v1'</span>,
|
|
<span class="property">apiKey</span>: <span class="string">'pk_live_xxx'</span>,
|
|
<span class="property">autoInjectBanner</span>: <span class="keyword">true</span>,
|
|
<span class="property">bannerConfig</span>: {
|
|
<span class="property">position</span>: <span class="string">'bottom'</span>,
|
|
<span class="property">theme</span>: <span class="string">'light'</span>,
|
|
<span class="property">language</span>: <span class="string">'de'</span>
|
|
},
|
|
<span class="property">onConsentChange</span>: <span class="keyword">function</span>(consent) {
|
|
<span class="keyword">if</span> (consent.analytics) loadAnalytics();
|
|
<span class="keyword">if</span> (consent.marketing) loadMarketing();
|
|
}
|
|
});
|
|
<span class="keyword"></script></span></pre>
|
|
</div>
|
|
|
|
<div class="feature-grid">
|
|
<div class="feature-card">
|
|
<h3>Auto-Inject Banner</h3>
|
|
<p>Cookie-Banner wird automatisch eingeblendet wenn keine Einwilligung vorliegt.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<h3>Consent Callbacks</h3>
|
|
<p>Reagieren Sie auf Einwilligungsaenderungen mit Custom-Callbacks.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<h3>Multi-Language</h3>
|
|
<p>Unterstuetzung fuer DE, EN, FR, ES, IT und weitere Sprachen.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="components" class="demo-section">
|
|
<h2>2. Web Components</h2>
|
|
<p>Verwenden Sie vorgefertigte Web Components fuer gaengige Compliance-Features:</p>
|
|
|
|
<div class="code-block">
|
|
<pre><span class="comment"><!-- Consent Banner --></span>
|
|
<span class="keyword"><breakpilot-consent-banner</span>
|
|
<span class="property">api-key</span>=<span class="string">"pk_live_xxx"</span>
|
|
<span class="property">position</span>=<span class="string">"bottom"</span>
|
|
<span class="property">theme</span>=<span class="string">"light"</span>
|
|
<span class="keyword">></breakpilot-consent-banner></span>
|
|
|
|
<span class="comment"><!-- DSR Portal --></span>
|
|
<span class="keyword"><breakpilot-dsr-portal</span>
|
|
<span class="property">language</span>=<span class="string">"de"</span>
|
|
<span class="keyword">></breakpilot-dsr-portal></span>
|
|
|
|
<span class="comment"><!-- Compliance Score Widget --></span>
|
|
<span class="keyword"><breakpilot-compliance-score</span>
|
|
<span class="property">show-details</span>=<span class="string">"true"</span>
|
|
<span class="keyword">></breakpilot-compliance-score></span></pre>
|
|
</div>
|
|
|
|
<h3 style="margin-top: 2rem; margin-bottom: 1rem;">Live Demo</h3>
|
|
<div class="webcomponents-demo">
|
|
<div id="consent-banner-demo" style="border: 2px dashed #e2e8f0; border-radius: 12px; padding: 2rem; text-align: center; background: #f8fafc;">
|
|
<p style="color: #64748b;">Consent Banner wird hier angezeigt</p>
|
|
<button class="btn btn-primary" style="margin-top: 1rem;" onclick="showConsentBanner()">Banner anzeigen</button>
|
|
</div>
|
|
<div id="score-demo" style="border: 2px dashed #e2e8f0; border-radius: 12px; padding: 2rem; text-align: center; background: #f8fafc;">
|
|
<p style="color: #64748b;">Compliance Score Widget</p>
|
|
<div style="margin-top: 1rem;">
|
|
<div style="width: 100px; height: 100px; margin: 0 auto; border-radius: 50%; background: conic-gradient(#3b82f6 0deg 280deg, #e2e8f0 280deg 360deg); display: flex; align-items: center; justify-content: center;">
|
|
<div style="width: 80px; height: 80px; border-radius: 50%; background: white; display: flex; align-items: center; justify-content: center; font-size: 1.5rem; font-weight: 700;">78%</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="events" class="demo-section">
|
|
<h2>3. Events & Callbacks</h2>
|
|
<p>Das SDK emittiert Events fuer alle wichtigen Aktionen:</p>
|
|
|
|
<div class="code-block">
|
|
<pre><span class="comment">// Event Listener registrieren</span>
|
|
<span class="keyword">window</span>.addEventListener(<span class="string">'breakpilot:consent-granted'</span>, (e) => {
|
|
console.log(<span class="string">'Einwilligung erteilt:'</span>, e.detail.purposes);
|
|
});
|
|
|
|
<span class="keyword">window</span>.addEventListener(<span class="string">'breakpilot:consent-revoked'</span>, (e) => {
|
|
console.log(<span class="string">'Einwilligung widerrufen:'</span>, e.detail.purposes);
|
|
});
|
|
|
|
<span class="keyword">window</span>.addEventListener(<span class="string">'breakpilot:dsr-submitted'</span>, (e) => {
|
|
console.log(<span class="string">'DSR Anfrage eingereicht:'</span>, e.detail.requestType);
|
|
});
|
|
|
|
<span class="comment">// Consent programmatisch pruefen</span>
|
|
<span class="keyword">const</span> hasAnalytics = BreakPilotSDK.hasConsent(<span class="string">'analytics'</span>);
|
|
<span class="keyword">const</span> allConsents = BreakPilotSDK.getConsents();</pre>
|
|
</div>
|
|
|
|
<div class="feature-grid">
|
|
<div class="feature-card">
|
|
<h3>consent-granted</h3>
|
|
<p>Wird ausgeloest wenn der Nutzer eine Einwilligung erteilt.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<h3>consent-revoked</h3>
|
|
<p>Wird ausgeloest wenn eine Einwilligung widerrufen wird.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<h3>dsr-submitted</h3>
|
|
<p>Wird ausgeloest wenn eine Betroffenenanfrage eingereicht wird.</p>
|
|
</div>
|
|
<div class="feature-card">
|
|
<h3>state-changed</h3>
|
|
<p>Wird ausgeloest wenn sich der SDK-State aendert.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="demo-section">
|
|
<h2>4. API-Referenz</h2>
|
|
<p>Vollstaendige API-Dokumentation fuer alle SDK-Methoden:</p>
|
|
|
|
<div class="code-block">
|
|
<pre><span class="comment">// SDK Initialisieren</span>
|
|
BreakPilotSDK.init(config);
|
|
|
|
<span class="comment">// Consent Management</span>
|
|
BreakPilotSDK.grantConsent(<span class="string">'analytics'</span>);
|
|
BreakPilotSDK.revokeConsent(<span class="string">'marketing'</span>);
|
|
BreakPilotSDK.hasConsent(<span class="string">'functional'</span>);
|
|
BreakPilotSDK.getConsents();
|
|
|
|
<span class="comment">// DSR (Data Subject Requests)</span>
|
|
BreakPilotSDK.submitDSR({
|
|
type: <span class="string">'ACCESS'</span>,
|
|
email: <span class="string">'user@example.com'</span>,
|
|
name: <span class="string">'Max Mustermann'</span>
|
|
});
|
|
|
|
<span class="comment">// Banner Control</span>
|
|
BreakPilotSDK.showBanner();
|
|
BreakPilotSDK.hideBanner();
|
|
|
|
<span class="comment">// State Management</span>
|
|
BreakPilotSDK.getState();
|
|
BreakPilotSDK.resetState();</pre>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<footer>
|
|
<p>© 2025 BreakPilot Compliance SDK. Built with privacy in mind.</p>
|
|
</footer>
|
|
|
|
<script>
|
|
// Demo functionality
|
|
function showConsentBanner() {
|
|
const demo = document.getElementById('consent-banner-demo');
|
|
demo.innerHTML = `
|
|
<div style="background: white; border-radius: 12px; padding: 1.5rem; box-shadow: 0 4px 20px rgba(0,0,0,0.15); text-align: left;">
|
|
<h4 style="margin-bottom: 0.75rem; font-size: 1rem;">Cookie-Einstellungen</h4>
|
|
<p style="color: #64748b; font-size: 0.875rem; margin-bottom: 1rem;">
|
|
Wir verwenden Cookies, um Ihre Erfahrung zu verbessern. Bitte waehlen Sie Ihre Praeferenzen.
|
|
</p>
|
|
<div style="display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem;">
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" checked disabled> Notwendig (immer aktiv)
|
|
</label>
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" id="analytics"> Analytics
|
|
</label>
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" id="marketing"> Marketing
|
|
</label>
|
|
</div>
|
|
<div style="display: flex; gap: 0.5rem;">
|
|
<button class="btn btn-primary" onclick="acceptAll()">Alle akzeptieren</button>
|
|
<button class="btn btn-secondary" onclick="savePreferences()">Speichern</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
function acceptAll() {
|
|
alert('Alle Cookies akzeptiert! Event: breakpilot:consent-granted');
|
|
document.getElementById('consent-banner-demo').innerHTML = '<p style="color: #22c55e; font-weight: 600;">Einwilligung gespeichert</p>';
|
|
}
|
|
|
|
function savePreferences() {
|
|
const analytics = document.getElementById('analytics').checked;
|
|
const marketing = document.getElementById('marketing').checked;
|
|
alert(`Gespeichert: Analytics=${analytics}, Marketing=${marketing}`);
|
|
document.getElementById('consent-banner-demo').innerHTML = '<p style="color: #22c55e; font-weight: 600;">Praeferenzen gespeichert</p>';
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|