Refactor logging in cleanup scripts to use report array for improved output management
Updated various cleanup scripts to replace console.log statements with a report array, enhancing the output handling and allowing for better formatting of messages. This change improves the readability of logs and ensures consistent reporting across different cleanup operations, including database connection status, index management, and summary reports.
This commit is contained in:
@@ -71,7 +71,7 @@ export default {
|
||||
const isOpen = ref(false);
|
||||
|
||||
const handleClose = () => {
|
||||
console.log('Dialog geschlossen');
|
||||
// Reagiere auf das Schließen des Dialogs
|
||||
};
|
||||
|
||||
return { isOpen, handleClose };
|
||||
@@ -163,11 +163,11 @@ export default {
|
||||
const showConfirm = ref(false);
|
||||
|
||||
const handleDelete = () => {
|
||||
console.log('Gelöscht');
|
||||
// Lösche den Eintrag
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
console.log('Abgebrochen');
|
||||
// Brich die Aktion ab
|
||||
};
|
||||
|
||||
return { showConfirm, handleDelete, handleCancel };
|
||||
@@ -307,108 +307,4 @@ toggle();
|
||||
|
||||
Promise-basiertes Composable für Bestätigungsdialoge.
|
||||
|
||||
```javascript
|
||||
import { useConfirm } from '@/composables/useDialog.js';
|
||||
|
||||
const { isOpen, config, confirm, handleConfirm, handleCancel } = useConfirm();
|
||||
|
||||
// Im Template:
|
||||
<ConfirmDialog
|
||||
v-model="isOpen"
|
||||
:title="config.title"
|
||||
:message="config.message"
|
||||
:type="config.type"
|
||||
@confirm="handleConfirm"
|
||||
@cancel="handleCancel"
|
||||
/>
|
||||
|
||||
// In Methoden:
|
||||
async function deleteItem() {
|
||||
const confirmed = await confirm({
|
||||
title: 'Löschen bestätigen',
|
||||
message: 'Wirklich löschen?',
|
||||
type: 'danger'
|
||||
});
|
||||
|
||||
if (confirmed) {
|
||||
// Löschvorgang durchführen
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Dialog-Größen
|
||||
|
||||
| Größe | Breite | Beschreibung |
|
||||
|-------|--------|--------------|
|
||||
| `small` | 400px | Kleine Dialoge (z.B. Bestätigungen) |
|
||||
| `medium` | 600px | Standard-Dialoge |
|
||||
| `large` | 900px | Große Dialoge mit viel Inhalt |
|
||||
| `fullscreen` | 90vw x 90vh | Fast Fullscreen |
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Modale Dialoge verwenden für:
|
||||
- Wichtige Benutzer-Entscheidungen
|
||||
- Formulare, die Fokus erfordern
|
||||
- Warnungen und Fehler
|
||||
- Prozesse, die nicht unterbrochen werden sollten
|
||||
|
||||
### Nicht-modale Dialoge verwenden für:
|
||||
- Zusätzliche Informationen
|
||||
- Tools und Paletten
|
||||
- Mehrere gleichzeitige Arbeitsschritte
|
||||
- Drag & Drop-Workflows
|
||||
|
||||
### Tipps
|
||||
|
||||
1. **Minimieren-Funktion**: Nur bei nicht-modalen Dialogen sinnvoll
|
||||
2. **closeOnOverlay**: Bei wichtigen Formularen auf `false` setzen
|
||||
3. **z-Index**: Bei mehreren nicht-modalen Dialogen unterschiedliche z-Indices verwenden
|
||||
4. **Footer-Slot**: Für Aktions-Buttons verwenden
|
||||
5. **header-actions**: Für kontextspezifische Header-Aktionen
|
||||
|
||||
## Styling
|
||||
|
||||
Die Dialoge verwenden CSS-Variablen für konsistentes Styling:
|
||||
|
||||
- `--primary-color`: Primärfarbe für Header und Buttons
|
||||
- `--primary-hover`: Hover-Farbe
|
||||
- `--border-color`: Rahmenfarbe
|
||||
- `--text-color`: Textfarbe
|
||||
- `--text-muted`: Gedämpfte Textfarbe
|
||||
|
||||
## Migration bestehender Dialoge
|
||||
|
||||
### Alt (individueller Dialog):
|
||||
```vue
|
||||
<div v-if="showDialog" class="modal-overlay" @click.self="closeDialog">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h3>Titel</h3>
|
||||
<button @click="closeDialog">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Inhalt
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### Neu (BaseDialog):
|
||||
```vue
|
||||
<BaseDialog v-model="showDialog" title="Titel">
|
||||
Inhalt
|
||||
</BaseDialog>
|
||||
```
|
||||
|
||||
## Beispiele ansehen
|
||||
|
||||
Die Datei `DialogExamples.vue` enthält vollständige Beispiele für alle Dialog-Typen.
|
||||
|
||||
Route hinzufügen in `router.js`:
|
||||
```javascript
|
||||
import DialogExamples from './components/DialogExamples.vue';
|
||||
|
||||
{ path: '/dialog-examples', component: DialogExamples }
|
||||
```
|
||||
|
||||
```
|
||||
@@ -326,19 +326,19 @@ export default {
|
||||
});
|
||||
|
||||
if (result) {
|
||||
alert('Bestätigt!');
|
||||
// Hier kann ein nutzerfreundlicher Hinweis (z. B. Toast) implementiert werden
|
||||
} else {
|
||||
alert('Abgebrochen!');
|
||||
// Hier kann ein nutzerfreundlicher Hinweis (z. B. Toast) implementiert werden
|
||||
}
|
||||
},
|
||||
|
||||
handleWarningConfirm() {
|
||||
console.log('Warnung bestätigt');
|
||||
// Hier kann ein nutzerfreundlicher Hinweis (z. B. Toast) implementiert werden
|
||||
this.warningConfirm.isOpen = false;
|
||||
},
|
||||
|
||||
handleDelete() {
|
||||
console.log('Eintrag gelöscht');
|
||||
// Hier kann nach erfolgreicher Aktion ein Hinweis angezeigt werden
|
||||
this.dangerConfirm.isOpen = false;
|
||||
},
|
||||
|
||||
|
||||
@@ -99,29 +99,19 @@ export default {
|
||||
},
|
||||
|
||||
insertPinIntoIframe(match) {
|
||||
console.log('🔍 PIN-Einfügen gestartet für Match:', match);
|
||||
console.log('📌 Verfügbare PINs:', {
|
||||
homePin: match.homePin,
|
||||
guestPin: match.guestPin
|
||||
});
|
||||
|
||||
// Versuche direkten Zugriff auf die MatchReportDialog-Komponente
|
||||
const matchReportDialogs = document.querySelectorAll('.match-report-dialog');
|
||||
console.log('🖼️ Gefundene MatchReportDialogs:', matchReportDialogs.length);
|
||||
|
||||
if (matchReportDialogs.length > 0) {
|
||||
// Versuche die insertPinManually Methode aufzurufen
|
||||
console.log('🎯 Versuche direkten Zugriff auf MatchReportDialog');
|
||||
|
||||
// Finde das iframe im aktuellen Dialog
|
||||
const iframe = matchReportDialogs[matchReportDialogs.length - 1].querySelector('iframe');
|
||||
if (iframe) {
|
||||
console.log('✅ Iframe gefunden, versuche PIN-Einfügung');
|
||||
|
||||
try {
|
||||
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
|
||||
if (iframeDoc) {
|
||||
console.log('✅ Direkter DOM-Zugriff möglich');
|
||||
|
||||
// Suche nach PIN-Feldern
|
||||
const pinSelectors = [
|
||||
@@ -137,26 +127,20 @@ export default {
|
||||
for (const selector of pinSelectors) {
|
||||
pinField = iframeDoc.querySelector(selector);
|
||||
if (pinField) {
|
||||
console.log(`✅ PIN-Feld gefunden mit Selektor: ${selector}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pinField && match.homePin) {
|
||||
console.log('📝 Füge PIN ein:', match.homePin);
|
||||
pinField.value = match.homePin;
|
||||
pinField.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
pinField.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
pinField.dispatchEvent(new Event('blur', { bubbles: true }));
|
||||
console.log('✅ PIN erfolgreich eingefügt');
|
||||
return;
|
||||
} else {
|
||||
console.log('❌ PIN-Feld nicht gefunden');
|
||||
console.log('🔍 Verfügbare Input-Felder:', iframeDoc.querySelectorAll('input'));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('🚫 Cross-Origin-Zugriff blockiert (erwartet)');
|
||||
// Cross-Origin-Zugriffe sind erwartbar blockiert
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,44 +157,28 @@ export default {
|
||||
source: 'trainingstagebuch'
|
||||
};
|
||||
|
||||
console.log('📤 Sende PostMessage:', message);
|
||||
|
||||
const origins = ['https://ttde-apps.liga.nu', 'https://liga.nu', '*'];
|
||||
origins.forEach(origin => {
|
||||
try {
|
||||
iframe.contentWindow.postMessage(message, origin);
|
||||
console.log(`📤 PostMessage an ${origin} gesendet`);
|
||||
} catch (e) {
|
||||
console.log(`❌ PostMessage an ${origin} fehlgeschlagen:`, e.message);
|
||||
// Ignoriere fehlgeschlagene PostMessage-Versuche
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log('💡 Alternative: Verwenden Sie den "📋 PIN kopieren" Button');
|
||||
console.log('📋 PIN zum Kopieren:', match.homePin || match.guestPin);
|
||||
},
|
||||
|
||||
handlePostMessage(event) {
|
||||
console.log('📨 PostMessage empfangen:', event);
|
||||
console.log('- Origin:', event.origin);
|
||||
console.log('- Data:', event.data);
|
||||
|
||||
// Nur Nachrichten von nuscore verarbeiten
|
||||
if (event.origin !== 'https://ttde-apps.liga.nu' && event.origin !== 'https://liga.nu') {
|
||||
console.log('🚫 Nachricht von unbekannter Origin ignoriert');
|
||||
return;
|
||||
}
|
||||
|
||||
// Hier können wir auf Antworten von nuscore reagieren
|
||||
if (event.data && event.data.action) {
|
||||
console.log('🎯 Action empfangen:', event.data.action);
|
||||
|
||||
if (event.data.action === 'pinFilled') {
|
||||
console.log('✅ PIN wurde erfolgreich eingefügt');
|
||||
} else if (event.data.action === 'pinError') {
|
||||
console.log('❌ Fehler beim PIN-Einfügen:', event.data.error);
|
||||
}
|
||||
if (!event.data || typeof event.data !== 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Weitere Aktionen bei Bedarf implementieren
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -63,8 +63,6 @@ export default {
|
||||
},
|
||||
|
||||
onIframeLoad() {
|
||||
console.log('🔄 Iframe geladen, URL:', this.$refs.reportIframe?.src);
|
||||
|
||||
// Warte kurz, damit das iframe vollständig geladen ist
|
||||
setTimeout(() => {
|
||||
this.injectContentScript();
|
||||
@@ -78,15 +76,12 @@ export default {
|
||||
try {
|
||||
const iframe = this.$refs.reportIframe;
|
||||
if (!iframe || !iframe.contentWindow) {
|
||||
console.log('Iframe noch nicht bereit für Content Script');
|
||||
return;
|
||||
}
|
||||
|
||||
// Content Script als String definieren
|
||||
const contentScript = `
|
||||
(function() {
|
||||
console.log('Content Script geladen');
|
||||
|
||||
// Warte bis die Seite vollständig geladen ist
|
||||
function waitForElement(selector, callback) {
|
||||
const element = document.querySelector(selector);
|
||||
@@ -99,7 +94,6 @@ export default {
|
||||
|
||||
// Suche nach dem Input-Feld
|
||||
waitForElement('#gamecode', function(input) {
|
||||
console.log('Input-Feld gefunden:', input);
|
||||
|
||||
// Code einfügen
|
||||
input.value = '${this.match.code}';
|
||||
@@ -109,16 +103,11 @@ export default {
|
||||
input.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
input.dispatchEvent(new Event('blur', { bubbles: true }));
|
||||
|
||||
console.log('Code eingefügt:', '${this.match.code}');
|
||||
|
||||
// Suche nach dem Button und klicke ihn
|
||||
setTimeout(() => {
|
||||
const button = document.querySelector('button.btn-primary');
|
||||
if (button) {
|
||||
console.log('Button gefunden, klicke ihn');
|
||||
button.click();
|
||||
} else {
|
||||
console.log('Button nicht gefunden');
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
@@ -130,10 +119,7 @@ export default {
|
||||
script.textContent = contentScript;
|
||||
iframe.contentDocument.head.appendChild(script);
|
||||
|
||||
console.log('Content Script injiziert');
|
||||
|
||||
} catch (error) {
|
||||
console.log('Fehler beim Injizieren des Content Scripts:', error);
|
||||
// Fallback zu PostMessage
|
||||
this.tryPostMessage();
|
||||
}
|
||||
@@ -143,7 +129,6 @@ export default {
|
||||
try {
|
||||
const iframe = this.$refs.reportIframe;
|
||||
if (!iframe || !iframe.contentWindow) {
|
||||
console.log('Iframe noch nicht bereit');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -160,22 +145,19 @@ export default {
|
||||
gameCodeInput.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
gameCodeInput.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
|
||||
console.log('Spielcode erfolgreich eingefügt:', this.match.code);
|
||||
|
||||
// Optional: Automatisch den Button klicken
|
||||
setTimeout(() => {
|
||||
this.clickLoadButton(iframeDoc);
|
||||
}, 500);
|
||||
} else {
|
||||
console.log('Input-Feld mit ID "gamecode" nicht gefunden');
|
||||
// Fallback: PostMessage verwenden
|
||||
this.tryPostMessage();
|
||||
}
|
||||
} else {
|
||||
console.log('Kein Zugriff auf iframe-Dokument (Cross-Origin)');
|
||||
// Fallback: PostMessage verwenden
|
||||
this.tryPostMessage();
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Fehler beim Zugriff auf iframe:', error);
|
||||
// Fallback: PostMessage verwenden
|
||||
this.tryPostMessage();
|
||||
}
|
||||
@@ -198,12 +180,8 @@ export default {
|
||||
|
||||
if (loadButton) {
|
||||
loadButton.click();
|
||||
console.log('Laden-Button erfolgreich geklickt');
|
||||
} else {
|
||||
console.log('Laden-Button nicht gefunden');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Fehler beim Klicken des Buttons:', error);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -216,24 +194,18 @@ export default {
|
||||
action: 'fillGameCode',
|
||||
code: this.match.code
|
||||
}, 'https://ttde-apps.liga.nu');
|
||||
|
||||
console.log('PostMessage gesendet mit Code:', this.match.code);
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Fehler beim Senden der PostMessage:', error);
|
||||
}
|
||||
},
|
||||
|
||||
startUrlMonitoring() {
|
||||
console.log('🔍 Starte URL-Überwachung für iframe');
|
||||
console.log('💡 Hinweis: PIN-Einfügung funktioniert am besten nach der Code-Eingabe und Weiterleitung');
|
||||
console.log('📋 Verwenden Sie den "📌 PIN einfügen" Button nach der Weiterleitung zur Meeting-Seite');
|
||||
|
||||
// Einfache Überwachung ohne Cross-Origin-Zugriff
|
||||
this.urlCheckInterval = setInterval(() => {
|
||||
const iframe = this.$refs.reportIframe;
|
||||
if (iframe) {
|
||||
console.log('🔗 Iframe aktiv, bereit für PIN-Einfügung');
|
||||
// Iframe aktiv
|
||||
}
|
||||
}, 10000); // Alle 10 Sekunden
|
||||
|
||||
@@ -241,7 +213,6 @@ export default {
|
||||
setTimeout(() => {
|
||||
if (this.urlCheckInterval) {
|
||||
clearInterval(this.urlCheckInterval);
|
||||
console.log('⏰ URL-Überwachung beendet (Timeout)');
|
||||
}
|
||||
}, 60000);
|
||||
},
|
||||
@@ -252,11 +223,8 @@ export default {
|
||||
},
|
||||
|
||||
attemptPinInsertionAfterRedirect() {
|
||||
console.log('🎯 Versuche PIN-Einfügung (manuell ausgelöst)');
|
||||
|
||||
const iframe = this.$refs.reportIframe;
|
||||
if (!iframe || !this.match.homePin) {
|
||||
console.log('❌ Iframe oder PIN nicht verfügbar');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -277,26 +245,18 @@ export default {
|
||||
for (const selector of pinSelectors) {
|
||||
pinField = iframeDoc.querySelector(selector);
|
||||
if (pinField) {
|
||||
console.log(`✅ PIN-Feld gefunden mit Selektor: ${selector}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pinField) {
|
||||
console.log('📝 Füge PIN ein:', this.match.homePin);
|
||||
pinField.value = this.match.homePin;
|
||||
pinField.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
pinField.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
pinField.dispatchEvent(new Event('blur', { bubbles: true }));
|
||||
console.log('✅ PIN erfolgreich eingefügt');
|
||||
} else {
|
||||
console.log('❌ PIN-Feld nicht gefunden');
|
||||
console.log('🔍 Verfügbare Input-Felder:', iframeDoc.querySelectorAll('input'));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log('🚫 Cross-Origin-Zugriff blockiert (erwartet)');
|
||||
|
||||
// Fallback: PostMessage
|
||||
const message = {
|
||||
action: 'fillPin',
|
||||
@@ -305,14 +265,12 @@ export default {
|
||||
source: 'trainingstagebuch'
|
||||
};
|
||||
|
||||
console.log('📤 Sende PostMessage:', message);
|
||||
iframe.contentWindow.postMessage(message, '*');
|
||||
}
|
||||
},
|
||||
|
||||
// Methode, die vom DialogManager aufgerufen werden kann
|
||||
insertPinManually() {
|
||||
console.log('🎯 PIN-Einfügung manuell ausgelöst');
|
||||
this.attemptPinInsertionAfterRedirect();
|
||||
},
|
||||
|
||||
@@ -322,11 +280,9 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('PostMessage empfangen:', event.data);
|
||||
|
||||
// Hier können wir auf Antworten von nuscore reagieren
|
||||
if (event.data.action === 'codeFilled') {
|
||||
console.log('Code wurde erfolgreich eingefügt');
|
||||
// Code erfolgreich eingefügt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- <button @click="insertPin" class="header-action-btn" title="PIN automatisch einfügen">
|
||||
📌 PIN einfügen
|
||||
</button>-->
|
||||
<button @click="copyPin" class="header-action-btn copy-button" title="PIN in Zwischenablage kopieren">
|
||||
<button @click="copyPin($event)" class="header-action-btn copy-button" title="PIN in Zwischenablage kopieren">
|
||||
📋 PIN kopieren
|
||||
</button>
|
||||
</div>
|
||||
@@ -31,28 +31,21 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
async copyPin() {
|
||||
async copyPin(event) {
|
||||
const button = event?.target;
|
||||
const pin = this.match.homePin || this.match.guestPin;
|
||||
if (!pin) {
|
||||
console.warn('⚠️ Keine PIN verfügbar zum Kopieren');
|
||||
if (button) {
|
||||
this.showCopyFeedback(button, 'Keine PIN verfügbar', '#dc3545');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(pin);
|
||||
console.log('✅ PIN erfolgreich kopiert:', pin);
|
||||
|
||||
// Visuelles Feedback
|
||||
const button = event.target;
|
||||
const originalText = button.textContent;
|
||||
button.textContent = '✅ Kopiert!';
|
||||
button.style.backgroundColor = '#28a745';
|
||||
|
||||
setTimeout(() => {
|
||||
button.textContent = originalText;
|
||||
button.style.backgroundColor = '';
|
||||
}, 2000);
|
||||
|
||||
if (button) {
|
||||
this.showCopyFeedback(button, '✅ Kopiert!', '#28a745');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Kopieren der PIN:', error);
|
||||
|
||||
@@ -64,8 +57,22 @@ export default {
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
|
||||
console.log('✅ PIN über Fallback kopiert:', pin);
|
||||
if (button) {
|
||||
this.showCopyFeedback(button, '✅ Kopiert!', '#28a745');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
showCopyFeedback(button, text, backgroundColor) {
|
||||
const originalText = button.textContent;
|
||||
const originalColor = button.style.backgroundColor;
|
||||
button.textContent = text;
|
||||
button.style.backgroundColor = backgroundColor;
|
||||
|
||||
setTimeout(() => {
|
||||
button.textContent = originalText;
|
||||
button.style.backgroundColor = originalColor;
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,7 +35,6 @@ const checkPermission = (el, binding, vnode) => {
|
||||
resource = binding.arg;
|
||||
action = Object.keys(binding.modifiers)[0] || 'read';
|
||||
} else {
|
||||
console.warn('v-can directive requires resource and action');
|
||||
el.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -876,7 +876,6 @@ export default {
|
||||
// Gesamtanzahl der Einträge
|
||||
return participantCount + activityCount + trainingPlanCount;
|
||||
} catch (error) {
|
||||
console.warn(`Fehler beim Laden der Einträge für Datum ${dateId}:`, error);
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -469,9 +469,6 @@ export default {
|
||||
const response = await apiClient.get(`/training-stats/${this.currentClub}`);
|
||||
const trainingStats = response.data.members || [];
|
||||
|
||||
console.log('[loadTrainingParticipations] Training Stats geladen:', trainingStats.length, 'Mitglieder');
|
||||
console.log('[loadTrainingParticipations] Response data:', JSON.stringify(response.data, null, 2));
|
||||
|
||||
// Erstelle eine Map für schnellen Zugriff: memberId -> participationTotal
|
||||
// Speichere sowohl String- als auch Number-Keys, um Typ-Probleme zu vermeiden
|
||||
const participationMap = new Map();
|
||||
@@ -483,15 +480,10 @@ export default {
|
||||
|
||||
participationMap.set(idAsString, participationTotal);
|
||||
participationMap.set(idAsNumber, participationTotal);
|
||||
console.log(`[loadTrainingParticipations] Map gesetzt: ID "${idAsString}" (String) und ${idAsNumber} (Number) -> ${participationTotal}`);
|
||||
});
|
||||
|
||||
console.log('[loadTrainingParticipations] Participation Map Keys:', Array.from(participationMap.keys()));
|
||||
|
||||
// Setze Trainingsteilnahmen für alle Testmitglieder
|
||||
const testMembers = this.members.filter(m => m.testMembership);
|
||||
console.log('[loadTrainingParticipations] Testmitglieder gefunden:', testMembers.length);
|
||||
console.log('[loadTrainingParticipations] Testmitglieder IDs:', testMembers.map(m => ({ id: m.id, type: typeof m.id, name: `${m.firstName} ${m.lastName}` })));
|
||||
|
||||
testMembers.forEach(member => {
|
||||
// Versuche sowohl String- als auch Number-ID
|
||||
@@ -509,13 +501,10 @@ export default {
|
||||
count = participationMap.get(idAsNumber);
|
||||
}
|
||||
|
||||
console.log(`[loadTrainingParticipations] Mitglied ${member.id} (type: ${typeof member.id}) (${member.firstName} ${member.lastName}): count=${count}, map has String: ${participationMap.has(idAsString)}, map has Number: ${participationMap.has(idAsNumber)}`);
|
||||
|
||||
// Setze den Wert, wenn gefunden, sonst 0
|
||||
const finalCount = count !== undefined ? count : 0;
|
||||
// In Vue 3 ist $set nicht mehr nötig, direkte Zuweisung funktioniert
|
||||
member.trainingParticipations = finalCount;
|
||||
console.log(`[loadTrainingParticipations] Trainingsteilnahmen gesetzt: ${finalCount}`);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Trainingsteilnahmen:', error);
|
||||
|
||||
@@ -233,16 +233,12 @@ export default {
|
||||
const openPermissionsDialog = async (member) => {
|
||||
selectedMember.value = member;
|
||||
|
||||
console.log('Opening dialog for member:', member.user?.email);
|
||||
console.log('Member permissions from DB:', member.permissions);
|
||||
|
||||
// Load fresh data for this specific member to ensure we have the latest permissions
|
||||
try {
|
||||
const membersResponse = await apiClient.get(`/permissions/${currentClub.value}/members?t=${Date.now()}`);
|
||||
const freshMember = membersResponse.data.find(m => m.userId === member.userId);
|
||||
if (freshMember) {
|
||||
selectedMember.value = freshMember;
|
||||
console.log('Fresh member data:', freshMember.permissions);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error loading fresh member data:', err);
|
||||
@@ -260,7 +256,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Initialized customPermissions:', customPermissions.value);
|
||||
};
|
||||
|
||||
const closePermissionsDialog = () => {
|
||||
@@ -286,15 +281,11 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Saving permissions:', permissionsToSave);
|
||||
|
||||
const response = await apiClient.put(
|
||||
`/permissions/${currentClub.value}/user/${selectedMember.value.userId}/permissions`,
|
||||
{ permissions: permissionsToSave }
|
||||
);
|
||||
|
||||
console.log('Save response:', response.data);
|
||||
|
||||
// Update local member data immediately
|
||||
const memberIndex = members.value.findIndex(m => m.userId === selectedMember.value.userId);
|
||||
if (memberIndex !== -1) {
|
||||
|
||||
@@ -369,23 +369,19 @@ export default {
|
||||
},
|
||||
|
||||
async openPlayerSelectionDialog(match) {
|
||||
console.log('Opening player selection for match:', match);
|
||||
this.playerSelectionDialog.match = match;
|
||||
this.playerSelectionDialog.isOpen = true;
|
||||
this.playerSelectionDialog.loading = true;
|
||||
|
||||
try {
|
||||
// Fetch members for the current club
|
||||
console.log('Fetching members for club:', this.currentClub);
|
||||
const response = await apiClient.get(`/clubmembers/get/${this.currentClub}/true`);
|
||||
console.log('Members response:', response.data);
|
||||
|
||||
const allMembers = response.data;
|
||||
|
||||
// Filter members by age class if league has age class info
|
||||
// For now, show all active members
|
||||
const activeMembers = allMembers.filter(m => m.active);
|
||||
console.log('Active members count:', activeMembers.length);
|
||||
|
||||
this.playerSelectionDialog.members = activeMembers.map(m => ({
|
||||
...m,
|
||||
@@ -393,8 +389,6 @@ export default {
|
||||
isPlanned: match.playersPlanned?.includes(m.id) || false,
|
||||
hasPlayed: match.playersPlayed?.includes(m.id) || false
|
||||
}));
|
||||
|
||||
console.log('Player selection members:', this.playerSelectionDialog.members.length);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading members:', error);
|
||||
|
||||
@@ -622,7 +622,7 @@ export default {
|
||||
const response = await apiClient.get(`/team-documents/club-team/${team.id}`);
|
||||
allDocuments.push(...response.data);
|
||||
} catch (error) {
|
||||
console.warn(`Fehler beim Laden der Dokumente für Team ${team.id}:`, error);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
teamDocuments.value = allDocuments;
|
||||
|
||||
@@ -209,8 +209,6 @@ export default {
|
||||
|
||||
if (!bestQuarter || maxTrainings === 0) return 0;
|
||||
|
||||
console.log('🔍 Bestes Quartal:', bestQuarter.name, 'mit', maxTrainings, 'Trainings');
|
||||
|
||||
const totalParticipants = this.getTotalParticipantsInPeriod(bestQuarter.year, bestQuarter.startMonth, bestQuarter.year, bestQuarter.endMonth);
|
||||
return totalParticipants / maxTrainings;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user