class QLConsole { constructor(username, project) { this.username = username; this.project = project; this.history = []; this.historyIndex = -1; this.currentCommand = ''; this.isProcessing = false; this.init(); } init() { this.bindEvents(); this.printWelcome(); this.setupHistory(); } bindEvents() { const input = document.getElementById('consoleInput'); const output = document.getElementById('consoleOutput'); if (!input || !output) return; // Obsługa klawisza Enter input.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); this.executeCommand(input.value.trim()); input.value = ''; this.historyIndex = -1; } // Strzałki dla historii else if (e.key === 'ArrowUp') { e.preventDefault(); this.navigateHistory(-1); } else if (e.key === 'ArrowDown') { e.preventDefault(); this.navigateHistory(1); } // Tab dla autouzupełniania else if (e.key === 'Tab') { e.preventDefault(); this.autoComplete(input); } }); // Obsługa przycisków konsoli document.getElementById('clearConsoleBtn')?.addEventListener('click', () => this.clearConsole()); document.getElementById('helpConsoleBtn')?.addEventListener('click', () => this.showHelp()); // Fokus na input przy kliknięciu w konsolę output.addEventListener('click', () => { input.focus(); }); // Auto-focus przy załadowaniu setTimeout(() => input.focus(), 100); } async executeCommand(command) { if (!command) return; // Dodaj do historii if (command !== this.history[this.history.length - 1]) { this.history.push(command); if (this.history.length > 50) { this.history.shift(); } } // Wyświetl komendę this.printCommand(command); // Ustaw flagę przetwarzania this.isProcessing = true; this.showLoading(); try { const response = await fetch(`/editor/${this.username}/${this.project}/console`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ command: command }) }); const data = await response.json(); if (response.ok) { if (data.output === 'CLEAR_CONSOLE') { this.clearConsole(); this.printWelcome(); } else { this.printResponse(data.output); } } else { this.printError(data.output || 'Błąd wykonania komendy'); } } catch (error) { this.printError(`Błąd sieciowy: ${error.message}`); } finally { this.isProcessing = false; this.hideLoading(); this.scrollToBottom(); } } printWelcome() { const welcome = ` ======================================== QL Console - Terminal systemowy Projekt: ${this.project} Użytkownik: ${this.username} Wpisz 'help' aby zobaczyć dostępne komendy ======================================== `.trim(); this.printInfo(welcome); } printCommand(command) { const output = document.getElementById('consoleOutput'); const line = document.createElement('div'); line.className = 'console-line'; line.innerHTML = ` $ ${this.escapeHtml(command)} `; output.appendChild(line); } printResponse(response) { const output = document.getElementById('consoleOutput'); const lines = response.split('\n'); lines.forEach(line => { const div = document.createElement('div'); div.className = 'console-line'; if (line.includes('Błąd:') || line.includes('Nie można')) { div.className += ' console-error'; } else if (line.includes('Utworzono') || line.includes('Zmieniono') || line.includes('Usunięto')) { div.className += ' console-success'; } else if (line.includes('Ścieżka:') || line.includes('Katalog:')) { div.className += ' console-path'; } else { div.className += ' console-info'; } div.textContent = line; output.appendChild(div); }); this.scrollToBottom(); } printError(error) { const output = document.getElementById('consoleOutput'); const line = document.createElement('div'); line.className = 'console-line console-error'; line.textContent = `❌ ${error}`; output.appendChild(line); this.scrollToBottom(); } printInfo(info) { const output = document.getElementById('consoleOutput'); const line = document.createElement('div'); line.className = 'console-line console-info'; line.textContent = info; output.appendChild(line); this.scrollToBottom(); } clearConsole() { const output = document.getElementById('consoleOutput'); output.innerHTML = ''; } showHelp() { const help = `Dostępne komendy: • help - wyświetla tę pomoc • ls - lista plików i folderów • cd [dir] - zmień katalog • pwd - pokaż aktualny katalog • mkdir [dir] - utwórz nowy katalog • touch [file] - utwórz nowy plik • cat [file] - wyświetl zawartość pliku • rm [file] - usuń plik • clear - wyczyść konsolę`; this.printResponse(help); } navigateHistory(direction) { if (this.history.length === 0) return; const input = document.getElementById('consoleInput'); if (direction === -1) { // Strzałka w górę if (this.historyIndex < this.history.length - 1) { if (this.historyIndex === -1) { this.currentCommand = input.value; } this.historyIndex++; } } else { // Strzałka w dół if (this.historyIndex > 0) { this.historyIndex--; } else if (this.historyIndex === 0) { this.historyIndex = -1; input.value = this.currentCommand; return; } } if (this.historyIndex >= 0) { input.value = this.history[this.history.length - 1 - this.historyIndex]; } // Przesuń kursor na koniec input.selectionStart = input.selectionEnd = input.value.length; } autoComplete(input) { const current = input.value; // Proste autouzupełnianie - można rozbudować const commands = ['help', 'ls', 'cd', 'pwd', 'mkdir', 'touch', 'cat', 'rm', 'clear']; const matching = commands.filter(cmd => cmd.startsWith(current)); if (matching.length === 1) { input.value = matching[0]; } else if (matching.length > 1) { this.printInfo(`Możliwe komendy: ${matching.join(', ')}`); } } showLoading() { const output = document.getElementById('consoleOutput'); const loader = document.createElement('div'); loader.id = 'consoleLoading'; loader.className = 'console-loading'; output.appendChild(loader); } hideLoading() { const loader = document.getElementById('consoleLoading'); if (loader) { loader.remove(); } } scrollToBottom() { const output = document.getElementById('consoleOutput'); output.scrollTop = output.scrollHeight; } escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } setupHistory() { // Załaduj historię z localStorage const savedHistory = localStorage.getItem(`console_history_${this.username}_${this.project}`); if (savedHistory) { this.history = JSON.parse(savedHistory); } // Zapisz historię przy wyjściu window.addEventListener('beforeunload', () => { localStorage.setItem(`console_history_${this.username}_${this.project}`, JSON.stringify(this.history.slice(-20))); }); } } // Inicjalizacja konsoli document.addEventListener('DOMContentLoaded', () => { const username = document.body.dataset.username; const project = document.body.dataset.project; if (username && project) { window.qlconsole = new QLConsole(username, project); } }); // Globalne funkcje dostępne z konsoli window.Console = { clear: function() { if (window.qlconsole) { window.qlconsole.clearConsole(); window.qlconsole.printWelcome(); } }, run: function(command) { if (window.qlconsole) { window.qlconsole.executeCommand(command); } }, help: function() { if (window.qlconsole) { window.qlconsole.showHelp(); } } };