{% extends "base.html" %} {% block title %}Container {{container_name}}{% endblock %} {% block content %} <main> <h1>Container <span class="container-name">{{container_name}}</span></h1> <h2>Status</h2> <div>TODO</div> <h2>Logs</h2> <code id="log"> </code> </main> <style scoped> main { display: flex; flex-direction: column; gap: 1rem; } h2 { text-transform: uppercase; margin: 0; padding: 0; } pre { margin: 0; padding: 0; } .container-name { color: #E796F3; } #log { background-color: #171625; display: flex; display: block; height: 800px; max-height: 80vh; overflow-y: auto; & .error { padding: 4px 8px; background-color: #3B1219; color: #FF9592; } & p { padding: 4px 8px; margin: 0; background-color: #1a1c38; &:nth-child(odd) { background-color: #212345; } } } </style> <script type="module"> import ansiFmt from 'https://esm.run/ansi-to-html'; const convert = new ansiFmt({ fg: '#E0DFFE', bg: '#171625', newline: false, escapeXML: true, stream: false, colors: ["#282c34", "#abb2bf", "#e06c75", "#be5046", "#98c379", "#d19a66", "#61afef", "#c678dd", "#56b6c2", "#4b5263", "#5c6370"] }); const logEl = document.querySelector("#log"); const logSource = new EventSource(`${location.origin}${location.pathname}/log`); logSource.addEventListener("error", (ev) => { logSource.close(); const err = document.createElement("div"); err.className = "error"; err.appendChild(document.createTextNode("No logs available after this (container not running)")); logEl.appendChild(err); err.scrollIntoView(); return; }); logSource.addEventListener("message", (ev) => { const data = JSON.parse(ev.data); // If an error is received stop listening if ("error" in data) { logSource.close(); const err = document.createElement("div"); err.className = "error"; err.appendChild(document.createTextNode(data.error)); logEl.appendChild(err); err.scrollIntoView(); return; } // Received lines of log if ("lines" in data) { data.lines.split("\n").map(line => convert.toHtml(line)).filter(line => line).forEach(line => { const lineEl = document.createElement("p"); lineEl.innerHTML = line.trim(); logEl.appendChild(lineEl); lineEl.scrollIntoView(); }); } }); // Fix copying from log (remove double newlines) logEl.addEventListener("copy", (event) => { const selection = document.getSelection(); event.clipboardData.setData("text/plain", selection.toString().replace(/\n\n/g, '\n')); event.preventDefault(); }); </script> {% endblock %}