Add root terminal
This commit is contained in:
@@ -591,6 +591,33 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Root Terminal -->
|
||||
<section id="root-terminal" class="station" data-label="[ STATION: ROOT_TERMINAL ]">
|
||||
<div class="station-header">
|
||||
<h2>Server Shell Access</h2>
|
||||
<a href="#top" class="back-to-top">[^ BACK_TO_TOP]</a>
|
||||
</div>
|
||||
|
||||
<div class="panel terminal-box" style="margin-top: 0; border-color: #ff555566;">
|
||||
<div class="terminal-header" style="border-bottom-color: #ff555566;">
|
||||
<div class="terminal-label" style="color: #ff5555;">ROOT@DOKKU:~$</div>
|
||||
<button class="copy-btn" onclick="copyLogs('terminal-output')"
|
||||
style="border-color: #ff555566; color: #ff5555;">COPY BUFFER</button>
|
||||
</div>
|
||||
<div id="terminal-output" class="terminal-body"
|
||||
style="height: 400px; font-size: 13px; background: #000;">
|
||||
<div class="log-line log-info">Dokku Terminal initialized. Ready for commands.</div>
|
||||
</div>
|
||||
<div style="display: flex; background: #000; padding: 10px; border-top: 1px solid #ff555566;">
|
||||
<span style="color: #00ff88; font-weight: 700; margin-right: 10px;">$</span>
|
||||
<input type="text" id="terminal-input" placeholder="Enter command..." spellcheck="false"
|
||||
autocomplete="off"
|
||||
style="background: transparent; color: #c9d1d9; border: none; outline: none; flex: 1; font-family: inherit; font-size: 13px;"
|
||||
onkeydown="if(event.key === 'Enter') runCommand()">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -598,7 +625,7 @@
|
||||
const el = document.getElementById(id);
|
||||
const text = el.innerText;
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
const btn = event.target;
|
||||
const btn = event.currentTarget || event.target;
|
||||
const orig = btn.innerText;
|
||||
btn.innerText = 'COPIED';
|
||||
setTimeout(() => { btn.innerText = orig; }, 2000);
|
||||
@@ -675,6 +702,47 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function runCommand() {
|
||||
const input = document.getElementById('terminal-input');
|
||||
const output = document.getElementById('terminal-output');
|
||||
const command = input.value.trim();
|
||||
|
||||
if (!command) return;
|
||||
|
||||
// Add command to terminal
|
||||
const cmdLine = document.createElement('div');
|
||||
cmdLine.className = 'log-line';
|
||||
cmdLine.innerHTML = `<span style="color: #00ff88;">$ ${command}</span>`;
|
||||
output.appendChild(cmdLine);
|
||||
|
||||
input.value = '';
|
||||
output.scrollTop = output.scrollHeight;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/terminal/exec', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ command })
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
const resultLine = document.createElement('div');
|
||||
resultLine.className = result.error ? 'log-line log-error' : 'log-line';
|
||||
resultLine.style.whiteSpace = 'pre-wrap';
|
||||
resultLine.innerText = result.output;
|
||||
output.appendChild(resultLine);
|
||||
|
||||
output.scrollTop = output.scrollHeight;
|
||||
} catch (err) {
|
||||
const errLine = document.createElement('div');
|
||||
errLine.className = 'log-line log-error';
|
||||
errLine.innerText = `FATAL ERROR: ${err.message}`;
|
||||
output.appendChild(errLine);
|
||||
output.scrollTop = output.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-scroll logic
|
||||
document.querySelectorAll('.terminal-body').forEach(el => {
|
||||
el.scrollTop = el.scrollHeight;
|
||||
|
||||
Reference in New Issue
Block a user