Pathl.Stona/static/js/console.js
2026-01-30 21:41:10 +01:00

314 lines
9.4 KiB
JavaScript

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 = `
<span class="console-prompt">$</span>
<span class="console-command">${this.escapeHtml(command)}</span>
`;
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();
}
}
};