Files
cloud-config/mushroom/helm/index.html
Paul Mathieu 0cf7c9b908 Initial commit: mushroom, zetikettes
With basic config to have TLS certs with ACME.
It works!

TODO:
- gitea
- bar-jupyter
2026-03-02 06:48:46 +00:00

212 lines
6.5 KiB
HTML

<html>
<head>
<title>A simple netcat client</title>
<link rel="icon">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<style>
body {
background-color: rgb(4, 18, 0);
color: rgb(199, 224, 192);
}
.container {
padding: 32px;
width: 800px;
}
@media only screen and (max-width: 480px) {
body {
font-size: 100%;
}
.container {
width: 100%;
padding: 0px;
}
}
.console {
height: 480px;
border: solid;
border-radius: 8px;
border-color: rgb(76, 75, 83);
padding: 10px;
background-color: rgb(8, 36, 0);
margin-bottom: 10px;
margin-top: 10px;
}
.console-text {
overflow: auto;
max-height: calc(100% - 20px);
white-space: pre-wrap;
}
.echo {
font-size: 80%;
color: rgb(133, 199, 170);
}
.online-status {
font-weight: bold;
color: greenyellow;
font-size: larger;
display: none;
text-align: center;
width: 120px;
}
</style>
<script src="https://code.jquery.com/jquery-3.7.0.slim.min.js"></script>
<script>
$(() => {
let ws;
const history = [];
let history_cursor;
function colorize(input) {
var mapObj = {
30: '#000000',
31: '#cc0000',
32: '#4e9a06',
33: '#c4a000',
34: '#729fcf',
35: '#75507b',
36: '#06989a',
37: '#d3d7cf',
90: '#555753',
91: '#ef2929',
92: '#8ae234',
93: '#fce94f',
94: '#32afff',
95: '#ad7fa8',
96: '#34e2e2',
97: '#ffffff',
};
const colored = input.replace(/\033\[(?:0;)?(\d+)m/g, function (_, color) {
return `</span><span style="color:${mapObj[color]}">`;
}).replace(/\033\[0m/g, '</span><span>');
return `<span>${colored}</span>`;
}
document.addEventListener("visibilitychange", () => {
if (!document.hidden) {
$('link')[0].href = document.createElement('canvas').toDataURL();
}
});
function notifyActivity() {
if (document.hasFocus()) {
return;
}
let c = document.createElement('canvas');
c.width = 16;
c.height = 16;
let ctx = c.getContext('2d');
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(7, 7, 3, 0, 2*Math.PI);
ctx.fill();
$('link')[0].href = c.toDataURL();
}
$('.input').keydown(e => {
if (e.key == "ArrowUp") {
if (history_cursor === undefined) {
history_cursor = history.length;
} else if (history_cursor === 0) {
return true;
}
history_cursor--;
$('.input').val(history[history_cursor]);
return false;
} else if (e.key == "ArrowDown" && history_cursor !== undefined) {
if (history_cursor >= history.length - 1) {
history_cursor = undefined;
$('.input').val('');
return false;
}
history_cursor++;
$('.input').val(history[history_cursor]);
return false;
}
});
$('.input').keypress(e => {
if (e.key == "Enter") {
if (ws === undefined || ws.readyState !== 1) {
return true;
}
const sh = $('.console-text').get(0).scrollHeight;
const line = $('.input').val()
$('.console-text').append('<br /> <span class="echo">&gt; ' + line + '</span><br />').scrollTop(sh);
$('.input').val('');
history.push(line);
history_cursor = undefined;
ws.send(`${line}\n`);
return false; //<---- Add this line
}
});
function connect() {
ws = new WebSocket($('input[name=wshost]').val());
ws.onerror = console.log;
ws.onclose = e => {
$('.online-status').hide();
$('input[type=button]').prop('value', 'Connect');
};
ws.onopen = e => {
$('.online-status').show();
$('.input').focus();
};
ws.onmessage = m => {
m.data.text().then(text => {
text = text
.replaceAll('&', '&amp;')
.replaceAll('<', '&lt;')
.replaceAll('>', '&gt;');
const sh = $('.console-text').get(0).scrollHeight;
$('.console-text').append(colorize(text)).scrollTop(sh);
});
notifyActivity();
};
$('input[type=button]').prop('value', 'Disconnect');
}
function disconnect() {
ws.close();
}
$('input[type=button]').click(() => {
if (ws && ws.readyState !== WebSocket.CLOSED) {
disconnect();
} else {
connect();
}
});
});
</script>
</head>
<body>
<div class="container">
<input name="wshost" value="wss://mushroom.jenova.ponteilla.net/ws"><input type="button" value="Connect">
<span class="online-status">online</span>
<div class="console">
<pre class="console-text"></pre>
</div>
<input class="input" style="width:100%">
</div>
</body>
</html>