Keks notice!

This commit is contained in:
2025-09-05 07:42:07 +02:00
parent b0b5149069
commit 4d00be8127
24 changed files with 1810 additions and 7 deletions

View File

@@ -6,6 +6,16 @@ let currentData = [];
document.addEventListener('DOMContentLoaded', function() {
checkAuth();
loadStatistics();
// Add cookie settings button functionality
const cookieSettingsBtn = document.getElementById('cookie-settings-footer');
if (cookieSettingsBtn) {
cookieSettingsBtn.addEventListener('click', function() {
if (window.cookieConsent) {
window.cookieConsent.resetConsent();
}
});
}
loadPageStatistics();
setupEventListeners();
});

View File

@@ -78,4 +78,14 @@ document.addEventListener('keypress', function(e) {
// Fokus auf erstes Eingabefeld
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('username').focus();
// Add cookie settings button functionality
const cookieSettingsBtn = document.getElementById('cookie-settings-footer');
if (cookieSettingsBtn) {
cookieSettingsBtn.addEventListener('click', function() {
if (window.cookieConsent) {
window.cookieConsent.resetConsent();
}
});
}
});

601
public/js/cookie-consent.js Normal file
View File

@@ -0,0 +1,601 @@
// Cookie Consent Management
class CookieConsent {
constructor() {
this.cookieName = 'ninjacross_cookie_consent';
this.cookieSettingsName = 'ninjacross_cookie_settings';
this.consentGiven = false;
this.settings = {
necessary: true, // Always true, can't be disabled
functional: false,
analytics: false
};
this.init();
}
init() {
// Check if consent was already given
const savedConsent = this.getCookie(this.cookieName);
const savedSettings = this.getCookie(this.cookieSettingsName);
if (savedConsent === 'true') {
this.consentGiven = true;
if (savedSettings) {
this.settings = { ...this.settings, ...JSON.parse(savedSettings) };
}
this.applySettings();
} else {
this.showConsentBanner();
}
}
showConsentBanner() {
// Don't show banner if already shown
if (document.getElementById('cookie-consent-banner')) {
return;
}
const banner = document.createElement('div');
banner.id = 'cookie-consent-banner';
banner.innerHTML = `
<div class="cookie-banner">
<div class="cookie-content">
<div class="cookie-icon">🍪</div>
<div class="cookie-text">
<h3>Cookie-Einstellungen</h3>
<p>Wir verwenden Cookies, um Ihnen die beste Erfahrung auf unserer Website zu bieten. Einige sind notwendig, andere helfen uns, die Website zu verbessern.</p>
</div>
</div>
<div class="cookie-actions">
<button id="cookie-settings-btn" class="btn-cookie-settings">Einstellungen</button>
<button id="cookie-accept-all" class="btn-cookie-accept">Alle akzeptieren</button>
<button id="cookie-accept-necessary" class="btn-cookie-necessary">Nur notwendige</button>
</div>
</div>
`;
// Add styles
const style = document.createElement('style');
style.textContent = `
#cookie-consent-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
color: white;
z-index: 10000;
box-shadow: 0 -4px 20px rgba(0,0,0,0.3);
animation: slideUp 0.3s ease-out;
}
@keyframes slideUp {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
.cookie-banner {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px;
max-width: 1200px;
margin: 0 auto;
gap: 20px;
}
.cookie-content {
display: flex;
align-items: center;
gap: 15px;
flex: 1;
}
.cookie-icon {
font-size: 2rem;
flex-shrink: 0;
}
.cookie-text h3 {
margin: 0 0 5px 0;
font-size: 1.1rem;
color: white;
}
.cookie-text p {
margin: 0;
font-size: 0.9rem;
opacity: 0.9;
line-height: 1.4;
}
.cookie-actions {
display: flex;
gap: 10px;
flex-shrink: 0;
}
.btn-cookie-settings,
.btn-cookie-accept,
.btn-cookie-necessary {
padding: 10px 16px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
font-weight: 500;
transition: all 0.2s ease;
}
.btn-cookie-settings {
background: rgba(255,255,255,0.2);
color: white;
border: 1px solid rgba(255,255,255,0.3);
}
.btn-cookie-settings:hover {
background: rgba(255,255,255,0.3);
}
.btn-cookie-accept {
background: #10b981;
color: white;
}
.btn-cookie-accept:hover {
background: #059669;
}
.btn-cookie-necessary {
background: #6b7280;
color: white;
}
.btn-cookie-necessary:hover {
background: #4b5563;
}
@media (max-width: 768px) {
.cookie-banner {
flex-direction: column;
text-align: center;
gap: 15px;
}
.cookie-content {
flex-direction: column;
text-align: center;
}
.cookie-actions {
flex-wrap: wrap;
justify-content: center;
}
}
`;
document.head.appendChild(style);
document.body.appendChild(banner);
// Add event listeners
document.getElementById('cookie-accept-all').addEventListener('click', () => {
this.acceptAll();
});
document.getElementById('cookie-accept-necessary').addEventListener('click', () => {
this.acceptNecessary();
});
document.getElementById('cookie-settings-btn').addEventListener('click', () => {
this.showSettingsModal();
});
}
showSettingsModal() {
// Remove banner
const banner = document.getElementById('cookie-consent-banner');
if (banner) {
banner.remove();
}
// Create modal
const modal = document.createElement('div');
modal.id = 'cookie-settings-modal';
modal.innerHTML = `
<div class="cookie-modal-overlay">
<div class="cookie-modal">
<div class="cookie-modal-header">
<h2>🍪 Cookie-Einstellungen</h2>
<button id="cookie-modal-close" class="btn-close">&times;</button>
</div>
<div class="cookie-modal-content">
<p>Wählen Sie aus, welche Cookies Sie zulassen möchten:</p>
<div class="cookie-category">
<div class="cookie-category-header">
<h3>Notwendige Cookies</h3>
<label class="cookie-toggle">
<input type="checkbox" id="necessary-cookies" checked disabled>
<span class="toggle-slider"></span>
</label>
</div>
<p>Diese Cookies sind für die Grundfunktionen der Website erforderlich und können nicht deaktiviert werden.</p>
</div>
<div class="cookie-category">
<div class="cookie-category-header">
<h3>Funktionale Cookies</h3>
<label class="cookie-toggle">
<input type="checkbox" id="functional-cookies" ${this.settings.functional ? 'checked' : ''}>
<span class="toggle-slider"></span>
</label>
</div>
<p>Diese Cookies ermöglichen erweiterte Funktionen wie Benutzeranmeldung und Einstellungen.</p>
</div>
<div class="cookie-category">
<div class="cookie-category-header">
<h3>Analyse-Cookies</h3>
<label class="cookie-toggle">
<input type="checkbox" id="analytics-cookies" ${this.settings.analytics ? 'checked' : ''}>
<span class="toggle-slider"></span>
</label>
</div>
<p>Diese Cookies helfen uns zu verstehen, wie Besucher mit der Website interagieren.</p>
</div>
</div>
<div class="cookie-modal-footer">
<button id="cookie-save-settings" class="btn-save">Einstellungen speichern</button>
<button id="cookie-accept-all-modal" class="btn-accept-all">Alle akzeptieren</button>
</div>
</div>
</div>
`;
// Add modal styles
const modalStyle = document.createElement('style');
modalStyle.textContent = `
.cookie-modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 10001;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.cookie-modal {
background: white;
border-radius: 12px;
max-width: 600px;
width: 100%;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 20px 40px rgba(0,0,0,0.3);
animation: modalSlideIn 0.3s ease-out;
}
@keyframes modalSlideIn {
from { transform: scale(0.9); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
.cookie-modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
border-bottom: 1px solid #e2e8f0;
}
.cookie-modal-header h2 {
margin: 0;
color: #1e3c72;
}
.btn-close {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: #6b7280;
padding: 0;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
}
.btn-close:hover {
color: #374151;
}
.cookie-modal-content {
padding: 20px;
}
.cookie-category {
margin-bottom: 20px;
padding: 15px;
border: 1px solid #e2e8f0;
border-radius: 8px;
}
.cookie-category-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.cookie-category-header h3 {
margin: 0;
color: #1e3c72;
font-size: 1.1rem;
}
.cookie-category p {
margin: 0;
color: #6b7280;
font-size: 0.9rem;
line-height: 1.4;
}
.cookie-toggle {
position: relative;
display: inline-block;
width: 50px;
height: 24px;
}
.cookie-toggle input {
opacity: 0;
width: 0;
height: 0;
}
.toggle-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .4s;
border-radius: 24px;
}
.toggle-slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background-color: white;
transition: .4s;
border-radius: 50%;
}
.cookie-toggle input:checked + .toggle-slider {
background-color: #1e3c72;
}
.cookie-toggle input:checked + .toggle-slider:before {
transform: translateX(26px);
}
.cookie-toggle input:disabled + .toggle-slider {
background-color: #10b981;
cursor: not-allowed;
}
.cookie-modal-footer {
padding: 20px;
border-top: 1px solid #e2e8f0;
display: flex;
gap: 10px;
justify-content: flex-end;
}
.btn-save, .btn-accept-all {
padding: 10px 20px;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s ease;
}
.btn-save {
background: #1e3c72;
color: white;
}
.btn-save:hover {
background: #2a5298;
}
.btn-accept-all {
background: #10b981;
color: white;
}
.btn-accept-all:hover {
background: #059669;
}
@media (max-width: 768px) {
.cookie-modal {
margin: 10px;
max-height: 90vh;
}
.cookie-modal-footer {
flex-direction: column;
}
.btn-save, .btn-accept-all {
width: 100%;
}
}
`;
document.head.appendChild(modalStyle);
document.body.appendChild(modal);
// Add event listeners
document.getElementById('cookie-modal-close').addEventListener('click', () => {
modal.remove();
this.showConsentBanner();
});
document.getElementById('cookie-save-settings').addEventListener('click', () => {
this.saveSettings();
modal.remove();
});
document.getElementById('cookie-accept-all-modal').addEventListener('click', () => {
this.acceptAll();
modal.remove();
});
// Close on overlay click
modal.querySelector('.cookie-modal-overlay').addEventListener('click', (e) => {
if (e.target === e.currentTarget) {
modal.remove();
this.showConsentBanner();
}
});
}
saveSettings() {
this.settings.functional = document.getElementById('functional-cookies').checked;
this.settings.analytics = document.getElementById('analytics-cookies').checked;
this.setCookie(this.cookieName, 'true', 365);
this.setCookie(this.cookieSettingsName, JSON.stringify(this.settings), 365);
this.consentGiven = true;
this.applySettings();
}
acceptAll() {
this.settings.functional = true;
this.settings.analytics = true;
this.setCookie(this.cookieName, 'true', 365);
this.setCookie(this.cookieSettingsName, JSON.stringify(this.settings), 365);
this.consentGiven = true;
this.applySettings();
}
acceptNecessary() {
this.settings.functional = false;
this.settings.analytics = false;
this.setCookie(this.cookieName, 'true', 365);
this.setCookie(this.cookieSettingsName, JSON.stringify(this.settings), 365);
this.consentGiven = true;
this.applySettings();
}
applySettings() {
// Remove banner if exists
const banner = document.getElementById('cookie-consent-banner');
if (banner) {
banner.remove();
}
// Apply functional cookies
if (this.settings.functional) {
// Enable functional features
console.log('Functional cookies enabled');
} else {
// Disable functional features
console.log('Functional cookies disabled');
}
// Apply analytics cookies
if (this.settings.analytics) {
// Enable analytics
console.log('Analytics cookies enabled');
this.enableAnalytics();
} else {
// Disable analytics
console.log('Analytics cookies disabled');
this.disableAnalytics();
}
}
enableAnalytics() {
// Enable page tracking
if (typeof trackPageView === 'function') {
trackPageView('main_page_visit');
}
}
disableAnalytics() {
// Disable page tracking
console.log('Analytics disabled by user choice');
}
setCookie(name, value, days) {
const expires = new Date();
expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));
document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/;SameSite=Lax`;
}
getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
// Public method to check if consent was given
hasConsent() {
return this.consentGiven;
}
// Public method to get current settings
getSettings() {
return { ...this.settings };
}
// Public method to reset consent
resetConsent() {
this.setCookie(this.cookieName, '', -1);
this.setCookie(this.cookieSettingsName, '', -1);
this.consentGiven = false;
this.settings = {
necessary: true,
functional: false,
analytics: false
};
this.showConsentBanner();
}
}
// Initialize cookie consent when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
window.cookieConsent = new CookieConsent();
});
// Export for use in other scripts
if (typeof module !== 'undefined' && module.exports) {
module.exports = CookieConsent;
}

View File

@@ -575,3 +575,16 @@ function showMessage(containerId, message, type) {
const container = document.getElementById(containerId);
container.innerHTML = `<div class="message ${type}">${message}</div>`;
}
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
// Add cookie settings button functionality
const cookieSettingsBtn = document.getElementById('cookie-settings-footer');
if (cookieSettingsBtn) {
cookieSettingsBtn.addEventListener('click', function() {
if (window.cookieConsent) {
window.cookieConsent.resetConsent();
}
});
}
});

View File

@@ -557,4 +557,14 @@ function toggleTokenFields() {
}
});
}
// Add cookie settings button functionality
const cookieSettingsBtn = document.getElementById('cookie-settings-footer');
if (cookieSettingsBtn) {
cookieSettingsBtn.addEventListener('click', function() {
if (window.cookieConsent) {
window.cookieConsent.resetConsent();
}
});
}
});

View File

@@ -497,4 +497,14 @@ function startAutoRefresh() {
document.addEventListener('DOMContentLoaded', function() {
init();
startAutoRefresh();
// Add cookie settings button functionality
const cookieSettingsBtn = document.getElementById('cookie-settings-footer');
if (cookieSettingsBtn) {
cookieSettingsBtn.addEventListener('click', function() {
if (window.cookieConsent) {
window.cookieConsent.resetConsent();
}
});
}
});

View File

@@ -94,6 +94,16 @@ function setupEventListeners() {
// Handle Google OAuth
document.getElementById('googleSignInBtn').addEventListener('click', signInWithGoogle);
// Cookie settings button
const cookieSettingsBtn = document.getElementById('cookie-settings-footer');
if (cookieSettingsBtn) {
cookieSettingsBtn.addEventListener('click', function() {
if (window.cookieConsent) {
window.cookieConsent.resetConsent();
}
});
}
// Handle login
document.getElementById('loginFormElement').addEventListener('submit', async (e) => {
e.preventDefault();

View File

@@ -164,6 +164,18 @@ if (accessToken && refreshToken) {
setSession();
}
// Add cookie settings button functionality
document.addEventListener('DOMContentLoaded', function() {
const cookieSettingsBtn = document.getElementById('cookie-settings-footer');
if (cookieSettingsBtn) {
cookieSettingsBtn.addEventListener('click', function() {
if (window.cookieConsent) {
window.cookieConsent.resetConsent();
}
});
}
});
// Passwort-Sicherheitshinweise
newPasswordInput.addEventListener('input', function() {
const password = this.value;