Skip to content

Instantly share code, notes, and snippets.

@nickalexej
Created February 11, 2026 07:08
Show Gist options
  • Select an option

  • Save nickalexej/30bed76bb33856fc55ec2cf923f51719 to your computer and use it in GitHub Desktop.

Select an option

Save nickalexej/30bed76bb33856fc55ec2cf923f51719 to your computer and use it in GitHub Desktop.
Entfernt Automatisch erstellte Workouts aus Garmin Connect Web --- 2026-02-11: An Anpassungen im HTML von Garmin angepasst. Verbesserte Log Ausgabe im Terminal
function deleteWorkouts() {
// Suche alle Zeilen in der Workout-Tabelle
const workoutRows = document.querySelectorAll('tr.SortableTableLayout_tableRow__iHLrR');
if (workoutRows.length === 0) {
console.log('Keine Workout-Zeilen gefunden.');
return;
}
// Finde das erste Workout mit "Bei Predictive Fitness bearbeiten"
let targetRow = null;
for (const row of workoutRows) {
// Prüfe die "Bearbeitet"-Spalte
const editedCell = row.querySelector('td[data-title="Bearbeitet"]');
if (editedCell) {
const text = editedCell.textContent.trim();
if (text === 'Bei Predictive Fitness bearbeiten') {
const workoutName = row.querySelector('td[data-title="Name"]')?.textContent;
targetRow = row;
console.log('✓ Predictive Fitness Workout gefunden:', workoutName);
break;
}
}
}
// Wenn kein passendes Training gefunden wurde → fertig
if (!targetRow) {
console.log('✓✓✓ Keine Predictive Fitness Workouts mehr gefunden. Fertig!');
return;
}
// Finde den Drei-Punkte-Button (Ellipsis)
const ellipsisButton = targetRow.querySelector('button[aria-label="Optionen"] i.icon-ellipsis-vertical');
if (!ellipsisButton) {
console.log('⚠ Drei-Punkte-Menü nicht gefunden. Überspringe...');
setTimeout(deleteWorkouts, 1000);
return;
}
// Klicke auf den Button (parent element)
ellipsisButton.closest('button').click();
console.log('→ Menü geöffnet...');
setTimeout(() => {
findAndClickDelete(targetRow);
}, 500);
}
function findAndClickDelete(row) {
// Suche das Löschen-Element im Menü dieser Zeile
const menuItems = row.querySelectorAll('.Menu_menuItems__eNgH5');
console.log('→ Gefundene Menü-Items:', menuItems.length);
let deleteItem = null;
for (const item of menuItems) {
const text = item.textContent.toLowerCase().trim();
if (text.includes('löschen') || text.includes('delete')) {
deleteItem = item;
console.log('✓ Löschen-Item gefunden!');
break;
}
}
if (!deleteItem) {
console.log('→ Löschen-Item nicht in Zeile gefunden. Versuche globale Suche...');
// Alternative: Suche überall nach sichtbaren Menü-Items
const allMenuItems = document.querySelectorAll('.Menu_menuItems__eNgH5');
for (const item of allMenuItems) {
const text = item.textContent.toLowerCase().trim();
if (text.includes('löschen') || text.includes('delete')) {
deleteItem = item;
console.log('✓ Löschen-Item global gefunden!');
break;
}
}
}
if (!deleteItem) {
console.log('⚠ Kein Löschen-Item gefunden. Schließe Menü und versuche nächstes Workout...');
document.body.click(); // Menü schließen
setTimeout(deleteWorkouts, 1500);
return;
}
deleteItem.click();
console.log('→ Löschen geklickt, warte auf Bestätigungs-Dialog...');
setTimeout(() => confirmDelete(), 1200);
}
function confirmDelete() {
// Suche nach ALLEN Dialogen
const allDialogs = document.querySelectorAll('.Dialog_dialog__fiyk-');
console.log('→ Gefundene Dialoge:', allDialogs.length);
// Finde den Dialog mit "Training löschen" im Header
let deleteDialog = null;
for (const dialog of allDialogs) {
const header = dialog.querySelector('.Dialog_dialogHeader__Guxgt h3');
if (header) {
const headerText = header.textContent.trim();
console.log(' → Dialog-Titel: "' + headerText + '"');
if (headerText === 'Training löschen' || headerText.toLowerCase().includes('löschen')) {
deleteDialog = dialog;
console.log('✓ "Training löschen"-Dialog gefunden!');
break;
}
}
}
if (!deleteDialog) {
console.log('⚠ "Training löschen"-Dialog nicht gefunden! Warte länger...');
// Zähle Wiederholungen
if (!confirmDelete.retryCount) confirmDelete.retryCount = 0;
confirmDelete.retryCount++;
if (confirmDelete.retryCount < 5) {
setTimeout(confirmDelete, 500);
} else {
console.log('⚠ Dialog erscheint nicht. Schließe alle Dialoge und versuche nächstes Workout...');
confirmDelete.retryCount = 0;
// Schließe alle Dialoge
const closeBtns = document.querySelectorAll('.Dialog_dialogCloseBtn__EtPd-');
closeBtns.forEach(btn => btn.click());
setTimeout(deleteWorkouts, 2000);
}
return;
}
// Reset retry counter
confirmDelete.retryCount = 0;
// Suche den Footer in diesem spezifischen Dialog
const dialogFooter = deleteDialog.querySelector('.Dialog_dialogFooter__W9xGT');
if (!dialogFooter) {
console.log('⚠ Dialog-Footer nicht gefunden in diesem Dialog!');
setTimeout(confirmDelete, 500);
return;
}
console.log('✓ Dialog-Footer im richtigen Dialog gefunden!');
// Suche alle Buttons im Footer dieses spezifischen Dialogs
const footerButtons = dialogFooter.querySelectorAll('button');
console.log('→ Gefundene Footer-Buttons im Lösch-Dialog:', footerButtons.length);
let confirmButton = null;
for (const btn of footerButtons) {
const text = btn.textContent.toLowerCase().trim();
const classes = btn.className;
console.log(' → Button-Text: "' + text + '", Klassen:', classes);
// Suche nach dem "Löschen" Button
if (text === 'löschen' || text === 'delete') {
confirmButton = btn;
console.log('✓✓ Löschen-Button gefunden!');
break;
}
}
if (!confirmButton) {
// Fallback: Suche nach danger-Button
confirmButton = dialogFooter.querySelector('button.Button_danger__hwLq8, button[class*="danger"]');
if (confirmButton) {
console.log('✓✓ Löschen-Button via Danger-Klasse gefunden!');
}
}
if (!confirmButton) {
console.log('⚠ Kein Löschen-Button gefunden. Schließe Dialog...');
const closeBtn = deleteDialog.querySelector('.Dialog_dialogCloseBtn__EtPd-');
if (closeBtn) {
closeBtn.click();
console.log('→ Dialog geschlossen, versuche nächstes Workout...');
}
setTimeout(deleteWorkouts, 2000);
return;
}
console.log('→ Klicke Löschen-Button...');
confirmButton.click();
console.log('✓✓✓ Workout gelöscht!\n');
// Nächstes Workout nach kurzer Pause
setTimeout(deleteWorkouts, 2000);
}
// Start
console.log('╔════════════════════════════════════════════════════╗');
console.log('║ Predictive Fitness Workout Bulk-Löscher ║');
console.log('╚════════════════════════════════════════════════════╝');
console.log('Kriterium: "Bei Predictive Fitness bearbeiten"\n');
deleteWorkouts();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment