Spaces:
Sleeping
Sleeping
| <html lang="de"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>File Browser - CofifoAIWO</title> | |
| <style> | |
| :root { | |
| --primary-color: #3498db; | |
| --secondary-color: #2980b9; | |
| --accent-color: #e74c3c; | |
| --text-color: #333; | |
| --light-bg: #f5f5f5; | |
| --border-color: #ddd; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| line-height: 1.6; | |
| color: var(--text-color); | |
| background-color: var(--light-bg); | |
| } | |
| #app { | |
| display: flex; | |
| flex-direction: column; | |
| min-height: 100vh; | |
| } | |
| header { | |
| background-color: #fff; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| } | |
| .navbar { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 1rem 2rem; | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| width: 100%; | |
| } | |
| .navbar-brand { | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .navbar-brand h1 { | |
| color: var(--primary-color); | |
| font-size: 1.8rem; | |
| margin-bottom: 0.2rem; | |
| } | |
| .subtitle { | |
| font-size: 0.9rem; | |
| color: #666; | |
| } | |
| .navbar-menu { | |
| display: flex; | |
| gap: 1.5rem; | |
| } | |
| .nav-link { | |
| color: var(--text-color); | |
| text-decoration: none; | |
| font-weight: 500; | |
| padding: 0.5rem 0; | |
| border-bottom: 2px solid transparent; | |
| transition: all 0.3s ease; | |
| } | |
| .nav-link:hover, .active { | |
| color: var(--primary-color); | |
| border-bottom: 2px solid var(--primary-color); | |
| } | |
| main { | |
| flex: 1; | |
| padding: 2rem; | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| width: 100%; | |
| } | |
| footer { | |
| background-color: #fff; | |
| text-align: center; | |
| padding: 1rem; | |
| border-top: 1px solid var(--border-color); | |
| margin-top: auto; | |
| } | |
| footer a { | |
| color: var(--primary-color); | |
| text-decoration: none; | |
| } | |
| /* Allgemeine Komponenten-Stile */ | |
| .btn { | |
| display: inline-block; | |
| background-color: var(--primary-color); | |
| color: white; | |
| padding: 0.6rem 1.2rem; | |
| border: none; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| font-size: 1rem; | |
| transition: background-color 0.3s ease; | |
| text-decoration: none; | |
| } | |
| .btn:hover { | |
| background-color: var(--secondary-color); | |
| } | |
| .btn-secondary { | |
| background-color: #95a5a6; | |
| } | |
| .btn-secondary:hover { | |
| background-color: #7f8c8d; | |
| } | |
| .btn-danger { | |
| background-color: var(--accent-color); | |
| } | |
| .btn-danger:hover { | |
| background-color: #c0392b; | |
| } | |
| .btn-sm { | |
| padding: 0.3rem 0.6rem; | |
| font-size: 0.9rem; | |
| } | |
| .card { | |
| background-color: #fff; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| padding: 1.5rem; | |
| margin-bottom: 1.5rem; | |
| } | |
| .form-group { | |
| margin-bottom: 1rem; | |
| } | |
| .form-group label { | |
| display: block; | |
| margin-bottom: 0.5rem; | |
| font-weight: 500; | |
| } | |
| .form-control { | |
| width: 100%; | |
| padding: 0.6rem; | |
| font-size: 1rem; | |
| border: 1px solid var(--border-color); | |
| border-radius: 4px; | |
| } | |
| .alert { | |
| padding: 1rem; | |
| border-radius: 4px; | |
| margin-bottom: 1rem; | |
| } | |
| .alert-success { | |
| background-color: #d4edda; | |
| color: #155724; | |
| } | |
| .alert-danger { | |
| background-color: #f8d7da; | |
| color: #721c24; | |
| } | |
| /* Browser Styles */ | |
| .path-navigation { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 1rem; | |
| padding-bottom: 1rem; | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .current-path { | |
| font-family: monospace; | |
| background-color: var(--light-bg); | |
| padding: 0.5rem; | |
| border-radius: 4px; | |
| flex: 1; | |
| margin-right: 1rem; | |
| word-break: break-all; | |
| } | |
| .directory-content { | |
| margin-bottom: 1rem; | |
| } | |
| .entries-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); | |
| gap: 0.8rem; | |
| margin-bottom: 1rem; | |
| } | |
| .entry { | |
| display: flex; | |
| align-items: center; | |
| padding: 0.6rem; | |
| border-radius: 4px; | |
| border: 1px solid var(--border-color); | |
| background-color: white; | |
| cursor: pointer; | |
| transition: background-color 0.2s; | |
| } | |
| .entry:hover { | |
| background-color: var(--light-bg); | |
| } | |
| .entry.selected { | |
| background-color: #e3f2fd; | |
| border-color: var(--primary-color); | |
| } | |
| .entry-icon { | |
| margin-right: 0.5rem; | |
| font-size: 1.2rem; | |
| } | |
| .entry-name { | |
| flex: 1; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| white-space: nowrap; | |
| } | |
| .entry-actions { | |
| margin-left: auto; | |
| } | |
| .selected-files-list { | |
| max-height: 300px; | |
| overflow-y: auto; | |
| margin-bottom: 1rem; | |
| border: 1px solid var(--border-color); | |
| border-radius: 4px; | |
| } | |
| .selected-file { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 0.6rem 1rem; | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .selected-file:last-child { | |
| border-bottom: none; | |
| } | |
| .file-path { | |
| font-family: monospace; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| white-space: nowrap; | |
| } | |
| .selection-actions { | |
| display: flex; | |
| gap: 1rem; | |
| } | |
| .loading, .error, .empty-directory, .empty-selection { | |
| padding: 1rem; | |
| text-align: center; | |
| color: #666; | |
| background-color: var(--light-bg); | |
| border-radius: 4px; | |
| } | |
| .error { | |
| color: var(--accent-color); | |
| } | |
| /* Modal Styles */ | |
| .modal { | |
| display: none; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-color: rgba(0, 0, 0, 0.5); | |
| } | |
| .modal-content { | |
| background-color: white; | |
| border-radius: 8px; | |
| width: 90%; | |
| max-width: 500px; | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| padding: 1rem; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| } | |
| .modal-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding-bottom: 1rem; | |
| border-bottom: 1px solid var(--border-color); | |
| } | |
| .close-btn { | |
| background: none; | |
| border: none; | |
| font-size: 1.5rem; | |
| cursor: pointer; | |
| color: #666; | |
| } | |
| @media (max-width: 768px) { | |
| .navbar { | |
| flex-direction: column; | |
| padding: 1rem; | |
| } | |
| .navbar-menu { | |
| margin-top: 1rem; | |
| } | |
| main { | |
| padding: 1rem; | |
| } | |
| .path-navigation { | |
| flex-direction: column; | |
| align-items: flex-start; | |
| gap: 0.5rem; | |
| } | |
| .entries-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| .selection-actions { | |
| flex-direction: column; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="app"> | |
| <header> | |
| <nav class="navbar"> | |
| <div class="navbar-brand"> | |
| <h1>CofifoAIWO</h1> | |
| <p class="subtitle">Combine Files for AI Workflows</p> | |
| </div> | |
| <div class="navbar-menu"> | |
| <a href="/" class="nav-link">Home</a> | |
| <a href="/shortcuts" class="nav-link">Shortcuts</a> | |
| <a href="/browser" class="nav-link active">File Browser</a> | |
| </div> | |
| </nav> | |
| </header> | |
| <main> | |
| <div class="file-browser"> | |
| <h2>Datei-Browser</h2> | |
| <div id="notification" class="alert" style="display: none;"></div> | |
| <div class="card"> | |
| <div class="path-navigation"> | |
| <div class="current-path"> | |
| <strong>Aktueller Pfad:</strong> <span id="current-path-display"></span> | |
| </div> | |
| <button id="navigate-up" class="btn btn-sm">⬆️ Ein Level nach oben</button> | |
| </div> | |
| <div class="directory-content"> | |
| <div id="loading" class="loading"> | |
| Lade Verzeichnisinhalt... | |
| </div> | |
| <div id="error" class="error" style="display: none;"></div> | |
| <div id="entries-container" style="display: none;"> | |
| <div id="entries-grid" class="entries-grid"></div> | |
| <div id="empty-directory" class="empty-directory" style="display: none;"> | |
| Dieses Verzeichnis ist leer. | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <h3>Ausgewählte Dateien</h3> | |
| <div id="empty-selection" class="empty-selection"> | |
| <p>Keine Dateien ausgewählt. Klicke auf Dateien im Browser, um sie auszuwählen.</p> | |
| </div> | |
| <div id="selected-files-container" style="display: none;"> | |
| <ul id="selected-files-list" class="selected-files-list"></ul> | |
| <div class="selection-actions"> | |
| <button id="save-as-shortcut" class="btn">Als Shortcut speichern</button> | |
| <button id="generate-output" class="btn">Textdatei generieren</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- "Als Shortcut speichern" Modal --> | |
| <div id="save-shortcut-modal" class="modal"> | |
| <div class="modal-content"> | |
| <div class="modal-header"> | |
| <h3>Als Shortcut speichern</h3> | |
| <button class="close-btn">×</button> | |
| </div> | |
| <div class="modal-body"> | |
| <form id="create-shortcut-form"> | |
| <div class="form-group"> | |
| <label for="shortcutName">Shortcut-Name:</label> | |
| <input | |
| type="text" | |
| id="shortcutName" | |
| class="form-control" | |
| required | |
| placeholder="z.B. my_project" | |
| > | |
| </div> | |
| <button type="submit" class="btn">Speichern</button> | |
| <button type="button" class="btn btn-secondary modal-cancel">Abbrechen</button> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- "Ausgabedatei generieren" Modal --> | |
| <div id="generate-modal" class="modal"> | |
| <div class="modal-content"> | |
| <div class="modal-header"> | |
| <h3>Textdatei generieren</h3> | |
| <button class="close-btn">×</button> | |
| </div> | |
| <div class="modal-body"> | |
| <form id="generate-form"> | |
| <div class="form-group"> | |
| <label for="outputFile">Ausgabedatei:</label> | |
| <input | |
| type="text" | |
| id="outputFile" | |
| class="form-control" | |
| required | |
| placeholder="output.txt" | |
| > | |
| </div> | |
| <div class="form-group"> | |
| <input type="checkbox" id="includeTree"> | |
| <label for="includeTree">Verzeichnisstruktur einbeziehen (tree)</label> | |
| </div> | |
| <button type="submit" class="btn">Generieren</button> | |
| <button type="button" class="btn btn-secondary modal-cancel">Abbrechen</button> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Download-Link (Modal) --> | |
| <div id="download-modal" class="modal"> | |
| <div class="modal-content"> | |
| <div class="modal-header"> | |
| <h3>Datei erfolgreich generiert</h3> | |
| <button class="close-btn">×</button> | |
| </div> | |
| <div class="modal-body"> | |
| <p>Deine Datei wurde erfolgreich erstellt!</p> | |
| <p> | |
| <a id="download-link" href="#" class="btn" download>Datei herunterladen</a> | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <footer> | |
| <p>© 2023 CofifoAIWO - Entwickelt von <a href="https://github.com/ogerly" target="_blank">ogerly</a></p> | |
| </footer> | |
| </div> | |
| <script> | |
| // DOM-Elemente | |
| const notificationEl = document.getElementById('notification'); | |
| const currentPathDisplay = document.getElementById('current-path-display'); | |
| const navigateUpBtn = document.getElementById('navigate-up'); | |
| const loadingEl = document.getElementById('loading'); | |
| const errorEl = document.getElementById('error'); | |
| const entriesContainer = document.getElementById('entries-container'); | |
| const entriesGrid = document.getElementById('entries-grid'); | |
| const emptyDirectoryEl = document.getElementById('empty-directory'); | |
| const emptySelectionEl = document.getElementById('empty-selection'); | |
| const selectedFilesContainer = document.getElementById('selected-files-container'); | |
| const selectedFilesList = document.getElementById('selected-files-list'); | |
| const saveAsShortcutBtn = document.getElementById('save-as-shortcut'); | |
| const generateOutputBtn = document.getElementById('generate-output'); | |
| // Modals | |
| const saveShortcutModal = document.getElementById('save-shortcut-modal'); | |
| const generateModal = document.getElementById('generate-modal'); | |
| const downloadModal = document.getElementById('download-modal'); | |
| // Forms | |
| const createShortcutForm = document.getElementById('create-shortcut-form'); | |
| const generateForm = document.getElementById('generate-form'); | |
| // Sonstige Elemente | |
| const downloadLink = document.getElementById('download-link'); | |
| const shortcutNameInput = document.getElementById('shortcutName'); | |
| const outputFileInput = document.getElementById('outputFile'); | |
| const includeTreeCheckbox = document.getElementById('includeTree'); | |
| // State | |
| let currentPath = ''; | |
| let selectedFiles = []; | |
| // Close-Buttons für Modals | |
| const closeButtons = document.querySelectorAll('.close-btn'); | |
| closeButtons.forEach(button => { | |
| button.addEventListener('click', () => { | |
| saveShortcutModal.style.display = 'none'; | |
| generateModal.style.display = 'none'; | |
| downloadModal.style.display = 'none'; | |
| }); | |
| }); | |
| const modalCancelButtons = document.querySelectorAll('.modal-cancel'); | |
| modalCancelButtons.forEach(button => { | |
| button.addEventListener('click', () => { | |
| saveShortcutModal.style.display = 'none'; | |
| generateModal.style.display = 'none'; | |
| }); | |
| }); | |
| // Funktion zum Anzeigen von Benachrichtigungen | |
| function showNotification(type, message) { | |
| notificationEl.textContent = message; | |
| notificationEl.className = 'alert alert-' + type; | |
| notificationEl.style.display = 'block'; | |
| // Benachrichtigung nach 5 Sekunden ausblenden | |
| setTimeout(() => { | |
| notificationEl.style.display = 'none'; | |
| }, 5000); | |
| } | |
| // Funktion zum Laden eines Verzeichnisses | |
| async function loadDirectory(path) { | |
| // Setze UI-Status auf "Laden" | |
| loadingEl.style.display = 'block'; | |
| errorEl.style.display = 'none'; | |
| entriesContainer.style.display = 'none'; | |
| try { | |
| const response = await fetch(`/api/browse?path=${encodeURIComponent(path)}`); | |
| if (!response.ok) { | |
| const data = await response.json(); | |
| throw new Error(data.error || 'Fehler beim Laden des Verzeichnisses'); | |
| } | |
| const data = await response.json(); | |
| // Aktuellen Pfad aktualisieren | |
| currentPath = data.path; | |
| currentPathDisplay.textContent = currentPath; | |
| // Einträge anzeigen | |
| displayEntries(data.entries || []); | |
| // UI-Status aktualisieren | |
| loadingEl.style.display = 'none'; | |
| entriesContainer.style.display = 'block'; | |
| // Prüfen, ob das Verzeichnis leer ist | |
| if (!data.entries || data.entries.length === 0) { | |
| emptyDirectoryEl.style.display = 'block'; | |
| } else { | |
| emptyDirectoryEl.style.display = 'none'; | |
| } | |
| } catch (error) { | |
| // Fehler anzeigen | |
| loadingEl.style.display = 'none'; | |
| errorEl.textContent = error.message; | |
| errorEl.style.display = 'block'; | |
| showNotification('danger', error.message); | |
| } | |
| } | |
| // Funktion zum Anzeigen der Verzeichniseinträge | |
| function displayEntries(entries) { | |
| entriesGrid.innerHTML = ''; | |
| entries.forEach(entry => { | |
| const entryEl = document.createElement('div'); | |
| entryEl.className = `entry ${entry.type}`; | |
| if (isSelected(entry.path)) { | |
| entryEl.classList.add('selected'); | |
| } | |
| const iconEl = document.createElement('div'); | |
| iconEl.className = 'entry-icon'; | |
| iconEl.innerHTML = entry.type === 'directory' ? '📁' : '📄'; | |
| const nameEl = document.createElement('div'); | |
| nameEl.className = 'entry-name'; | |
| nameEl.textContent = entry.name; | |
| entryEl.appendChild(iconEl); | |
| entryEl.appendChild(nameEl); | |
| if (entry.type === 'file') { | |
| const actionsEl = document.createElement('div'); | |
| actionsEl.className = 'entry-actions'; | |
| const toggleBtn = document.createElement('button'); | |
| toggleBtn.className = 'btn btn-sm'; | |
| toggleBtn.textContent = isSelected(entry.path) ? '✓' : '+'; | |
| toggleBtn.addEventListener('click', (e) => { | |
| e.stopPropagation(); | |
| toggleSelection(entry.path); | |
| }); | |
| actionsEl.appendChild(toggleBtn); | |
| entryEl.appendChild(actionsEl); | |
| } | |
| entryEl.addEventListener('click', () => { | |
| if (entry.type === 'directory') { | |
| loadDirectory(entry.path); | |
| } else { | |
| toggleSelection(entry.path); | |
| } | |
| }); | |
| entriesGrid.appendChild(entryEl); | |
| }); | |
| } | |
| // Funktion zum Ein Level nach oben Navigieren | |
| function navigateUp() { | |
| const parentPath = currentPath.split('/').slice(0, -1).join('/') || '/'; | |
| loadDirectory(parentPath); | |
| } | |
| // Funktion zum Überprüfen, ob ein Pfad ausgewählt ist | |
| function isSelected(path) { | |
| return selectedFiles.includes(path); | |
| } | |
| // Funktion zum Hinzufügen oder Entfernen eines Pfads aus der Auswahl | |
| function toggleSelection(path) { | |
| if (isSelected(path)) { | |
| // Aus Auswahl entfernen | |
| selectedFiles = selectedFiles.filter(file => file !== path); | |
| } else { | |
| // Zur Auswahl hinzufügen | |
| selectedFiles.push(path); | |
| } | |
| // UI aktualisieren | |
| updateSelectedFilesUI(); | |
| // Verzeichniseinträge aktualisieren (um Auswahlstatus zu aktualisieren) | |
| const entries = Array.from(entriesGrid.querySelectorAll('.entry')); | |
| entries.forEach(entry => { | |
| const entryPath = entry.querySelector('.entry-name').textContent; | |
| const fullPath = currentPath + '/' + entryPath; | |
| if (isSelected(fullPath)) { | |
| entry.classList.add('selected'); | |
| const toggleBtn = entry.querySelector('.btn'); | |
| if (toggleBtn) toggleBtn.textContent = '✓'; | |
| } else { | |
| entry.classList.remove('selected'); | |
| const toggleBtn = entry.querySelector('.btn'); | |
| if (toggleBtn) toggleBtn.textContent = '+'; | |
| } | |
| }); | |
| } | |
| // Funktion zum Aktualisieren der UI für ausgewählte Dateien | |
| function updateSelectedFilesUI() { | |
| if (selectedFiles.length === 0) { | |
| emptySelectionEl.style.display = 'block'; | |
| selectedFilesContainer.style.display = 'none'; | |
| } else { | |
| emptySelectionEl.style.display = 'none'; | |
| selectedFilesContainer.style.display = 'block'; | |
| // Liste der ausgewählten Dateien aktualisieren | |
| selectedFilesList.innerHTML = ''; | |
| selectedFiles.forEach(file => { | |
| const listItem = document.createElement('li'); | |
| listItem.className = 'selected-file'; | |
| const filePathEl = document.createElement('span'); | |
| filePathEl.className = 'file-path'; | |
| filePathEl.textContent = file; | |
| const removeBtn = document.createElement('button'); | |
| removeBtn.className = 'btn btn-sm btn-danger'; | |
| removeBtn.textContent = '×'; | |
| removeBtn.addEventListener('click', () => { | |
| toggleSelection(file); | |
| }); | |
| listItem.appendChild(filePathEl); | |
| listItem.appendChild(removeBtn); | |
| selectedFilesList.appendChild(listItem); | |
| }); | |
| } | |
| } | |
| // Funktion zum Speichern als Shortcut | |
| async function saveAsShortcut() { | |
| if (selectedFiles.length === 0) { | |
| showNotification('danger', 'Bitte wähle zuerst Dateien aus.'); | |
| return; | |
| } | |
| saveShortcutModal.style.display = 'block'; | |
| } | |
| // Funktion zum Erstellen eines Shortcuts | |
| async function createShortcut(event) { | |
| event.preventDefault(); | |
| const name = shortcutNameInput.value.trim(); | |
| if (!name) { | |
| showNotification('danger', 'Bitte gib einen Namen für den Shortcut ein.'); | |
| return; | |
| } | |
| try { | |
| const response = await fetch('/api/add_shortcut', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ | |
| name, | |
| paths: selectedFiles | |
| }) | |
| }); | |
| if (!response.ok) { | |
| const data = await response.json(); | |
| throw new Error(data.error || 'Fehler beim Erstellen des Shortcuts'); | |
| } | |
| const result = await response.json(); | |
| // Modal schließen | |
| saveShortcutModal.style.display = 'none'; | |
| // Formular zurücksetzen | |
| shortcutNameInput.value = ''; | |
| showNotification('success', result.message); | |
| } catch (error) { | |
| showNotification('danger', error.message); | |
| } | |
| } | |
| // Funktion zum Generieren einer Ausgabedatei | |
| function showGenerateModal() { | |
| if (selectedFiles.length === 0) { | |
| showNotification('danger', 'Bitte wähle zuerst Dateien aus.'); | |
| return; | |
| } | |
| outputFileInput.value = 'output.txt'; | |
| includeTreeCheckbox.checked = false; | |
| generateModal.style.display = 'block'; | |
| } | |
| // Funktion zum Generieren einer Textdatei | |
| async function generateTextFile(event) { | |
| event.preventDefault(); | |
| const outputFile = outputFileInput.value.trim(); | |
| const includeTree = includeTreeCheckbox.checked; | |
| if (!outputFile) { | |
| showNotification('danger', 'Bitte gib einen Namen für die Ausgabedatei ein.'); | |
| return; | |
| } | |
| try { | |
| // Erstelle einen temporären Shortcut für die ausgewählten Dateien | |
| const tempShortcutName = `temp_${Date.now()}`; | |
| await fetch('/api/add_shortcut', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ | |
| name: tempShortcutName, | |
| paths: selectedFiles | |
| }) | |
| }); | |
| // Verwende den temporären Shortcut, um die Textdatei zu generieren | |
| const response = await fetch('/api/use_shortcut', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ | |
| name: tempShortcutName, | |
| output_file: outputFile, | |
| include_tree: includeTree | |
| }) | |
| }); | |
| if (!response.ok) { | |
| const data = await response.json(); | |
| throw new Error(data.error || 'Fehler beim Generieren der Textdatei'); | |
| } | |
| const result = await response.json(); | |
| // Entferne den temporären Shortcut | |
| await fetch('/api/remove_shortcut', { | |
| method: 'DELETE', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ | |
| name: tempShortcutName | |
| }) | |
| }); | |
| // Modal schließen | |
| generateModal.style.display = 'none'; | |
| // Download-Link aktualisieren | |
| downloadLink.href = `/api/download/${encodeURIComponent(result.output_file)}`; | |
| // Download-Modal anzeigen | |
| downloadModal.style.display = 'block'; | |
| } catch (error) { | |
| showNotification('danger', error.message); | |
| } | |
| } | |
| // Event-Listener | |
| navigateUpBtn.addEventListener('click', navigateUp); | |
| saveAsShortcutBtn.addEventListener('click', saveAsShortcut); | |
| generateOutputBtn.addEventListener('click', showGenerateModal); | |
| createShortcutForm.addEventListener('submit', createShortcut); | |
| generateForm.addEventListener('submit', generateTextFile); | |
| // Initialisiere die Anwendung | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Lade das aktuelle Verzeichnis | |
| loadDirectory('/'); | |
| // Initialisiere die ausgewählten Dateien | |
| updateSelectedFilesUI(); | |
| }); | |
| </script> | |
| </body> | |
| </html> |