Files
michaelschiemer/src/Framework/WebPush/templates/webpush-demo.view.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

441 lines
14 KiB
PHP

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebPush Demo - Push-Benachrichtigungen</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, -apple-system, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.container {
background: white;
border-radius: 20px;
padding: 40px;
max-width: 600px;
width: 100%;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
h1 {
color: #667eea;
margin-bottom: 10px;
font-size: 32px;
}
.subtitle {
color: #666;
margin-bottom: 30px;
font-size: 16px;
}
.status-card {
background: #f7fafc;
border-radius: 12px;
padding: 20px;
margin-bottom: 30px;
border-left: 4px solid #667eea;
}
.status-label {
color: #667eea;
font-weight: 600;
font-size: 14px;
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 8px;
}
.status-value {
color: #2d3748;
font-size: 18px;
font-weight: 500;
}
.status-subscribed {
color: #48bb78;
}
.status-unsubscribed {
color: #f56565;
}
.button-group {
display: grid;
gap: 15px;
margin-bottom: 30px;
}
button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 16px 24px;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
button:active {
transform: translateY(0);
}
button:disabled {
background: #cbd5e0;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
button.secondary {
background: white;
color: #667eea;
border: 2px solid #667eea;
box-shadow: none;
}
button.secondary:hover {
background: #f7fafc;
}
button.danger {
background: linear-gradient(135deg, #f56565 0%, #c53030 100%);
box-shadow: 0 4px 15px rgba(245, 101, 101, 0.3);
}
button.danger:hover {
box-shadow: 0 6px 20px rgba(245, 101, 101, 0.4);
}
.info-box {
background: #edf2f7;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
}
.info-title {
color: #2d3748;
font-weight: 600;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.info-list {
list-style: none;
padding: 0;
}
.info-list li {
color: #4a5568;
padding: 8px 0;
padding-left: 24px;
position: relative;
}
.info-list li:before {
content: "";
position: absolute;
left: 0;
color: #48bb78;
font-weight: bold;
}
.console-output {
background: #1a202c;
color: #e2e8f0;
border-radius: 12px;
padding: 20px;
font-family: 'Courier New', monospace;
font-size: 13px;
max-height: 200px;
overflow-y: auto;
margin-top: 20px;
}
.console-output .log-entry {
margin-bottom: 8px;
opacity: 0;
animation: fadeIn 0.3s ease forwards;
}
@keyframes fadeIn {
to {
opacity: 1;
}
}
.console-output .log-success {
color: #48bb78;
}
.console-output .log-error {
color: #f56565;
}
.console-output .log-info {
color: #4299e1;
}
@media (max-width: 640px) {
.container {
padding: 24px;
}
h1 {
font-size: 24px;
}
button {
padding: 14px 20px;
font-size: 14px;
}
}
</style>
</head>
<body>
<div class="container">
<h1>🔔 WebPush Demo</h1>
<p class="subtitle">Teste Push-Benachrichtigungen in deinem Browser</p>
<div class="status-card">
<div class="status-label">Status</div>
<div class="status-value" id="subscription-status">Prüfe...</div>
</div>
<div class="button-group">
<button id="btn-init" onclick="initWebPush()">
🚀 WebPush initialisieren
</button>
<button id="btn-subscribe" onclick="subscribe()" disabled>
Push-Benachrichtigungen aktivieren
</button>
<button id="btn-unsubscribe" onclick="unsubscribe()" class="danger" disabled>
Push-Benachrichtigungen deaktivieren
</button>
<button id="btn-test" onclick="sendTestNotification()" class="secondary" disabled>
🧪 Test-Benachrichtigung senden
</button>
</div>
<div class="info-box">
<div class="info-title">
<span>📋</span>
<span>Features</span>
</div>
<ul class="info-list">
<li>Service Worker Registration</li>
<li>VAPID Public Key vom Server</li>
<li>Push-Subscription Management</li>
<li>Test-Benachrichtigungen</li>
<li>Status-Tracking</li>
</ul>
</div>
<div class="console-output" id="console-output"></div>
</div>
<script type="module">
// Use the globally available WebPushManager from main.js
// It's initialized at app startup as window.webPushManager
let webPush = null;
// Console Output
function log(message, type = 'info') {
const output = document.getElementById('console-output');
const entry = document.createElement('div');
entry.className = `log-entry log-${type}`;
entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
output.appendChild(entry);
output.scrollTop = output.scrollHeight;
}
// Update UI
function updateUI(isSubscribed) {
const status = document.getElementById('subscription-status');
const btnSubscribe = document.getElementById('btn-subscribe');
const btnUnsubscribe = document.getElementById('btn-unsubscribe');
const btnTest = document.getElementById('btn-test');
if (isSubscribed) {
status.textContent = 'Abonniert';
status.className = 'status-value status-subscribed';
btnSubscribe.disabled = true;
btnUnsubscribe.disabled = false;
btnTest.disabled = false;
} else {
status.textContent = 'Nicht abonniert';
status.className = 'status-value status-unsubscribed';
btnSubscribe.disabled = false;
btnUnsubscribe.disabled = true;
btnTest.disabled = true;
}
}
// Initialize WebPush
window.initWebPush = async function() {
try {
log('Initialisiere WebPush Manager...', 'info');
// Use the global WebPushManager instance from main.js
if (!window.webPushManager) {
throw new Error('WebPushManager nicht verfügbar. Bitte Seite neu laden.');
}
webPush = window.webPushManager;
const isSubscribed = await webPush.init();
updateUI(isSubscribed);
document.getElementById('btn-init').disabled = true;
log('✓ WebPush Manager erfolgreich initialisiert', 'success');
log(`Browser-Support: Service Worker ✓, Push API ✓`, 'success');
} catch (error) {
log(`✗ Fehler: ${error.message}`, 'error');
console.error(error);
}
};
// Subscribe
window.subscribe = async function() {
if (!webPush) {
log('✗ Bitte zuerst initialisieren', 'error');
return;
}
try {
log('Fordere Berechtigung an...', 'info');
const subscription = await webPush.subscribe();
log('✓ Erfolgreich abonniert!', 'success');
log(`Endpoint: ${subscription.endpoint.substring(0, 50)}...`, 'info');
} catch (error) {
log(`✗ Abonnement fehlgeschlagen: ${error.message}`, 'error');
console.error(error);
}
};
// Unsubscribe
window.unsubscribe = async function() {
if (!webPush) {
log('✗ Bitte zuerst initialisieren', 'error');
return;
}
try {
log('Deabonniere...', 'info');
const success = await webPush.unsubscribe();
if (success) {
log('✓ Erfolgreich deabonniert!', 'success');
}
} catch (error) {
log(`✗ Deabonnieren fehlgeschlagen: ${error.message}`, 'error');
console.error(error);
}
};
// Send Test Notification
window.sendTestNotification = async function() {
if (!webPush) {
log('✗ Bitte zuerst initialisieren', 'error');
return;
}
try {
log('Sende Test-Benachrichtigung...', 'info');
const result = await webPush.sendTestNotification(
'Test Benachrichtigung',
'Dies ist eine Test-Benachrichtigung vom WebPush Demo! 🎉'
);
log('✓ Test-Benachrichtigung gesendet!', 'success');
log(`Response: ${JSON.stringify(result)}`, 'info');
} catch (error) {
log(`✗ Senden fehlgeschlagen: ${error.message}`, 'error');
console.error(error);
}
};
// Check browser support on load
document.addEventListener('DOMContentLoaded', () => {
// First check: Browser capabilities (synchronous)
const hasServiceWorker = 'serviceWorker' in navigator;
const hasPushManager = 'PushManager' in window;
const hasNotification = 'Notification' in window;
console.log('=== WebPush Browser Check ===');
console.log('Service Worker support:', hasServiceWorker);
console.log('Push Manager support:', hasPushManager);
console.log('Notification support:', hasNotification);
console.log('HTTPS:', location.protocol === 'https:');
console.log('Browser:', navigator.userAgent.split(' ').slice(-2).join(' '));
// Log browser capabilities immediately
if (!hasServiceWorker) {
log('✗ Browser unterstützt keine Service Workers', 'error');
} else {
log('✓ Service Workers verfügbar', 'success');
}
if (!hasPushManager) {
log('✗ Browser unterstützt keine Push API', 'error');
} else {
log('✓ Push API verfügbar', 'success');
}
if (!hasNotification) {
log('✗ Browser unterstützt keine Notifications', 'error');
} else {
log('✓ Notification API verfügbar', 'success');
}
// Wait for main.js to initialize
setTimeout(() => {
console.log('=== WebPushManager Check ===');
console.log('window.webPushManager:', window.webPushManager);
if (!window.webPushManager) {
log('✗ WebPushManager nicht initialisiert', 'error');
if (!hasServiceWorker || !hasPushManager) {
log('💡 Grund: Browser unterstützt nicht alle erforderlichen APIs', 'info');
} else {
log('💡 Grund: main.js hat WebPushManager nicht initialisiert', 'info');
log('Tipp: Prüfe Browser Console für Fehler in main.js', 'info');
}
document.getElementById('btn-init').disabled = true;
document.getElementById('subscription-status').textContent = 'Nicht verfügbar';
document.getElementById('subscription-status').className = 'status-value status-unsubscribed';
} else {
log('✓ WebPushManager erfolgreich geladen', 'success');
log('💡 Klicke auf "WebPush initialisieren" um zu starten', 'info');
}
}, 500); // Wait 500ms for main.js to load
});
</script>
</body>
</html>