Merge branch 'main' of https://git.clickcandit.com/marwinm/website
This commit is contained in:
2
.env
2
.env
@@ -4,7 +4,7 @@
|
||||
# Flask
|
||||
FLASK_APP=app.py
|
||||
FLASK_DEBUG=1
|
||||
SECRET_KEY=your-secret-key-replace-in-production
|
||||
SECRET_KEY=ETMyh4JfBfvpZSscqfuzjCOAvelm5lEju
|
||||
|
||||
# OpenAI API
|
||||
OPENAI_API_KEY=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
|
||||
|
||||
@@ -250,6 +250,36 @@
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.profile-tab.active {
|
||||
color: white;
|
||||
background: rgba(179, 143, 255, 0.2);
|
||||
border-bottom: 3px solid rgba(179, 143, 255, 0.7);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.profile-tab.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, #8B5CF6, #6366F1);
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
/* Animation für Tab-Inhalte */
|
||||
.tab-content {
|
||||
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.tab-content.hidden {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
/* Statistik-Elemente - verkleinert */
|
||||
.stat-item {
|
||||
padding: 0.75rem !important;
|
||||
@@ -322,7 +352,9 @@
|
||||
<span><i class="fas fa-map-marker-alt"></i> {{ user.location if user.location else 'Kein Standort angegeben' }}</span>
|
||||
<span><i class="fas fa-calendar-alt"></i> Mitglied seit {{ user.created_at.strftime('%d.%m.%Y') }}</span>
|
||||
</div>
|
||||
<button class="edit-profile-btn">Profil bearbeiten</button>
|
||||
<button class="edit-profile-btn mt-4 bg-purple-600 hover:bg-purple-700 text-white font-semibold py-2 px-4 rounded-lg transition-all duration-300 flex items-center">
|
||||
<i class="fas fa-user-edit mr-2"></i> Profil bearbeiten
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -534,16 +566,25 @@
|
||||
<div class="tab-content hidden" id="collections-tab">
|
||||
<div id="collections-container">
|
||||
{% if collections %}
|
||||
{% for collection in collections %}
|
||||
<div class="collection-item">
|
||||
<h3>{{ collection.title }}</h3>
|
||||
<p>{{ collection.description }}</p>
|
||||
<div class="collection-meta">
|
||||
<span>{{ collection.thoughts_count }} Gedanken</span>
|
||||
<span>{{ collection.date }}</span>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{% for collection in collections %}
|
||||
<div class="collection-item bg-opacity-70 rounded-xl overflow-hidden border border-gray-700/60 bg-gray-800/80 transition-all duration-300 hover:transform hover:scale-105 hover:shadow-lg">
|
||||
<div class="p-5">
|
||||
<h3 class="text-xl font-bold mb-2 text-purple-400">{{ collection.title }}</h3>
|
||||
<p class="mb-4 text-sm text-gray-300">{{ collection.description }}</p>
|
||||
<div class="flex justify-between items-center text-xs text-gray-400">
|
||||
<span>{{ collection.thoughts_count }} Gedanken</span>
|
||||
<span>{{ collection.date }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-3 border-t border-gray-700/60 bg-gray-900/80 flex justify-center">
|
||||
<a href="#" class="text-purple-400 hover:text-purple-300 transition-colors">
|
||||
<i class="fas fa-eye mr-1"></i> Anzeigen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-folder-open text-5xl text-gray-400 mb-4"></i>
|
||||
@@ -557,27 +598,29 @@
|
||||
<div class="tab-content hidden" id="connections-tab">
|
||||
<div id="connections-container">
|
||||
{% if connections %}
|
||||
{% for connection in connections %}
|
||||
<div class="connection-item">
|
||||
<div class="connection-nodes">
|
||||
<div class="connection-node">
|
||||
<h4>{{ connection.source.title }}</h4>
|
||||
<p>{{ connection.source.excerpt }}</p>
|
||||
<div class="grid grid-cols-1 gap-6">
|
||||
{% for connection in connections %}
|
||||
<div class="connection-item bg-opacity-70 rounded-xl p-4 border border-gray-700/60 bg-gray-800/80 transition-all duration-300 hover:bg-gray-800/95">
|
||||
<div class="connection-nodes flex items-stretch">
|
||||
<div class="connection-node flex-1 p-4 rounded-lg bg-gray-900/80 text-white">
|
||||
<h4 class="font-semibold mb-1">{{ connection.source.title }}</h4>
|
||||
<p class="text-sm text-gray-400">{{ connection.source.excerpt }}</p>
|
||||
</div>
|
||||
<div class="connection-type flex flex-col items-center justify-center px-4">
|
||||
<i class="fas fa-arrow-right text-purple-400 mb-1"></i>
|
||||
<span class="text-xs text-gray-500">{{ connection.relation_type }}</span>
|
||||
</div>
|
||||
<div class="connection-node flex-1 p-4 rounded-lg bg-gray-900/80 text-white">
|
||||
<h4 class="font-semibold mb-1">{{ connection.target.title }}</h4>
|
||||
<p class="text-sm text-gray-400">{{ connection.target.excerpt }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="connection-type">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
<span>{{ connection.relation_type }}</span>
|
||||
</div>
|
||||
<div class="connection-node">
|
||||
<h4>{{ connection.target.title }}</h4>
|
||||
<p>{{ connection.target.excerpt }}</p>
|
||||
<div class="connection-meta mt-2 text-right">
|
||||
<span class="text-xs text-gray-500">{{ connection.date }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="connection-meta">
|
||||
<span>{{ connection.date }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-center py-12">
|
||||
<i class="fas fa-project-diagram text-5xl text-gray-400 mb-4"></i>
|
||||
@@ -590,54 +633,50 @@
|
||||
|
||||
<div class="tab-content hidden" id="settings-tab">
|
||||
<!-- Einstellungs-Tab-Inhalt -->
|
||||
<div class="settings-card">
|
||||
<div class="settings-card-header">Profilinformationen</div>
|
||||
<div class="settings-card bg-white/10 backdrop-blur-md rounded-xl p-6 mb-6 border border-white/10">
|
||||
<div class="settings-card-header text-xl font-bold mb-4 text-purple-300">Profilinformationen</div>
|
||||
<div class="settings-card-body">
|
||||
<div class="settings-group">
|
||||
<label class="settings-label" for="name">Name</label>
|
||||
<input type="text" id="name" class="settings-input" value="{{ user.name }}" />
|
||||
<div class="settings-group mb-4">
|
||||
<label class="settings-label block text-gray-300 mb-2" for="bio">Über mich</label>
|
||||
<textarea id="bio" class="settings-input w-full bg-gray-800/60 border border-gray-700/60 text-white rounded-lg p-3 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all" rows="4">{{ user.bio }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="settings-label" for="bio">Über mich</label>
|
||||
<textarea id="bio" class="settings-input" rows="4">{{ user.bio }}</textarea>
|
||||
<div class="settings-group mb-4">
|
||||
<label class="settings-label block text-gray-300 mb-2" for="location">Standort</label>
|
||||
<input type="text" id="location" class="settings-input w-full bg-gray-800/60 border border-gray-700/60 text-white rounded-lg p-3 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all" value="{{ user.location }}" />
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="settings-label" for="location">Standort</label>
|
||||
<input type="text" id="location" class="settings-input" value="{{ user.location }}" />
|
||||
<div class="settings-group mb-4">
|
||||
<label class="settings-label block text-gray-300 mb-2" for="website">Website</label>
|
||||
<input type="url" id="website" class="settings-input w-full bg-gray-800/60 border border-gray-700/60 text-white rounded-lg p-3 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all" value="{{ user.website }}" />
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="settings-label" for="website">Website</label>
|
||||
<input type="url" id="website" class="settings-input" value="{{ user.website }}" />
|
||||
</div>
|
||||
|
||||
<button class="profile-action-btn primary mt-4">
|
||||
<button id="save-profile-btn" class="profile-action-btn primary mt-4">
|
||||
<i class="fas fa-save mr-1"></i> Speichern
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-card">
|
||||
<div class="settings-card-header">Datenschutz und Sicherheit</div>
|
||||
<div class="settings-card bg-white/10 backdrop-blur-md rounded-xl p-6 mb-6 border border-white/10">
|
||||
<div class="settings-card-header text-xl font-bold mb-4 text-purple-300">Datenschutz und Sicherheit</div>
|
||||
<div class="settings-card-body">
|
||||
<div class="settings-group">
|
||||
<label class="settings-label" for="email">E-Mail-Adresse</label>
|
||||
<input type="email" id="email" class="settings-input" value="{{ user.email }}" />
|
||||
<div class="settings-group mb-4">
|
||||
<label class="settings-label block text-gray-300 mb-2" for="email">E-Mail-Adresse</label>
|
||||
<input type="email" id="email" class="settings-input w-full bg-gray-800/60 border border-gray-700/60 text-white rounded-lg p-3 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all" value="{{ user.email }}" readonly />
|
||||
<p class="text-xs text-gray-500 mt-1">Die E-Mail-Adresse kann derzeit nicht geändert werden.</p>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="settings-label" for="password">Neues Passwort</label>
|
||||
<input type="password" id="password" class="settings-input" placeholder="Neues Passwort eingeben" />
|
||||
<div class="settings-group mb-4">
|
||||
<label class="settings-label block text-gray-300 mb-2" for="password">Neues Passwort</label>
|
||||
<input type="password" id="password" class="settings-input w-full bg-gray-800/60 border border-gray-700/60 text-white rounded-lg p-3 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all" placeholder="Neues Passwort eingeben" />
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label class="settings-label" for="password_confirm">Passwort bestätigen</label>
|
||||
<input type="password" id="password_confirm" class="settings-input" placeholder="Passwort wiederholen" />
|
||||
<div class="settings-group mb-4">
|
||||
<label class="settings-label block text-gray-300 mb-2" for="password_confirm">Passwort bestätigen</label>
|
||||
<input type="password" id="password_confirm" class="settings-input w-full bg-gray-800/60 border border-gray-700/60 text-white rounded-lg p-3 focus:ring-2 focus:ring-purple-500 focus:border-transparent transition-all" placeholder="Passwort wiederholen" />
|
||||
</div>
|
||||
|
||||
<button class="profile-action-btn primary mt-4">
|
||||
<button id="update-password-btn" class="profile-action-btn primary mt-4">
|
||||
<i class="fas fa-lock mr-1"></i> Passwort aktualisieren
|
||||
</button>
|
||||
</div>
|
||||
@@ -655,6 +694,12 @@
|
||||
const tabs = document.querySelectorAll('.profile-tab');
|
||||
const tabContents = document.querySelectorAll('.tab-content');
|
||||
|
||||
// Standardmäßig den ersten Tab aktivieren
|
||||
if (tabs.length > 0 && tabContents.length > 0) {
|
||||
tabs[0].classList.add('active');
|
||||
tabContents[0].classList.remove('hidden');
|
||||
}
|
||||
|
||||
tabs.forEach(tab => {
|
||||
tab.addEventListener('click', function() {
|
||||
// Alle Tabs deaktivieren
|
||||
@@ -706,6 +751,8 @@
|
||||
}
|
||||
|
||||
countElement.textContent = count;
|
||||
|
||||
// Hier könnte ein AJAX-Request erfolgen, um die Reaktion zu speichern
|
||||
});
|
||||
});
|
||||
|
||||
@@ -726,7 +773,7 @@
|
||||
const avatarEditBtn = document.querySelector('.avatar-edit');
|
||||
if (avatarEditBtn) {
|
||||
avatarEditBtn.addEventListener('click', function() {
|
||||
// Dateiauwahl öffnen
|
||||
// Dateiauswahl öffnen
|
||||
const fileInput = document.createElement('input');
|
||||
fileInput.type = 'file';
|
||||
fileInput.accept = 'image/*';
|
||||
@@ -738,13 +785,27 @@
|
||||
fileInput.addEventListener('change', function() {
|
||||
if (this.files && this.files[0]) {
|
||||
// Anzeigen des gewählten Bildes
|
||||
const avatarImg = document.querySelector('.avatar');
|
||||
const avatarImg = document.querySelector('.avatar') || document.querySelector('.default-avatar');
|
||||
|
||||
// FileReader zum Einlesen des Bildes
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
// Vorschau anzeigen
|
||||
avatarImg.src = e.target.result;
|
||||
if (avatarImg.tagName.toLowerCase() === 'img') {
|
||||
avatarImg.src = e.target.result;
|
||||
} else {
|
||||
// Falls es ein div mit SVG ist, ersetzen wir es durch ein Image
|
||||
const imgElement = document.createElement('img');
|
||||
imgElement.src = e.target.result;
|
||||
imgElement.classList.add('avatar');
|
||||
imgElement.alt = "Profilbild";
|
||||
|
||||
const avatarContainer = document.querySelector('.avatar-container');
|
||||
if (avatarContainer) {
|
||||
avatarContainer.innerHTML = '';
|
||||
avatarContainer.appendChild(imgElement);
|
||||
}
|
||||
}
|
||||
|
||||
// Avatar-URL im Einstellungsbereich speichern
|
||||
const avatarUrlInput = document.createElement('input');
|
||||
@@ -778,119 +839,123 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Einstellungen-Formular-Handling
|
||||
const saveSettingsBtn = document.querySelectorAll('.settings-card .profile-action-btn.primary');
|
||||
// Profil Speichern-Button
|
||||
const saveProfileBtn = document.getElementById('save-profile-btn');
|
||||
|
||||
saveSettingsBtn.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const isPasswordUpdate = this.textContent.includes('Passwort');
|
||||
if (saveProfileBtn) {
|
||||
saveProfileBtn.addEventListener('click', function() {
|
||||
// Sammle Daten aus den Eingabefeldern
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'update_profile');
|
||||
formData.append('bio', document.getElementById('bio').value || '');
|
||||
formData.append('location', document.getElementById('location').value || '');
|
||||
formData.append('website', document.getElementById('website').value || '');
|
||||
|
||||
// Passwort-Update
|
||||
if (isPasswordUpdate) {
|
||||
const currentPassword = document.getElementById('password').value;
|
||||
const newPassword = document.getElementById('password_confirm').value;
|
||||
|
||||
if (!currentPassword || !newPassword) {
|
||||
showNotification('Bitte fülle alle Passwortfelder aus', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// AJAX-Anfrage senden
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'update_password');
|
||||
formData.append('current_password', currentPassword);
|
||||
formData.append('new_password', newPassword);
|
||||
formData.append('confirm_password', newPassword);
|
||||
|
||||
// Visuelle Rückmeldung
|
||||
const originalText = this.innerHTML;
|
||||
this.innerHTML = '<i class="fas fa-circle-notch fa-spin mr-1"></i> Speichern...';
|
||||
this.disabled = true;
|
||||
|
||||
fetch('{{ url_for("settings") }}', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.catch(error => {
|
||||
console.error('Fehler beim Aktualisieren des Passworts:', error);
|
||||
return { success: false, message: 'Netzwerkfehler. Bitte versuche es erneut.' };
|
||||
})
|
||||
.then(data => {
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
|
||||
if (data && data.success) {
|
||||
showNotification('Passwort erfolgreich aktualisiert!', 'success');
|
||||
document.getElementById('password').value = '';
|
||||
document.getElementById('password_confirm').value = '';
|
||||
} else {
|
||||
showNotification(data?.message || 'Fehler beim Aktualisieren des Passworts', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
// Profil-Update
|
||||
else {
|
||||
// Sammle Daten aus den Eingabefeldern
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'update_profile');
|
||||
formData.append('bio', document.getElementById('bio').value || '');
|
||||
formData.append('location', document.getElementById('location').value || '');
|
||||
formData.append('website', document.getElementById('website').value || '');
|
||||
|
||||
// Avatar hinzufügen, falls vorhanden
|
||||
const avatarUrlInput = document.getElementById('avatar_url');
|
||||
if (avatarUrlInput) {
|
||||
formData.append('avatar_url', avatarUrlInput.value);
|
||||
}
|
||||
|
||||
// Visuelle Rückmeldung
|
||||
const originalText = this.innerHTML;
|
||||
this.innerHTML = '<i class="fas fa-circle-notch fa-spin mr-1"></i> Speichern...';
|
||||
this.disabled = true;
|
||||
|
||||
// AJAX-Anfrage senden
|
||||
fetch('{{ url_for("settings") }}', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Fehler beim Speichern');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Fehler beim Speichern der Profileinstellungen:', error);
|
||||
return { success: false, message: 'Netzwerkfehler. Bitte versuche es erneut.' };
|
||||
})
|
||||
.then(data => {
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
|
||||
if (data && data.success) {
|
||||
// Erfolgsanimation
|
||||
showNotification('Profil erfolgreich aktualisiert!', 'success');
|
||||
|
||||
// UI aktualisieren ohne Neuladen
|
||||
const bioElement = document.querySelector('.user-bio');
|
||||
const locationElement = document.querySelector('.user-meta span:first-child');
|
||||
|
||||
if (bioElement) {
|
||||
bioElement.textContent = document.getElementById('bio').value || 'Keine Bio vorhanden. Klicke auf bearbeiten, um eine hinzuzufügen.';
|
||||
}
|
||||
|
||||
if (locationElement) {
|
||||
const location = document.getElementById('location').value;
|
||||
locationElement.innerHTML = `<i class="fas fa-map-marker-alt"></i> ${location || 'Kein Standort angegeben'}`;
|
||||
}
|
||||
} else {
|
||||
showNotification(data?.message || 'Fehler beim Aktualisieren des Profils', 'error');
|
||||
}
|
||||
});
|
||||
// Avatar hinzufügen, falls vorhanden
|
||||
const avatarUrlInput = document.getElementById('avatar_url');
|
||||
if (avatarUrlInput) {
|
||||
formData.append('avatar_url', avatarUrlInput.value);
|
||||
}
|
||||
|
||||
// Visuelle Rückmeldung
|
||||
const originalText = this.innerHTML;
|
||||
this.innerHTML = '<i class="fas fa-circle-notch fa-spin mr-1"></i> Speichern...';
|
||||
this.disabled = true;
|
||||
|
||||
// AJAX-Anfrage senden
|
||||
fetch('{{ url_for("settings") }}', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Fehler beim Speichern');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Fehler beim Speichern der Profileinstellungen:', error);
|
||||
return { success: false, message: 'Netzwerkfehler. Bitte versuche es erneut.' };
|
||||
})
|
||||
.then(data => {
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
|
||||
if (data && data.success) {
|
||||
// Erfolgsanimation
|
||||
showNotification('Profil erfolgreich aktualisiert!', 'success');
|
||||
|
||||
// UI aktualisieren ohne Neuladen
|
||||
const bioElement = document.querySelector('.user-bio');
|
||||
const locationElement = document.querySelector('.user-meta span:first-child');
|
||||
|
||||
if (bioElement) {
|
||||
bioElement.textContent = document.getElementById('bio').value || 'Keine Bio vorhanden. Klicke auf bearbeiten, um eine hinzuzufügen.';
|
||||
}
|
||||
|
||||
if (locationElement) {
|
||||
const location = document.getElementById('location').value;
|
||||
locationElement.innerHTML = `<i class="fas fa-map-marker-alt"></i> ${location || 'Kein Standort angegeben'}`;
|
||||
}
|
||||
} else {
|
||||
showNotification(data?.message || 'Fehler beim Aktualisieren des Profils', 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Passwort Update Button
|
||||
const updatePasswordBtn = document.getElementById('update-password-btn');
|
||||
|
||||
if (updatePasswordBtn) {
|
||||
updatePasswordBtn.addEventListener('click', function() {
|
||||
const currentPassword = document.getElementById('password').value;
|
||||
const newPassword = document.getElementById('password_confirm').value;
|
||||
|
||||
if (!currentPassword || !newPassword) {
|
||||
showNotification('Bitte fülle alle Passwortfelder aus', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentPassword !== newPassword) {
|
||||
showNotification('Die Passwörter stimmen nicht überein', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// AJAX-Anfrage senden
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'update_password');
|
||||
formData.append('new_password', newPassword);
|
||||
formData.append('confirm_password', newPassword);
|
||||
|
||||
// Visuelle Rückmeldung
|
||||
const originalText = this.innerHTML;
|
||||
this.innerHTML = '<i class="fas fa-circle-notch fa-spin mr-1"></i> Aktualisieren...';
|
||||
this.disabled = true;
|
||||
|
||||
fetch('{{ url_for("settings") }}', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.catch(error => {
|
||||
console.error('Fehler beim Aktualisieren des Passworts:', error);
|
||||
return { success: false, message: 'Netzwerkfehler. Bitte versuche es erneut.' };
|
||||
})
|
||||
.then(data => {
|
||||
this.innerHTML = originalText;
|
||||
this.disabled = false;
|
||||
|
||||
if (data && data.success) {
|
||||
showNotification('Passwort erfolgreich aktualisiert!', 'success');
|
||||
document.getElementById('password').value = '';
|
||||
document.getElementById('password_confirm').value = '';
|
||||
} else {
|
||||
showNotification(data?.message || 'Fehler beim Aktualisieren des Passworts', 'error');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Gedanken-Karten mit Hover-Effekten und Border-Farben
|
||||
const thoughtItems = document.querySelectorAll('.thought-item');
|
||||
@@ -909,7 +974,7 @@
|
||||
// Border-Farben anwenden
|
||||
const borderElem = item.querySelector('.thought-border');
|
||||
if (borderElem && borderElem.dataset.color) {
|
||||
borderElem.style.borderLeftColor = borderElem.dataset.color;
|
||||
borderElem.style.borderLeft = `4px solid ${borderElem.dataset.color}`;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user