initial commit
This commit is contained in:
82
templates/_base.html
Normal file
82
templates/_base.html
Normal file
@@ -0,0 +1,82 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
|
||||
/>
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta name="format-detection" content="date=no" />
|
||||
<title>LAN Web</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ url_for('static', filename='theme/LCARS/assets/classic.css') }}"
|
||||
/>
|
||||
{% block styles %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<audio
|
||||
id="audio1"
|
||||
src="{{ url_for('static', filename='theme/LCARS/assets/beep1.mp3') }}"
|
||||
preload="auto"
|
||||
></audio>
|
||||
<audio
|
||||
id="audio2"
|
||||
src="{{ url_for('static', filename='theme/LCARS/assets/beep2.mp3') }}"
|
||||
preload="auto"
|
||||
></audio>
|
||||
<audio
|
||||
id="audio3"
|
||||
src="{{ url_for('static', filename='theme/LCARS/assets/beep3.mp3') }}"
|
||||
preload="auto"
|
||||
></audio>
|
||||
<audio
|
||||
id="audio4"
|
||||
src="{{ url_for('static', filename='theme/LCARS/assets/beep4.mp3') }}"
|
||||
preload="auto"
|
||||
></audio>
|
||||
|
||||
<section class="wrap-standard" id="column-3">
|
||||
<div class="wrap">
|
||||
<div class="left-frame-top">
|
||||
<button
|
||||
onclick="playSoundAndRedirect('audio1', '/')"
|
||||
class="panel-1-button"
|
||||
>
|
||||
LAN Web
|
||||
</button>
|
||||
<div class="panel-2">Infrastructure Overview</div>
|
||||
</div>
|
||||
<div class="right-frame-top">
|
||||
<div class="banner">
|
||||
LAN Web Interface | zwitschi.net / allucanget.biz
|
||||
</div>
|
||||
{% include "_top.html" %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="wrap" id="gap">
|
||||
{% include "_left.html" %}
|
||||
<div class="right-frame">
|
||||
<div class="bar-panel">
|
||||
<div class="bar-6"></div>
|
||||
<div class="bar-7"></div>
|
||||
<div class="bar-8"></div>
|
||||
<div class="bar-9"></div>
|
||||
<div class="bar-10"></div>
|
||||
</div>
|
||||
<main>{% block content %}{% endblock %}</main>
|
||||
<footer>
|
||||
© 2025 - LAN Web Interface for
|
||||
<a href="https://allucanget.biz">allucanget.biz</a> by
|
||||
<a href="https://zwitschi.net">zwitschi.net</a>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script src="{{ url_for('static', filename='theme/LCARS/assets/lcars.js') }}"></script>
|
||||
<div class="headtrim"></div>
|
||||
<div class="baseboard"></div>
|
||||
</body>
|
||||
</html>
|
||||
23
templates/_left.html
Normal file
23
templates/_left.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% block left %}
|
||||
<div class="left-frame">
|
||||
<button
|
||||
onclick="topFunction(); playSoundAndRedirect('audio4', '#')"
|
||||
id="topBtn"
|
||||
>
|
||||
<span class="hop">screen</span> top
|
||||
</button>
|
||||
<div>
|
||||
<div class="panel-3">03<span class="hop">-111968</span></div>
|
||||
<div class="panel-4">04<span class="hop">-041969</span></div>
|
||||
<div class="panel-5">05<span class="hop">-1701D</span></div>
|
||||
<div class="panel-6">06<span class="hop">-071984</span></div>
|
||||
<div class="panel-7">07<span class="hop">-081940</span></div>
|
||||
<div class="panel-8">08<span class="hop">-47148</span></div>
|
||||
<div class="panel-9">09<span class="hop">-081966</span></div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="panel-10">10<span class="hop">-31</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
23
templates/_nav.html
Normal file
23
templates/_nav.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% block nav %}
|
||||
<nav>
|
||||
<!--
|
||||
*** MAIN NAVIGATION BUTTONS ***
|
||||
Replace the hashtag '#' with a real URL (or not).
|
||||
If you don't want sound effects, replace the <button> element with a basic <a> tag shown here in this comment:
|
||||
<a href="#">01</a>
|
||||
<a href="#">02</a>
|
||||
<a href="#">03</a>
|
||||
<a href="#">04</a>
|
||||
-->
|
||||
<button onclick="playSoundAndRedirect('audio2', '/')">Systems</button>
|
||||
<button onclick="playSoundAndRedirect('audio2', '/numbers')">Numbers</button>
|
||||
<button onclick="playSoundAndRedirect('audio2', '/host/pve')">PVE</button>
|
||||
<button onclick="playSoundAndRedirect('audio2', '/host/naspve')">
|
||||
NASPVE
|
||||
</button>
|
||||
<!--
|
||||
<button onclick="playSoundAndRedirect('audio2', '#')">03</button>
|
||||
<button onclick="playSoundAndRedirect('audio2', '#')">04</button>
|
||||
-->
|
||||
</nav>
|
||||
{% endblock %}
|
||||
44
templates/_top.html
Normal file
44
templates/_top.html
Normal file
@@ -0,0 +1,44 @@
|
||||
{% block top %}
|
||||
<script>
|
||||
function getNumbers() {
|
||||
fetch("/numbers")
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
const wrapper = document.getElementById("default");
|
||||
wrapper.innerHTML = ""; // Clear existing content
|
||||
const lines = 24;
|
||||
const columns = 9;
|
||||
let index = 0;
|
||||
|
||||
for (let i = 0; i < columns; i++) {
|
||||
const columnDiv = document.createElement("div");
|
||||
columnDiv.className = "data-column";
|
||||
|
||||
for (let j = 0; j < lines; j++) {
|
||||
if (index < data.length) {
|
||||
const rowDiv = document.createElement("div");
|
||||
rowDiv.className = `dc-row-${j + 1}`;
|
||||
rowDiv.textContent = data[index];
|
||||
columnDiv.appendChild(rowDiv);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
wrapper.appendChild(columnDiv);
|
||||
}
|
||||
})
|
||||
.catch((error) => console.error("Error fetching numbers:", error));
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", getNumbers);
|
||||
</script>
|
||||
<div class="data-cascade-button-group">
|
||||
<div class="data-cascade-wrapper" id="default"></div>
|
||||
{% include "_nav.html" %}
|
||||
</div>
|
||||
<div class="bar-panel first-bar-panel">
|
||||
<div class="bar-1"></div>
|
||||
<div class="bar-2"></div>
|
||||
<div class="bar-3"></div>
|
||||
<div class="bar-4"></div>
|
||||
<div class="bar-5"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
6
templates/error.html
Normal file
6
templates/error.html
Normal file
@@ -0,0 +1,6 @@
|
||||
{% extends '_base.html' %} {% block content %}
|
||||
<h2>Error</h2>
|
||||
<div class="lcars-frame">
|
||||
<pre>{{ error }}</pre>
|
||||
</div>
|
||||
{% endblock %}
|
||||
88
templates/host_detail.html
Normal file
88
templates/host_detail.html
Normal file
@@ -0,0 +1,88 @@
|
||||
{% extends '_base.html' %} {% block styles %}
|
||||
<style>
|
||||
#services {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
.service {
|
||||
font-size: 1.2em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.service-link {
|
||||
display: flex;
|
||||
width: var(--lfw);
|
||||
justify-content: flex-end;
|
||||
align-items: flex-end;
|
||||
text-align: right;
|
||||
vertical-align: bottom;
|
||||
background-color: var(--panel-1-color);
|
||||
min-height: clamp(60px, 10vw, 120px);
|
||||
overflow: hidden;
|
||||
padding: var(--left-frame-padding);
|
||||
border-radius: 0;
|
||||
border-bottom: var(--panel-border);
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.if {
|
||||
background-color: var(--orange);
|
||||
}
|
||||
.fs {
|
||||
background-color: var(--blue);
|
||||
}
|
||||
.cmk {
|
||||
background-color: var(--green);
|
||||
}
|
||||
.pve {
|
||||
background-color: var(--lilac);
|
||||
}
|
||||
</style>
|
||||
{% endblock %} {% block content %}
|
||||
<h2>Services for {{ hostname }}</h2>
|
||||
<div id="services">
|
||||
{% for svc in services %}
|
||||
<div class="service">
|
||||
{% if svc.links %} {% for l in svc.links %} {% set classString =
|
||||
'service-link' %} {% if 'Interface' in svc.extensions.description %} {% set
|
||||
classString = classString + ' if' %} {% elif 'Filesystem' in
|
||||
svc.extensions.description %} {% set classString = classString + ' fs' %} {%
|
||||
elif 'Check_MK' in svc.extensions.description %} {% set classString =
|
||||
classString + ' cmk' %} {% elif 'PVE' in svc.extensions.description %} {%
|
||||
set classString = classString + ' pve' %} {% endif %}
|
||||
<button class="{{ classString }}" data-link="{{ l.href }}">
|
||||
{{ svc.extensions.description }}
|
||||
</button>
|
||||
{% endfor %} {% else %}
|
||||
<span class="service-label"
|
||||
>{{ svc.service_description or svc.title or svc.description or svc.name
|
||||
}}</span
|
||||
>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script>
|
||||
function playSound(audioId) {
|
||||
var audio = document.getElementById(audioId);
|
||||
audio.play();
|
||||
}
|
||||
|
||||
function serviceClick(event) {
|
||||
event.preventDefault();
|
||||
playSound("audio1");
|
||||
let url = event.currentTarget.getAttribute("data-link");
|
||||
let target = "/service/" + encodeURIComponent(url);
|
||||
window.location.href = target;
|
||||
}
|
||||
|
||||
document.querySelectorAll(".service-link").forEach(function (el) {
|
||||
el.addEventListener("click", serviceClick);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
63
templates/index.html
Normal file
63
templates/index.html
Normal file
@@ -0,0 +1,63 @@
|
||||
{% extends '_base.html' %} {% block styles %}
|
||||
<style>
|
||||
.host {
|
||||
font-size: 1.2em;
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 10px;
|
||||
margin-right: 10px;
|
||||
border-radius: 8px;
|
||||
background-color: var(--background-color);
|
||||
min-width: 280px;
|
||||
}
|
||||
.host h3 a {
|
||||
color: var(--blue);
|
||||
}
|
||||
.status-indicator {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.status-indicator.online {
|
||||
color: var(--green);
|
||||
}
|
||||
.status-indicator.offline {
|
||||
color: var(--red);
|
||||
}
|
||||
.checkmk-status {
|
||||
margin-top: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.checkmk-status.online {
|
||||
color: var(--green);
|
||||
}
|
||||
.checkmk-status.offline {
|
||||
color: var(--red);
|
||||
}
|
||||
</style>
|
||||
{% endblock %} {% block content %}
|
||||
<h2>Hosts</h2>
|
||||
<div class="lcars-frame">
|
||||
{% for h in hosts %}
|
||||
<div class="host">
|
||||
<h3>
|
||||
<button
|
||||
class="panel-1-button"
|
||||
onclick="playSoundAndRedirect('audio1', '/host/{{ h.name }}')"
|
||||
>
|
||||
{{ h.name }}
|
||||
</button>
|
||||
</h3>
|
||||
<div class="status-indicator {{ h.status }}">Status: {{ h.status }}</div>
|
||||
CPU: {{ h.cpu }}<br />
|
||||
Memory: {{ h.memory }}GB<br />
|
||||
VMs: {{ h.vm_count }}<br />
|
||||
Containers: {{ h.lxc_count }}<br />
|
||||
<div
|
||||
class="checkmk-status {% if h.check_mk.get('extensions') and h.check_mk.get('extensions').is_offline %}offline{% else %}online{% endif %}"
|
||||
>
|
||||
Monitoring: {% if h.check_mk.get('extensions') and
|
||||
h.check_mk.get('extensions').is_offline %}OFFLINE{% else %}ONLINE{% endif
|
||||
%}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
125
templates/service_detail.html
Normal file
125
templates/service_detail.html
Normal file
@@ -0,0 +1,125 @@
|
||||
{% extends '_base.html' %} {% block styles %}
|
||||
<style>
|
||||
h1 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#details {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
.service-detail,
|
||||
.service-status {
|
||||
display: flex;
|
||||
width: var(--lfw);
|
||||
justify-content: flex-end;
|
||||
align-items: flex-end;
|
||||
text-align: right;
|
||||
vertical-align: bottom;
|
||||
background-color: var(--panel-1-color);
|
||||
min-height: clamp(60px, 10vw, 120px);
|
||||
overflow: hidden;
|
||||
padding: var(--left-frame-padding);
|
||||
border-radius: 0;
|
||||
border-bottom: var(--panel-border);
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.service-status {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
{% endblock %} {% block content %}
|
||||
<h1>
|
||||
Host {{ service.extensions.host_name }} - {{ service.extensions.description }}
|
||||
Details
|
||||
</h1>
|
||||
<div id="details">
|
||||
<div class="service-status">Status: {{ service.extensions.state }}</div>
|
||||
<div class="service-detail">
|
||||
Last Check: {{ service.extensions.last_check }}
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function getServiceStateText(state) {
|
||||
switch (state) {
|
||||
case 0:
|
||||
return "OK";
|
||||
case 1:
|
||||
return "WARNING";
|
||||
case 2:
|
||||
return "CRITICAL";
|
||||
case 3:
|
||||
return "UNKNOWN";
|
||||
default:
|
||||
return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
function getServiceStateClass(state) {
|
||||
switch (state) {
|
||||
case 0:
|
||||
return "service-ok";
|
||||
case 1:
|
||||
return "service-warning";
|
||||
case 2:
|
||||
return "service-critical";
|
||||
case 3:
|
||||
return "service-unknown";
|
||||
default:
|
||||
return "service-na";
|
||||
}
|
||||
}
|
||||
|
||||
function getServiceStateColor(state) {
|
||||
switch (state) {
|
||||
case 0:
|
||||
return "var(--green)";
|
||||
case 1:
|
||||
return "var(--yellow)";
|
||||
case 2:
|
||||
return "var(--red)";
|
||||
case 3:
|
||||
return "var(--orange)";
|
||||
default:
|
||||
return "var(--gray)";
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
var statusDiv = document.querySelector(".service-status");
|
||||
var state = {{ service.extensions.state }};
|
||||
statusDiv.textContent = "Status: " + getServiceStateText(state);
|
||||
statusDiv.classList.add(getServiceStateClass(state));
|
||||
statusDiv.style.backgroundColor = getServiceStateColor(state);
|
||||
});
|
||||
|
||||
let service = {
|
||||
links: [
|
||||
{
|
||||
domainType: "link",
|
||||
rel: "self",
|
||||
href: "http://192.168.88.91/monitoring/check_mk/api/1.0/objects/service/pve-TCP%2520Connections",
|
||||
method: "GET",
|
||||
type: "application/json",
|
||||
},
|
||||
],
|
||||
domainType: "service",
|
||||
id: "pve-TCP Connections",
|
||||
title: "Service TCP Connections",
|
||||
members: {},
|
||||
extensions: {
|
||||
host_name: "pve",
|
||||
description: "TCP Connections",
|
||||
state: 0,
|
||||
state_type: 1,
|
||||
last_check: 1757963587,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user