From d94238f6df784d7e997ee90169bda1bdc24829e3 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 10 Nov 2025 13:25:11 +0100 Subject: [PATCH] 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. --- backend/cleanupKeysNode.cjs | 57 +++++---- backend/cleanupKeysNode.js | 80 ++++++------- backend/clients/myTischtennisClient.js | 11 -- .../diaryMemberActivityController.js | 12 -- backend/scripts/cleanupAllIndexes.js | 15 ++- backend/scripts/cleanupUserTokenKeys.js | 34 ++++-- backend/scripts/createTestUsers.js | 41 ++++--- backend/scripts/migratePermissions.js | 36 +++--- backend/scripts/quickFixOwner.js | 27 +++-- backend/server.js | 7 +- backend/services/diaryDateActivityService.js | 6 - backend/services/memberService.js | 11 +- backend/services/pdfParserService.js | 31 ----- backend/services/schedulerService.js | 36 ++---- backend/services/tournamentService.js | 3 - backend/utils/encrypt.js | 1 - frontend/src/components/DIALOG_TEMPLATES.md | 112 +----------------- frontend/src/components/DialogExamples.vue | 8 +- frontend/src/components/DialogManager.vue | 44 +------ frontend/src/components/MatchReportDialog.vue | 54 +-------- .../components/MatchReportHeaderActions.vue | 41 ++++--- frontend/src/directives/permissions.js | 1 - frontend/src/views/DiaryView.vue | 1 - frontend/src/views/MembersView.vue | 11 -- frontend/src/views/PermissionsView.vue | 9 -- frontend/src/views/ScheduleView.vue | 6 - frontend/src/views/TeamManagementView.vue | 2 +- frontend/src/views/TrainingStatsView.vue | 2 - 28 files changed, 225 insertions(+), 474 deletions(-) diff --git a/backend/cleanupKeysNode.cjs b/backend/cleanupKeysNode.cjs index 279c213..f9d65ec 100644 --- a/backend/cleanupKeysNode.cjs +++ b/backend/cleanupKeysNode.cjs @@ -9,15 +9,18 @@ const dbConfig = { database: process.env.DB_NAME || 'trainingsdiary' }; +const report = []; + async function cleanupKeys() { let connection; try { - console.log('🔌 Verbinde mit der Datenbank...'); + report.push('🔌 Verbinde mit der Datenbank...'); connection = await mysql.createConnection(dbConfig); // 1. Status vor dem Cleanup - console.log('\n📊 STATUS VOR DEM CLEANUP:'); + report.push(''); + report.push('📊 STATUS VOR DEM CLEANUP:'); const [tablesBefore] = await connection.execute(` SELECT TABLE_NAME, @@ -29,57 +32,60 @@ async function cleanupKeys() { `, [dbConfig.database]); tablesBefore.forEach(table => { - console.log(` ${table.TABLE_NAME}: ${table.key_count} Keys`); + report.push(` ${table.TABLE_NAME}: ${table.key_count} Keys`); }); // 2. Alle INDEX der Problem-Tabellen anzeigen const problemTables = ['member', 'diary_tags', 'season']; for (const tableName of problemTables) { - console.log(`\n🔍 INDEX für Tabelle '${tableName}':`); + report.push(''); + report.push(`🔍 INDEX für Tabelle '${tableName}':`); try { const [indexes] = await connection.execute(`SHOW INDEX FROM \`${tableName}\``); if (indexes.length === 0) { - console.log(` Keine INDEX gefunden für Tabelle '${tableName}'`); + report.push(` Keine INDEX gefunden für Tabelle '${tableName}'`); continue; } indexes.forEach(index => { - console.log(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`); + report.push(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`); }); // 3. Überflüssige INDEX entfernen (alle außer PRIMARY und UNIQUE) - console.log(`\n🗑️ Entferne überflüssige INDEX aus '${tableName}':`); + report.push(''); + report.push(`🗑️ Entferne überflüssige INDEX aus '${tableName}':`); for (const index of indexes) { // Behalte PRIMARY KEY und UNIQUE constraints if (index.Key_name === 'PRIMARY' || index.Non_unique === 0) { - console.log(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`); + report.push(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`); continue; } // Entferne alle anderen INDEX try { await connection.execute(`DROP INDEX \`${index.Key_name}\` ON \`${tableName}\``); - console.log(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`); + report.push(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`); } catch (error) { if (error.code === 'ER_CANT_DROP_FIELD_OR_KEY') { - console.log(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`); + report.push(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`); } else { - console.log(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`); + report.push(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`); } } } } catch (error) { - console.log(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`); + report.push(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`); } } // 4. Status nach dem Cleanup - console.log('\n📊 STATUS NACH DEM CLEANUP:'); + report.push(''); + report.push('📊 STATUS NACH DEM CLEANUP:'); const [tablesAfter] = await connection.execute(` SELECT TABLE_NAME, @@ -96,7 +102,7 @@ async function cleanupKeys() { const diff = beforeCount - table.key_count; const status = table.key_count <= 5 ? '✅' : table.key_count <= 10 ? '⚠️' : '❌'; - console.log(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`); + report.push(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`); }); // 5. Gesamtanzahl der Keys @@ -106,18 +112,20 @@ async function cleanupKeys() { WHERE TABLE_SCHEMA = ? `, [dbConfig.database]); - console.log(`\n📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`); - + report.push(''); + report.push(`📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`); + // 6. Zusammenfassung - console.log('\n🎯 ZUSAMMENFASSUNG:'); + report.push(''); + report.push('🎯 ZUSAMMENFASSUNG:'); const problemTablesAfter = tablesAfter.filter(t => t.key_count > 10); if (problemTablesAfter.length === 0) { - console.log(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!'); + report.push(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!'); } else { - console.log(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:'); + report.push(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:'); problemTablesAfter.forEach(table => { - console.log(` - ${table.TABLE_NAME}: ${table.key_count} Keys`); + report.push(` - ${table.TABLE_NAME}: ${table.key_count} Keys`); }); } @@ -126,15 +134,18 @@ async function cleanupKeys() { } finally { if (connection) { await connection.end(); - console.log('\n🔌 Datenbankverbindung geschlossen.'); + report.push(''); + report.push('🔌 Datenbankverbindung geschlossen.'); } } } // Script ausführen -console.log('🚀 Starte intelligentes INDEX-Cleanup...\n'); +report.push('🚀 Starte intelligentes INDEX-Cleanup...'); cleanupKeys().then(() => { - console.log('\n✨ Cleanup abgeschlossen!'); + report.push(''); + report.push('✨ Cleanup abgeschlossen!'); + process.stdout.write(`${report.join('\n')}\n`); process.exit(0); }).catch(error => { console.error('\n💥 Fehler beim Cleanup:', error); diff --git a/backend/cleanupKeysNode.js b/backend/cleanupKeysNode.js index 031a000..8783865 100644 --- a/backend/cleanupKeysNode.js +++ b/backend/cleanupKeysNode.js @@ -7,41 +7,23 @@ import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +const report = []; + // Umgebungsvariablen aus dem Root-Verzeichnis laden -//const envPath = path.join(__dirname, '..', '.env'); -//console.log('🔍 Lade .env-Datei von:', envPath); +const envPath = path.join(__dirname, '..', '.env'); dotenv.config(); - -// Debug: Zeige geladene Umgebungsvariablen -console.log('🔍 Geladene Umgebungsvariablen:'); -console.log(' DB_HOST:', process.env.DB_HOST); -console.log(' DB_USER:', process.env.DB_USER); -console.log(' DB_NAME:', process.env.DB_NAME); -console.log(' DB_PASSWORD:', process.env.DB_PASSWORD ? '***gesetzt***' : 'nicht gesetzt'); - -// Datenbankverbindung -const dbConfig = { - host: process.env.DB_HOST || 'localhost', - user: process.env.DB_USER || 'root', - password: process.env.DB_PASSWORD || '', - database: process.env.DB_NAME || 'trainingsdiary' -}; - -console.log('🔍 Datenbankverbindung:'); -console.log(' Host:', dbConfig.host); -console.log(' User:', dbConfig.user); -console.log(' Database:', dbConfig.database); -console.log(' Password:', dbConfig.password ? '***gesetzt***' : 'nicht gesetzt'); +report.push('Environment variables loaded'); async function cleanupKeys() { let connection; try { - console.log('🔌 Verbinde mit der Datenbank...'); + report.push('🔌 Verbinde mit der Datenbank...'); connection = await mysql.createConnection(dbConfig); // 1. Status vor dem Cleanup - console.log('\n📊 STATUS VOR DEM CLEANUP:'); + report.push(''); + report.push('📊 STATUS VOR DEM CLEANUP:'); const [tablesBefore] = await connection.execute(` SELECT TABLE_NAME, @@ -53,57 +35,60 @@ async function cleanupKeys() { `, [dbConfig.database]); tablesBefore.forEach(table => { - console.log(` ${table.TABLE_NAME}: ${table.key_count} Keys`); + report.push(` ${table.TABLE_NAME}: ${table.key_count} Keys`); }); // 2. Alle INDEX der Problem-Tabellen anzeigen const problemTables = ['member', 'diary_tags', 'season']; for (const tableName of problemTables) { - console.log(`\n🔍 INDEX für Tabelle '${tableName}':`); + report.push(''); + report.push(`🔍 INDEX für Tabelle '${tableName}':`); try { const [indexes] = await connection.execute(`SHOW INDEX FROM \`${tableName}\``); if (indexes.length === 0) { - console.log(` Keine INDEX gefunden für Tabelle '${tableName}'`); + report.push(` Keine INDEX gefunden für Tabelle '${tableName}'`); continue; } indexes.forEach(index => { - console.log(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`); + report.push(` - ${index.Key_name} (${index.Column_name}) - ${index.Non_unique === 0 ? 'UNIQUE' : 'NON-UNIQUE'}`); }); // 3. Überflüssige INDEX entfernen (alle außer PRIMARY und UNIQUE) - console.log(`\n🗑️ Entferne überflüssige INDEX aus '${tableName}':`); + report.push(''); + report.push(`🗑️ Entferne überflüssige INDEX aus '${tableName}':`); for (const index of indexes) { // Behalte PRIMARY KEY und UNIQUE constraints if (index.Key_name === 'PRIMARY' || index.Non_unique === 0) { - console.log(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`); + report.push(` ✅ Behalte: ${index.Key_name} (${index.Column_name})`); continue; } // Entferne alle anderen INDEX try { await connection.execute(`DROP INDEX \`${index.Key_name}\` ON \`${tableName}\``); - console.log(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`); + report.push(` ❌ Entfernt: ${index.Key_name} (${index.Column_name})`); } catch (error) { if (error.code === 'ER_CANT_DROP_FIELD_OR_KEY') { - console.log(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`); + report.push(` ⚠️ Kann nicht entfernen: ${index.Key_name} (${index.Column_name}) - ${error.message}`); } else { - console.log(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`); + report.push(` ❌ Fehler beim Entfernen von ${index.Key_name}: ${error.message}`); } } } } catch (error) { - console.log(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`); + report.push(` ⚠️ Fehler beim Zugriff auf Tabelle '${tableName}': ${error.message}`); } } // 4. Status nach dem Cleanup - console.log('\n📊 STATUS NACH DEM CLEANUP:'); + report.push(''); + report.push('📊 STATUS NACH DEM CLEANUP:'); const [tablesAfter] = await connection.execute(` SELECT TABLE_NAME, @@ -120,7 +105,7 @@ async function cleanupKeys() { const diff = beforeCount - table.key_count; const status = table.key_count <= 5 ? '✅' : table.key_count <= 10 ? '⚠️' : '❌'; - console.log(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`); + report.push(` ${status} ${table.TABLE_NAME}: ${table.key_count} Keys (${diff > 0 ? `-${diff}` : `+${Math.abs(diff)}`})`); }); // 5. Gesamtanzahl der Keys @@ -130,18 +115,20 @@ async function cleanupKeys() { WHERE TABLE_SCHEMA = ? `, [dbConfig.database]); - console.log(`\n📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`); + report.push(''); + report.push(`📈 GESAMTANZAHL KEYS: ${totalKeys[0].total_keys}`); // 6. Zusammenfassung - console.log('\n🎯 ZUSAMMENFASSUNG:'); + report.push(''); + report.push('🎯 ZUSAMMENFASSUNG:'); const problemTablesAfter = tablesAfter.filter(t => t.key_count > 10); if (problemTablesAfter.length === 0) { - console.log(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!'); + report.push(' ✅ Alle Tabellen haben jetzt weniger als 10 Keys!'); } else { - console.log(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:'); + report.push(' ⚠️ Folgende Tabellen haben immer noch zu viele Keys:'); problemTablesAfter.forEach(table => { - console.log(` - ${table.TABLE_NAME}: ${table.key_count} Keys`); + report.push(` - ${table.TABLE_NAME}: ${table.key_count} Keys`); }); } @@ -150,15 +137,18 @@ async function cleanupKeys() { } finally { if (connection) { await connection.end(); - console.log('\n🔌 Datenbankverbindung geschlossen.'); + report.push(''); + report.push('🔌 Datenbankverbindung geschlossen.'); } } } // Script ausführen -console.log('🚀 Starte intelligentes INDEX-Cleanup...\n'); +report.push('🚀 Starte intelligentes INDEX-Cleanup...'); cleanupKeys().then(() => { - console.log('\n✨ Cleanup abgeschlossen!'); + report.push(''); + report.push('✨ Cleanup abgeschlossen!'); + process.stdout.write(`${report.join('\n')}\n`); process.exit(0); }).catch(error => { console.error('\n💥 Fehler beim Cleanup:', error); diff --git a/backend/clients/myTischtennisClient.js b/backend/clients/myTischtennisClient.js index 9b2206c..1af6b69 100644 --- a/backend/clients/myTischtennisClient.js +++ b/backend/clients/myTischtennisClient.js @@ -156,17 +156,6 @@ class MyTischtennisClient { if (result.success) { - console.log('[getUserProfile] - Response structure:', { - hasUserProfile: !!result.data?.userProfile, - hasClub: !!result.data?.userProfile?.club, - hasOrganization: !!result.data?.userProfile?.organization, - clubnr: result.data?.userProfile?.club?.clubnr, - clubName: result.data?.userProfile?.club?.name, - orgShort: result.data?.userProfile?.organization?.short, - ttr: result.data?.userProfile?.ttr, - qttr: result.data?.userProfile?.qttr - }); - return { success: true, diff --git a/backend/controllers/diaryMemberActivityController.js b/backend/controllers/diaryMemberActivityController.js index 41269fd..7f96a50 100644 --- a/backend/controllers/diaryMemberActivityController.js +++ b/backend/controllers/diaryMemberActivityController.js @@ -20,13 +20,6 @@ export const addMembersToActivity = async (req, res) => { const { clubId, diaryDateActivityId } = req.params; const { participantIds } = req.body; // array of participant ids - console.log('[addMembersToActivity] Request:', { - clubId, - diaryDateActivityId, - participantIds, - bodyKeys: Object.keys(req.body) - }); - await checkAccess(userToken, clubId); if (!participantIds || !Array.isArray(participantIds)) { @@ -35,25 +28,20 @@ export const addMembersToActivity = async (req, res) => { } const validParticipants = await Participant.findAll({ where: { id: participantIds } }); - console.log('[addMembersToActivity] Valid participants found:', validParticipants.length); const validIds = new Set(validParticipants.map(p => p.id)); const created = []; for (const pid of participantIds) { if (!validIds.has(pid)) { - console.log('[addMembersToActivity] Participant not found:', pid); continue; } const existing = await DiaryMemberActivity.findOne({ where: { diaryDateActivityId, participantId: pid } }); if (!existing) { const rec = await DiaryMemberActivity.create({ diaryDateActivityId, participantId: pid }); - console.log('[addMembersToActivity] Created:', rec.id); created.push(rec); } else { - console.log('[addMembersToActivity] Already exists:', pid); } } - console.log('[addMembersToActivity] Success, created:', created.length); res.status(201).json(created); } catch (e) { console.error('[addMembersToActivity] Error:', e); diff --git a/backend/scripts/cleanupAllIndexes.js b/backend/scripts/cleanupAllIndexes.js index 2e556f7..36c7569 100644 --- a/backend/scripts/cleanupAllIndexes.js +++ b/backend/scripts/cleanupAllIndexes.js @@ -3,6 +3,8 @@ import dotenv from 'dotenv'; dotenv.config(); +const report = []; + const dbConfig = { host: process.env.DB_HOST || 'localhost', user: process.env.DB_USER || 'root', @@ -56,9 +58,9 @@ async function cleanupDuplicates(connection, table) { for (const idxName of dropNames) { try { await connection.execute(`DROP INDEX \`${idxName}\` ON \`${table}\``); - console.log(`[drop] ${table}: ${idxName}`); + report.push(`[drop] ${table}: ${idxName}`); } catch (e) { - console.warn(`[warn] ${table}: konnte Index ${idxName} nicht löschen: ${e.code || e.message}`); + report.push(`[warn] ${table}: konnte Index ${idxName} nicht löschen: ${e.code || e.message}`); } } @@ -69,11 +71,11 @@ async function cleanupDuplicates(connection, table) { async function main() { let connection; try { - console.log('Connecting to DB:', dbConfig); + report.push(`Connecting to DB: ${JSON.stringify(dbConfig)}`); connection = await mysql.createConnection(dbConfig); const tables = await getTables(connection); - console.log(`Found ${tables.length} tables`); + report.push(`Found ${tables.length} tables`); let totalBefore = 0; let totalAfter = 0; @@ -86,12 +88,15 @@ async function main() { totalDropped += dropped; } - console.log('Summary:', { totalBefore, totalAfter, totalDropped }); + report.push(`Summary: ${JSON.stringify({ totalBefore, totalAfter, totalDropped })}`); } catch (e) { console.error('Cleanup failed:', e); process.exitCode = 1; } finally { if (connection) await connection.end(); + if (report.length > 0) { + process.stdout.write(`${report.join('\n')}\n`); + } } } diff --git a/backend/scripts/cleanupUserTokenKeys.js b/backend/scripts/cleanupUserTokenKeys.js index c822c59..c9dca1f 100644 --- a/backend/scripts/cleanupUserTokenKeys.js +++ b/backend/scripts/cleanupUserTokenKeys.js @@ -3,6 +3,8 @@ import dotenv from 'dotenv'; dotenv.config(); +const report = []; + const dbConfig = { host: process.env.DB_HOST || 'localhost', user: process.env.DB_USER || 'root', @@ -26,13 +28,14 @@ async function cleanupUserTokenKeys() { const table = 'UserToken'; try { - console.log('Connecting to DB:', dbConfig); + report.push(`Connecting to DB: ${JSON.stringify(dbConfig)}`); connection = await mysql.createConnection(dbConfig); - console.log(`\nBefore cleanup (indexes on ${table}):`); + report.push(''); + report.push(`Before cleanup (indexes on ${table}):`); let before = await getIndexSummary(connection, table); Object.entries(before).forEach(([name, info]) => { - console.log(` - ${name} ${info.unique ? '(UNIQUE)' : ''} -> [${info.columns.join(', ')}]`); + report.push(` - ${name} ${info.unique ? '(UNIQUE)' : ''} -> [${info.columns.join(', ')}]`); }); // Drop all non-PRIMARY indexes on UserToken @@ -42,9 +45,9 @@ async function cleanupUserTokenKeys() { for (const keyName of keyNames) { try { await connection.execute(`DROP INDEX \`${keyName}\` ON \`${table}\``); - console.log(`Dropped index: ${keyName}`); + report.push(`Dropped index: ${keyName}`); } catch (err) { - console.warn(`Could not drop ${keyName}: ${err.code || err.message}`); + report.push(`Could not drop ${keyName}: ${err.code || err.message}`); } } @@ -52,9 +55,9 @@ async function cleanupUserTokenKeys() { // Unique on token (column is 'token') try { await connection.execute(`CREATE UNIQUE INDEX \`uniq_UserToken_token\` ON \`${table}\` (\`token\`)`); - console.log('Created UNIQUE index: uniq_UserToken_token (token)'); + report.push('Created UNIQUE index: uniq_UserToken_token (token)'); } catch (err) { - console.warn('Could not create uniq_UserToken_token:', err.code || err.message); + report.push(`Could not create uniq_UserToken_token: ${err.code || err.message}`); } // Helpful index on user_id if column exists @@ -62,26 +65,31 @@ async function cleanupUserTokenKeys() { const [cols] = await connection.execute(`SHOW COLUMNS FROM \`${table}\` LIKE 'user_id'`); if (cols && cols.length > 0) { await connection.execute(`CREATE INDEX \`idx_UserToken_user_id\` ON \`${table}\` (\`user_id\`)`); - console.log('Created INDEX: idx_UserToken_user_id (user_id)'); + report.push('Created INDEX: idx_UserToken_user_id (user_id)'); } else { - console.log('Column user_id not found, skip creating idx_UserToken_user_id'); + report.push('Column user_id not found, skip creating idx_UserToken_user_id'); } } catch (err) { - console.warn('Could not create idx_UserToken_user_id:', err.code || err.message); + report.push(`Could not create idx_UserToken_user_id: ${err.code || err.message}`); } - console.log(`\nAfter cleanup (indexes on ${table}):`); + report.push(''); + report.push(`After cleanup (indexes on ${table}):`); const after = await getIndexSummary(connection, table); Object.entries(after).forEach(([name, info]) => { - console.log(` - ${name} ${info.unique ? '(UNIQUE)' : ''} -> [${info.columns.join(', ')}]`); + report.push(` - ${name} ${info.unique ? '(UNIQUE)' : ''} -> [${info.columns.join(', ')}]`); }); - console.log('\nDone.'); + report.push(''); + report.push('Done.'); } catch (err) { console.error('Cleanup failed:', err); process.exitCode = 1; } finally { if (connection) await connection.end(); + if (report.length > 0) { + process.stdout.write(`${report.join('\n')}\n`); + } } } diff --git a/backend/scripts/createTestUsers.js b/backend/scripts/createTestUsers.js index ea16bfa..adaf341 100644 --- a/backend/scripts/createTestUsers.js +++ b/backend/scripts/createTestUsers.js @@ -47,7 +47,8 @@ const TEST_USERS = [ ]; async function createTestUsers() { - console.log('Creating test users...\n'); + const report = []; + report.push('Creating test users...'); try { // Get first club (or specify club ID) @@ -59,16 +60,16 @@ async function createTestUsers() { } const club = clubs[0]; - console.log(`Using club: ${club.name} (ID: ${club.id})\n`); + report.push(`Using club: ${club.name} (ID: ${club.id})`); for (const userData of TEST_USERS) { - console.log(`Creating user: ${userData.email} (${userData.role})...`); + report.push(`Creating user: ${userData.email} (${userData.role})...`); // Check if user already exists let user = await User.findOne({ where: { email: userData.email } }); if (user) { - console.log(` ⚠️ User already exists, using existing user`); + report.push(' ⚠️ User already exists, using existing user'); } else { // Create user user = await User.create({ @@ -76,7 +77,7 @@ async function createTestUsers() { password: userData.password, isActive: true }); - console.log(` ✓ User created`); + report.push(' ✓ User created'); } // Check if user is already in club @@ -88,13 +89,13 @@ async function createTestUsers() { }); if (userClub) { - console.log(` ⚠️ User already in club, updating role...`); + report.push(' ⚠️ User already in club, updating role...'); await userClub.update({ role: userData.role, isOwner: userData.isOwner, approved: true }); - console.log(` ✓ Updated to role: ${userData.role}`); + report.push(` ✓ Updated to role: ${userData.role}`); } else { // Add user to club userClub = await UserClub.create({ @@ -104,31 +105,37 @@ async function createTestUsers() { isOwner: userData.isOwner, approved: true }); - console.log(` ✓ Added to club with role: ${userData.role}`); + report.push(` ✓ Added to club with role: ${userData.role}`); } } - console.log('\n✅ Test users created successfully!\n'); + report.push(''); + report.push('✅ Test users created successfully!'); // Show summary - console.log('Summary:'); - console.log('========================================'); - console.log(`Club: ${club.name}`); - console.log('\nTest Users:'); + report.push('Summary:'); + report.push('========================================'); + report.push(`Club: ${club.name}`); + report.push(''); + report.push('Test Users:'); for (const userData of TEST_USERS) { - console.log(` ${userData.email.padEnd(25)} | ${userData.role.padEnd(15)} | Password: test123`); + report.push(` ${userData.email.padEnd(25)} | ${userData.role.padEnd(15)} | Password: test123`); } - console.log('\n========================================'); - console.log('You can now login with any of these users!'); - console.log('All passwords are: test123'); + report.push(''); + report.push('========================================'); + report.push('You can now login with any of these users!'); + report.push('All passwords are: test123'); } catch (error) { console.error('❌ Error creating test users:', error); throw error; } finally { await sequelize.close(); + if (report.length > 0) { + process.stdout.write(`${report.join('\n')}\n`); + } } } diff --git a/backend/scripts/migratePermissions.js b/backend/scripts/migratePermissions.js index 96d383b..e6fa766 100644 --- a/backend/scripts/migratePermissions.js +++ b/backend/scripts/migratePermissions.js @@ -11,7 +11,8 @@ import sequelize from '../database.js'; */ async function migratePermissions() { - console.log('Starting permissions migration...\n'); + const report = []; + report.push('Starting permissions migration...'); try { // Get all clubs @@ -29,10 +30,11 @@ async function migratePermissions() { }] }); - console.log(`Found ${clubs.length} club(s)\n`); + report.push(`Found ${clubs.length} club(s)`); for (const club of clubs) { - console.log(`\n--- Club: ${club.name} (ID: ${club.id}) ---`); + report.push(``); + report.push(`--- Club: ${club.name} (ID: ${club.id}) ---`); const userClubs = await UserClub.findAll({ where: { @@ -47,15 +49,15 @@ async function migratePermissions() { }); if (userClubs.length === 0) { - console.log(' No approved members found.'); + report.push(' No approved members found.'); continue; } // First user becomes owner const firstUser = userClubs[0]; - console.log(` Members found: ${userClubs.length}`); - console.log(` First member (will be owner): ${firstUser.user.email}`); + report.push(` Members found: ${userClubs.length}`); + report.push(` First member (will be owner): ${firstUser.user.email}`); for (let i = 0; i < userClubs.length; i++) { const userClub = userClubs[i]; @@ -71,12 +73,14 @@ async function migratePermissions() { await userClub.save(); - console.log(` ✓ Updated ${userClub.user.email}: role=${userClub.role}, isOwner=${userClub.isOwner}`); + report.push(` ✓ Updated ${userClub.user.email}: role=${userClub.role}, isOwner=${userClub.isOwner}`); } } - console.log('\n✅ Migration completed successfully!'); - console.log('\nSummary:'); + report.push(''); + report.push('✅ Migration completed successfully!'); + report.push(''); + report.push('Summary:'); // Show summary const owners = await UserClub.findAll({ @@ -95,9 +99,9 @@ async function migratePermissions() { ] }); - console.log(`\nClub Owners (${owners.length}):`); + report.push(`\nClub Owners (${owners.length}):`); for (const owner of owners) { - console.log(` - ${owner.club.name}: ${owner.user.email}`); + report.push(` - ${owner.club.name}: ${owner.user.email}`); } const admins = await UserClub.count({ @@ -107,15 +111,19 @@ async function migratePermissions() { where: { role: 'member' } }); - console.log(`\nRole Distribution:`); - console.log(` - Admins: ${admins}`); - console.log(` - Members: ${members}`); + report.push(''); + report.push('Role Distribution:'); + report.push(` - Admins: ${admins}`); + report.push(` - Members: ${members}`); } catch (error) { console.error('❌ Migration failed:', error); throw error; } finally { await sequelize.close(); + if (report.length > 0) { + process.stdout.write(`${report.join('\n')}\n`); + } } } diff --git a/backend/scripts/quickFixOwner.js b/backend/scripts/quickFixOwner.js index 90d25ff..95ed083 100644 --- a/backend/scripts/quickFixOwner.js +++ b/backend/scripts/quickFixOwner.js @@ -9,15 +9,15 @@ import sequelize from '../database.js'; */ async function quickFixOwners() { - console.log('Quick Fix: Setting club owners...\n'); + const report = []; + report.push('Quick Fix: Setting club owners...'); try { const clubs = await Club.findAll(); - - console.log(`Found ${clubs.length} club(s)\n`); + report.push(`Found ${clubs.length} club(s)`); for (const club of clubs) { - console.log(`Club: ${club.name} (ID: ${club.id})`); + report.push(`Club: ${club.name} (ID: ${club.id})`); // Find all approved members, ordered by creation date const userClubs = await UserClub.findAll({ @@ -34,7 +34,7 @@ async function quickFixOwners() { }); if (userClubs.length === 0) { - console.log(' ⚠️ No approved members\n'); + report.push(' ⚠️ No approved members'); continue; } @@ -58,21 +58,20 @@ async function quickFixOwners() { role: 'admin' }); - console.log(` ✅ Owner: ${firstUserClub.user.email}`); + report.push(` ✅ Owner: ${firstUserClub.user.email}`); // Set role for other members if not set for (let i = 1; i < userClubs.length; i++) { const uc = userClubs[i]; if (!uc.role) { await uc.update({ role: 'member' }); - console.log(` 👤 Member: ${uc.user.email}`); + report.push(` 👤 Member: ${uc.user.email}`); } } - - console.log(''); + report.push(''); } - console.log('✅ Quick fix completed!\n'); + report.push('✅ Quick fix completed!'); // Show all owners const owners = await UserClub.findAll({ @@ -82,10 +81,9 @@ async function quickFixOwners() { { model: Club, as: 'club', attributes: ['name'] } ] }); - - console.log('Current Club Owners:'); + report.push('Current Club Owners:'); for (const owner of owners) { - console.log(` 📍 ${owner.club.name}: ${owner.user.email} (role: ${owner.role})`); + report.push(` 📍 ${owner.club.name}: ${owner.user.email} (role: ${owner.role})`); } } catch (error) { @@ -93,6 +91,9 @@ async function quickFixOwners() { throw error; } finally { await sequelize.close(); + if (report.length > 0) { + process.stdout.write(`${report.join('\n')}\n`); + } } } diff --git a/backend/server.js b/backend/server.js index 99b12bc..a74d931 100644 --- a/backend/server.js +++ b/backend/server.js @@ -235,12 +235,7 @@ app.get('*', (req, res) => { // Start scheduler service schedulerService.start(); - app.listen(port, () => { - console.log(`Server is running on http://localhost:${port}`); - console.log('Scheduler service started:'); - console.log(' - Rating updates: 6:00 AM daily'); - console.log(' - Match results fetch: 6:30 AM daily'); - }); + app.listen(port); } catch (err) { console.error('Unable to synchronize the database:', err); } diff --git a/backend/services/diaryDateActivityService.js b/backend/services/diaryDateActivityService.js index 6c2be9c..95b21a4 100644 --- a/backend/services/diaryDateActivityService.js +++ b/backend/services/diaryDateActivityService.js @@ -277,12 +277,6 @@ class DiaryDateActivityService { throw new Error('Group not found'); } - console.log('[DiaryDateActivityService::addGroupActivity] Group found:', { - groupId: group.id, - groupDiaryDateId: group.diaryDateId, - activityDiaryDateId: diaryDateActivity.diaryDateId - }); - if (group.diaryDateId !== diaryDateActivity.diaryDateId) { console.error('[DiaryDateActivityService::addGroupActivity] Group and date don\'t fit'); console.error('Group diaryDateId:', group.diaryDateId, 'Activity diaryDateId:', diaryDateActivity.diaryDateId); diff --git a/backend/services/memberService.js b/backend/services/memberService.js index 0107165..97ecf94 100644 --- a/backend/services/memberService.js +++ b/backend/services/memberService.js @@ -230,7 +230,6 @@ class MemberService { try { session = await myTischtennisService.getSession(userId); } catch (sessionError) { - console.log('[updateRatingsFromMyTischtennis] - Session invalid, attempting login...', sessionError.message); // Versuche automatischen Login mit gespeicherten Credentials try { @@ -243,7 +242,6 @@ class MemberService { expiresAt: freshSession.expiresAt, userData: freshSession.userData }; - console.log('[updateRatingsFromMyTischtennis] - Automatic login successful'); } catch (loginError) { console.error('[updateRatingsFromMyTischtennis] - Automatic login failed:', loginError.message); return { @@ -354,6 +352,7 @@ class MemberService { account.fedNickname, 'no' ); + let qttrWarning = null; try { await (await import('./apiLogService.js')).default.logRequest({ userId, @@ -386,7 +385,7 @@ class MemberService { } if (!rankingsQuarter.success) { // QTTR optional; nicht hart abbrechen, aber vermerken - console.warn('[updateRatingsFromMyTischtennis] - QTTR Abruf fehlgeschlagen:', rankingsQuarter.error); + qttrWarning = rankingsQuarter.error || 'QTTR Abruf fehlgeschlagen'; } // 3. Alle Mitglieder des Clubs laden @@ -394,6 +393,12 @@ class MemberService { let updated = 0; const errors = []; + if (qttrWarning) { + errors.push({ + type: 'warning', + message: qttrWarning + }); + } const notFound = []; const matched = []; diff --git a/backend/services/pdfParserService.js b/backend/services/pdfParserService.js index 2b55b11..883dec6 100644 --- a/backend/services/pdfParserService.js +++ b/backend/services/pdfParserService.js @@ -109,21 +109,11 @@ class PDFParserService { const result = strategy.fn(lines, clubId, filteredLineEntries.length === lines.length ? filteredLineEntries : null); if (result.matches.length > 0) { - console.log(`[PDF Parser] Using strategy: ${strategy.name}, found ${result.matches.length} matches`); - if (result.matches.length > 0) { - console.log(`[PDF Parser] First match sample:`, { - homeTeamName: result.matches[0].homeTeamName, - guestTeamName: result.matches[0].guestTeamName, - date: result.matches[0].date, - rawLine: result.matches[0].rawLine - }); - } matches.push(...result.matches); metadata.parsedMatches += result.matches.length; break; // Erste erfolgreiche Strategie verwenden } } catch (strategyError) { - console.log(`[PDF Parser] Strategy ${strategy.name} failed:`, strategyError.message); errors.push(`Strategy ${strategy.name} failed: ${strategyError.message}`); } } @@ -423,18 +413,6 @@ class PDFParserService { } if (homeTeamName && guestTeamName) { - let debugInfo; - if (code) { - debugInfo = `code: "${code}"`; - } else if (homePin && guestPin) { - debugInfo = `homePin: "${homePin}", guestPin: "${guestPin}"`; - } else if (homePin) { - debugInfo = `homePin: "${homePin}"`; - } else if (guestPin) { - debugInfo = `guestPin: "${guestPin}"`; - } - - console.log(`[PDF Parser] Parsed match: ${homeTeamName} vs ${guestTeamName}, ${debugInfo}`); matches.push({ date: date, @@ -769,27 +747,18 @@ class PDFParserService { where: { clubId: matchData.clubId }, attributes: ['id', 'name'] }); - console.log(`[PDF Parser] Available teams in club: ${allTeams.map(t => t.name).join(', ')}`); // Fuzzy-Matching für Team-Namen if (!homeTeam) { homeTeam = allTeams.find(t => PDFParserService.namesRoughlyMatch(t.name, matchData.homeTeamName) ); - - if (homeTeam) { - console.log(`[PDF Parser] Found home team via fuzzy match: "${matchData.homeTeamName}" → "${homeTeam.name}"`); - } } if (!guestTeam) { guestTeam = allTeams.find(t => PDFParserService.namesRoughlyMatch(t.name, matchData.guestTeamName) ); - - if (guestTeam) { - console.log(`[PDF Parser] Found guest team via fuzzy match: "${matchData.guestTeamName}" → "${guestTeam.name}"`); - } } } diff --git a/backend/services/schedulerService.js b/backend/services/schedulerService.js index 439b254..0532d67 100644 --- a/backend/services/schedulerService.js +++ b/backend/services/schedulerService.js @@ -24,28 +24,22 @@ class SchedulerService { // Schedule automatic rating updates at 6:00 AM daily const ratingUpdateJob = cron.schedule('0 6 * * *', async () => { const startTime = Date.now(); - const timestamp = new Date().toISOString(); - console.log(`[${timestamp}] CRON: Executing scheduled rating updates...`); - devLog('Executing scheduled rating updates...'); + devLog(`[${new Date().toISOString()}] CRON: Executing scheduled rating updates...`); - let success = false; - let message = ''; let errorMessage = null; try { // Let the service return details including counts if available const result = await autoUpdateRatingsService.executeAutomaticUpdates(); const executionTime = Date.now() - startTime; - success = true; // result may include updatedCount or a summary object const messageObj = result && typeof result === 'object' ? result : { message: 'Rating updates completed successfully' }; - console.log(`[${new Date().toISOString()}] CRON: Rating updates completed successfully`); // Log to ApiLog with rich details await apiLogService.logSchedulerExecution('rating_updates', true, messageObj, executionTime, null); + devLog('Scheduled rating updates completed successfully'); } catch (error) { const executionTime = Date.now() - startTime; - success = false; errorMessage = error.message; console.error(`[${new Date().toISOString()}] CRON ERROR in scheduled rating updates:`, error); console.error('Stack trace:', error.stack); @@ -60,32 +54,26 @@ class SchedulerService { this.jobs.set('ratingUpdates', ratingUpdateJob); ratingUpdateJob.start(); - console.log('[Scheduler] Rating update job scheduled and started'); + devLog('Rating update job scheduled and started'); // Schedule automatic match results fetching at 6:30 AM daily const matchResultsJob = cron.schedule('30 6 * * *', async () => { const startTime = Date.now(); - const timestamp = new Date().toISOString(); - console.log(`[${timestamp}] CRON: Executing scheduled match results fetch...`); - devLog('Executing scheduled match results fetch...'); + devLog(`[${new Date().toISOString()}] CRON: Executing scheduled match results fetch...`); - let success = false; - let message = ''; let errorMessage = null; try { // Execute and capture returned summary (should include counts) const result = await autoFetchMatchResultsService.executeAutomaticFetch(); const executionTime = Date.now() - startTime; - success = true; const messageObj = result && typeof result === 'object' ? result : { message: 'Match results fetch completed successfully' }; - console.log(`[${new Date().toISOString()}] CRON: Match results fetch completed successfully`); // Log to ApiLog with rich details (including counts if present) await apiLogService.logSchedulerExecution('match_results', true, messageObj, executionTime, null); + devLog('Scheduled match results fetch completed successfully'); } catch (error) { const executionTime = Date.now() - startTime; - success = false; errorMessage = error.message; console.error(`[${new Date().toISOString()}] CRON ERROR in scheduled match results fetch:`, error); console.error('Stack trace:', error.stack); @@ -100,7 +88,7 @@ class SchedulerService { this.jobs.set('matchResults', matchResultsJob); matchResultsJob.start(); - console.log('[Scheduler] Match results fetch job scheduled and started'); + devLog('Match results fetch job scheduled and started'); this.isRunning = true; const now = new Date(); @@ -112,12 +100,12 @@ class SchedulerService { tomorrow630AM.setDate(tomorrow630AM.getDate() + 1); tomorrow630AM.setHours(6, 30, 0, 0); - console.log('[Scheduler] ===== SCHEDULER SERVICE STARTED ====='); - console.log(`[Scheduler] Server time: ${now.toISOString()}`); - console.log(`[Scheduler] Timezone: Europe/Berlin`); - console.log(`[Scheduler] Rating updates: Next execution at ${tomorrow6AM.toISOString()} (6:00 AM Berlin time)`); - console.log(`[Scheduler] Match results fetch: Next execution at ${tomorrow630AM.toISOString()} (6:30 AM Berlin time)`); - console.log('[Scheduler] ====================================='); + devLog('[Scheduler] ===== SCHEDULER SERVICE STARTED ====='); + devLog(`[Scheduler] Server time: ${now.toISOString()}`); + devLog(`[Scheduler] Timezone: Europe/Berlin`); + devLog(`[Scheduler] Rating updates: Next execution at ${tomorrow6AM.toISOString()} (6:00 AM Berlin time)`); + devLog(`[Scheduler] Match results fetch: Next execution at ${tomorrow630AM.toISOString()} (6:30 AM Berlin time)`); + devLog('[Scheduler] ====================================='); devLog('Scheduler service started successfully'); devLog('Rating updates scheduled for 6:00 AM daily (Europe/Berlin timezone)'); diff --git a/backend/services/tournamentService.js b/backend/services/tournamentService.js index 5a3c415..6f95629 100644 --- a/backend/services/tournamentService.js +++ b/backend/services/tournamentService.js @@ -207,7 +207,6 @@ class TournamentService { const gm = await TournamentMember.findAll({ where: { groupId: g.id } }); if (gm.length < 2) { - console.warn(`Gruppe ${g.id} hat nur ${gm.length} Teilnehmer - keine Matches erstellt`); continue; } @@ -227,8 +226,6 @@ class TournamentService { player2Id: p2Id, groupRound: roundIndex + 1 }); - } else { - console.warn(`Spieler gehören nicht zur gleichen Gruppe: ${p1Id} (${p1?.groupId}) vs ${p2Id} (${p2?.groupId}) in Gruppe ${g.id}`); } } } diff --git a/backend/utils/encrypt.js b/backend/utils/encrypt.js index 5aab2e3..03477b4 100644 --- a/backend/utils/encrypt.js +++ b/backend/utils/encrypt.js @@ -18,7 +18,6 @@ function encryptData(data) { encrypted += cipher.final('hex'); return encrypted; } catch (error) { - console.log(error, data, process.env.ENCRYPTION_KEY, typeof data, process.env.ENCRYPTION_KEY.length); return ''; } } diff --git a/frontend/src/components/DIALOG_TEMPLATES.md b/frontend/src/components/DIALOG_TEMPLATES.md index b600ea8..bd51358 100644 --- a/frontend/src/components/DIALOG_TEMPLATES.md +++ b/frontend/src/components/DIALOG_TEMPLATES.md @@ -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: - - -// 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 - -``` - -### Neu (BaseDialog): -```vue - - Inhalt - -``` - -## 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 } -``` - +``` \ No newline at end of file diff --git a/frontend/src/components/DialogExamples.vue b/frontend/src/components/DialogExamples.vue index 11e4fbe..e3f8e6a 100644 --- a/frontend/src/components/DialogExamples.vue +++ b/frontend/src/components/DialogExamples.vue @@ -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; }, diff --git a/frontend/src/components/DialogManager.vue b/frontend/src/components/DialogManager.vue index 7b30496..8f84034 100644 --- a/frontend/src/components/DialogManager.vue +++ b/frontend/src/components/DialogManager.vue @@ -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 } }, diff --git a/frontend/src/components/MatchReportDialog.vue b/frontend/src/components/MatchReportDialog.vue index f6b7ee8..8597e31 100644 --- a/frontend/src/components/MatchReportDialog.vue +++ b/frontend/src/components/MatchReportDialog.vue @@ -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 } } } diff --git a/frontend/src/components/MatchReportHeaderActions.vue b/frontend/src/components/MatchReportHeaderActions.vue index 6ae723c..1320c78 100644 --- a/frontend/src/components/MatchReportHeaderActions.vue +++ b/frontend/src/components/MatchReportHeaderActions.vue @@ -3,7 +3,7 @@ - @@ -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); } } }; diff --git a/frontend/src/directives/permissions.js b/frontend/src/directives/permissions.js index 7541bad..a8c52f2 100644 --- a/frontend/src/directives/permissions.js +++ b/frontend/src/directives/permissions.js @@ -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; } diff --git a/frontend/src/views/DiaryView.vue b/frontend/src/views/DiaryView.vue index 21c6bda..9dfbe2e 100644 --- a/frontend/src/views/DiaryView.vue +++ b/frontend/src/views/DiaryView.vue @@ -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; } }, diff --git a/frontend/src/views/MembersView.vue b/frontend/src/views/MembersView.vue index 2513252..0973d3a 100644 --- a/frontend/src/views/MembersView.vue +++ b/frontend/src/views/MembersView.vue @@ -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); diff --git a/frontend/src/views/PermissionsView.vue b/frontend/src/views/PermissionsView.vue index d38a246..3872760 100644 --- a/frontend/src/views/PermissionsView.vue +++ b/frontend/src/views/PermissionsView.vue @@ -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) { diff --git a/frontend/src/views/ScheduleView.vue b/frontend/src/views/ScheduleView.vue index 534c0a8..d063e68 100644 --- a/frontend/src/views/ScheduleView.vue +++ b/frontend/src/views/ScheduleView.vue @@ -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); diff --git a/frontend/src/views/TeamManagementView.vue b/frontend/src/views/TeamManagementView.vue index 3e8e931..665bec5 100644 --- a/frontend/src/views/TeamManagementView.vue +++ b/frontend/src/views/TeamManagementView.vue @@ -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; diff --git a/frontend/src/views/TrainingStatsView.vue b/frontend/src/views/TrainingStatsView.vue index 5f63104..9b22330 100644 --- a/frontend/src/views/TrainingStatsView.vue +++ b/frontend/src/views/TrainingStatsView.vue @@ -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; },