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; },