mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-09 03:36:48 +00:00
A stopped VM, an unreachable or unsupported console and a disabled serial console rendered the lite VNC page under the error: it connected to novncd anyway, showed "Something went wrong" and offered keys, Scale and Send CtrlAltDel for a console that was not there. A refused console was a bare text 403 inside the popup. - console-error.html: the console shell with the VM's name and the reason, no menu and no script; a refused or unknown VM gets it with 403 and without the VM's name, as before for everyone (no superuser exception). - The view signs the console token only for a page that connects. - console-menu.html: the Send key(s) menu and Fullscreen, included by the console pages; the serial page lists only the keys it sends (the VNC groups did nothing there). - Every console window is titled "<VM> - Console". - The lite page no longer takes a VNC password from its link. - The shell lost its 850px x 600px corner radius (a grey arc on the serial and error pages) and spans the window (container-fluid).
105 lines
3.7 KiB
HTML
105 lines
3.7 KiB
HTML
{% extends "console-base.html" %}
|
|
{% load i18n %}
|
|
{% load static %}
|
|
|
|
{% block head %}
|
|
<link rel="stylesheet" href="{% static 'css/xterm.css' %}"/>
|
|
<script src="{% static 'js/xterm/xterm.js' %}"></script>
|
|
<script src="{% static 'js/xterm/addon-fit.js' %}"></script>
|
|
|
|
<script src="{% static 'js/socket.io.js' %}"></script>
|
|
<style>
|
|
#terminal { flex: 1; min-height: 0; }
|
|
</style>
|
|
|
|
{% endblock %}
|
|
{% block navbarmenu %}{% include "console-menu.html" with serial=True %}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div style="background: white; padding-bottom: 5px;">
|
|
<span style="font-size: small;">Status: <span style="font-size: small;" id="status">connecting...</span></span>
|
|
<button id="button" type="button" onclick="myFunction();">Connect</button>
|
|
</div>
|
|
|
|
<div id="terminal"></div>
|
|
<script>
|
|
// socketiod is behind this page's own /socket.io/ location; the page's
|
|
// signed token is the credential. It lasts two minutes: a new
|
|
// connection takes a new page (Reconnect), not an automatic retry.
|
|
var socket = io({transports: ["websocket", "polling"], auth: {token: "{{ token|escapejs }}"}, reconnection: false});
|
|
|
|
const status = document.getElementById("status");
|
|
const button = document.getElementById("button");
|
|
|
|
var term = new Terminal({
|
|
cursorBlink: true,
|
|
});
|
|
var fitAddon = new FitAddon.FitAddon();
|
|
term.loadAddon(fitAddon);
|
|
|
|
term.open(document.getElementById('terminal'));
|
|
|
|
// typed and pasted input
|
|
term.onData((data) => {
|
|
socket.emit("pty_input", {"input": data})
|
|
});
|
|
|
|
socket.on("pty_output", function(output){
|
|
term.write(output["output"])
|
|
})
|
|
|
|
function showStatus(text, color) {
|
|
status.textContent = text;
|
|
status.style.backgroundColor = color;
|
|
button.textContent = socket.connected ? "{% trans 'Disconnect'|escapejs %}" : "{% trans 'Reconnect'|escapejs %}";
|
|
}
|
|
socket.on("connect", () => showStatus("{% trans 'connected'|escapejs %}", "lightgreen"));
|
|
socket.on("disconnect", () => showStatus("{% trans 'disconnected'|escapejs %}", "#ff8383"));
|
|
// the server says why: serial console off, an expired link, the console open elsewhere
|
|
socket.on("connect_error", (err) => showStatus(err.message, "#ff8383"));
|
|
|
|
function myFunction(){
|
|
if (socket.connected) {
|
|
socket.disconnect();
|
|
} else {
|
|
location.reload();
|
|
}
|
|
}
|
|
|
|
function resize(){
|
|
fitAddon.fit()
|
|
socket.emit("resize", {"cols": term.cols, "rows": term.rows})
|
|
}
|
|
|
|
function bindTerminalKey(id, str) {
|
|
const el = document.getElementById(id);
|
|
if (el) {
|
|
el.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
socket.emit("pty_input", {"input": str});
|
|
});
|
|
}
|
|
}
|
|
bindTerminalKey('ctrlc', '\x03');
|
|
bindTerminalKey('ctrld', '\x04');
|
|
bindTerminalKey('ctrlz', '\x1a');
|
|
bindTerminalKey('ctrlbackslash', '\x1c');
|
|
bindTerminalKey('sendtab', '\t');
|
|
bindTerminalKey('sendesc', '\x1b');
|
|
|
|
const fsBtn = document.getElementById('fullscreen_button');
|
|
if (fsBtn) {
|
|
fsBtn.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
if (document.fullscreenElement) {
|
|
document.exitFullscreen().catch(() => {});
|
|
} else {
|
|
document.documentElement.requestFullscreen().catch(() => {});
|
|
}
|
|
});
|
|
}
|
|
|
|
window.onresize = resize;
|
|
window.onload = resize;
|
|
</script>
|
|
{% endblock %}
|