--wip-- [skip ci]
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging as lg
|
import logging as lg
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
@@ -11,6 +13,19 @@ def main() -> None:
|
|||||||
format="%(asctime)s : [%(levelname)s] : %(threadName)s : %(name)s :: %(message)s",
|
format="%(asctime)s : [%(levelname)s] : %(threadName)s : %(name)s :: %(message)s",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_ = subprocess.Popen(
|
||||||
|
[
|
||||||
|
"npx",
|
||||||
|
"tailwindcss",
|
||||||
|
"-i",
|
||||||
|
"input.css",
|
||||||
|
"-o",
|
||||||
|
"../src/judas_web/static/css/dist/tailwind.css",
|
||||||
|
"--watch",
|
||||||
|
],
|
||||||
|
cwd="tailwind/",
|
||||||
|
)
|
||||||
|
|
||||||
web_server = WebServer("http://127.0.0.1:8000/api/v1", "supersecretkey")
|
web_server = WebServer("http://127.0.0.1:8000/api/v1", "supersecretkey")
|
||||||
web_server.run(debug=True, host="0.0.0.0", port=5000)
|
web_server.run(debug=True, host="0.0.0.0", port=5000)
|
||||||
|
|
||||||
|
|||||||
@@ -9,27 +9,50 @@ $(document).ready(function () {
|
|||||||
}, 3000);
|
}, 3000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadClientDetails = (clientId) => {
|
|
||||||
fetch(`/client/${clientId}`)
|
|
||||||
.then((response) => response.text())
|
|
||||||
.then((html) => {
|
|
||||||
$("#content").html(html);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Error fetching client details:", error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// load client_details for the client specified in the URL
|
// load client_details for the client specified in the URL
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
const clientId = urlParams.get("client");
|
const clientId = urlParams.get("client");
|
||||||
if (clientId) {
|
if (clientId) {
|
||||||
loadClientDetails(clientId);
|
// loadClientDetails(clientId);
|
||||||
$(`#client-list a[href="?client=${clientId}"]`).addClass("active");
|
$(`#client-list a[href="?client=${clientId}"]`).addClass("active");
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#notify").hide();
|
$("#notify").hide();
|
||||||
|
|
||||||
|
// Show the correct nav item and panel by default based on GET param
|
||||||
|
const urlParamsPanel = new URLSearchParams(window.location.search);
|
||||||
|
const panelParam = urlParamsPanel.get("panel");
|
||||||
|
let navItems = $("#panel-content > nav > ul > li");
|
||||||
|
let panelToShow = panelParam;
|
||||||
|
let navToActivate = null;
|
||||||
|
if (panelToShow) {
|
||||||
|
navToActivate = navItems.filter(`[panel='${panelToShow}']`).first();
|
||||||
|
}
|
||||||
|
if (!navToActivate || navToActivate.length === 0) {
|
||||||
|
navToActivate = navItems.first();
|
||||||
|
panelToShow = navToActivate.attr("panel");
|
||||||
|
}
|
||||||
|
navItems.removeClass("bg-ctp-surface0");
|
||||||
|
navToActivate.addClass("bg-ctp-surface0");
|
||||||
|
$(".panels").addClass("hidden");
|
||||||
|
if (panelToShow) {
|
||||||
|
$(`#${panelToShow}`).removeClass("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
navItems.on("click", function (e) {
|
||||||
|
navItems.removeClass("bg-ctp-surface0");
|
||||||
|
$(this).addClass("bg-ctp-surface0");
|
||||||
|
$(".panels").addClass("hidden");
|
||||||
|
const panelToShow = $(this).attr("panel");
|
||||||
|
$(`#${panelToShow}`).removeClass("hidden");
|
||||||
|
|
||||||
|
// Update the URL GET params with the selected panel
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
urlParams.set("panel", panelToShow);
|
||||||
|
const newUrl = `${window.location.pathname}?${urlParams.toString()}`;
|
||||||
|
window.history.pushState({ path: newUrl }, "", newUrl);
|
||||||
|
});
|
||||||
|
|
||||||
socket.on("connect", () => {
|
socket.on("connect", () => {
|
||||||
console.log("Connected to server");
|
console.log("Connected to server");
|
||||||
$("#no-connection-message").hide();
|
$("#no-connection-message").hide();
|
||||||
@@ -159,7 +182,7 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
clientId = clientId.replace("client=", "");
|
clientId = clientId.replace("client=", "");
|
||||||
|
|
||||||
loadClientDetails(clientId);
|
// loadClientDetails(clientId);
|
||||||
$("#client-list a").removeClass("bg-ctp-surface0");
|
$("#client-list a").removeClass("bg-ctp-surface0");
|
||||||
$(this).addClass("bg-ctp-surface0");
|
$(this).addClass("bg-ctp-surface0");
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -167,5 +190,17 @@ $(document).ready(function () {
|
|||||||
let newUrl = `${window.location.pathname}?client=${clientId}`;
|
let newUrl = `${window.location.pathname}?client=${clientId}`;
|
||||||
window.history.pushState({ path: newUrl }, "", newUrl);
|
window.history.pushState({ path: newUrl }, "", newUrl);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update client details panel
|
||||||
|
if (clientId) {
|
||||||
|
const client = data.clients[clientId];
|
||||||
|
if (client) {
|
||||||
|
$("#client-hostname").text(client.initial_telemetry.platform.node);
|
||||||
|
$("#client-status").text(client.status);
|
||||||
|
$("#client-last_seen").text(
|
||||||
|
new Date(client.last_seen * 1000).toLocaleString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,10 +4,8 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>{% block title %}{% endblock %} – judas</title>
|
<title>{% block title %}{% endblock %} – judas</title>
|
||||||
<link
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/dist/tailwind.css') }}" />
|
||||||
rel="stylesheet"
|
|
||||||
href="{{ url_for('static', filename='css/style.css') }}"
|
|
||||||
/>
|
|
||||||
<link rel="stylesheet" href="https://cdn-uicons.flaticon.com/2.6.0/uicons-regular-rounded/css/uicons-regular-rounded.css" />
|
<link rel="stylesheet" href="https://cdn-uicons.flaticon.com/2.6.0/uicons-regular-rounded/css/uicons-regular-rounded.css" />
|
||||||
<link rel="stylesheet" href="https://cdn-uicons.flaticon.com/2.6.0/uicons-regular-straight/css/uicons-regular-straight.css" />
|
<link rel="stylesheet" href="https://cdn-uicons.flaticon.com/2.6.0/uicons-regular-straight/css/uicons-regular-straight.css" />
|
||||||
<link rel="stylesheet" href="https://cdn-uicons.flaticon.com/2.6.0/uicons-solid-rounded/css/uicons-solid-rounded.css" />
|
<link rel="stylesheet" href="https://cdn-uicons.flaticon.com/2.6.0/uicons-solid-rounded/css/uicons-solid-rounded.css" />
|
||||||
@@ -29,10 +27,12 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="bg-ctp-base text-ctp-text min-h-screen flex flex-col {% block body_class %}{% endblock %}">
|
||||||
{% include "base/header.html" %}
|
{% include "base/header.html" %}
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
<div id="content" class="flex flex-col grow {% block content_class %}{% endblock %}">
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
{% block scripts %}{% endblock %}
|
{% block scripts %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -8,6 +8,6 @@
|
|||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
<a class="btn-primary" href="{{ url_for('auth.logout') }}">Logout</a>
|
<a class="btn-primary" href="{{ url_for('auth.logout') }}">Logout</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a class="button" href="{{ url_for('auth.login') }}">Login</a>
|
<a class="btn-primary" href="{{ url_for('auth.login') }}">Login</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -2,20 +2,22 @@
|
|||||||
|
|
||||||
{% block title %}home{% endblock %}
|
{% block title %}home{% endblock %}
|
||||||
|
|
||||||
|
{% block content_class %}
|
||||||
|
text-center gap-2
|
||||||
|
{% endblock content_class %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="content" class="center">
|
<div class="mt-16">
|
||||||
<div style="margin-top: 2rem">
|
|
||||||
<p>Welcome to</p>
|
<p>Welcome to</p>
|
||||||
<h2 id="typing-text" style="font-size: 3rem">judas</h2>
|
<h2 id="typing-text" class="my-2 text-6xl font-mono font-bold">judas</h2>
|
||||||
<p>a remote PC fleet management system</p>
|
<p>a remote PC fleet management system</p>
|
||||||
</div>
|
|
||||||
<p style="color: var(--ctp-red)"><strong>Notice:</strong> Please use this system responsibly and in accordance with all applicable laws and organizational policies.</p>
|
|
||||||
{% if logged %}
|
|
||||||
<p><a class="button" href="{{ url_for('panel.panel') }}">Go to panel</a></p>
|
|
||||||
{% else %}
|
|
||||||
<p>Please <a href="{{ url_for('auth.login')}}" class="link">log in</a> to manage your remote PCs.</p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
|
<p class="text-ctp-red"><strong>Notice:</strong> Please use this system responsibly and in accordance with all applicable laws and organizational policies.</p>
|
||||||
|
{% if logged %}
|
||||||
|
<p><a class="btn-primary" href="{{ url_for('panel.panel') }}">Go to panel</a></p>
|
||||||
|
{% else %}
|
||||||
|
<p>Please <a href="{{ url_for('auth.login')}}" class="link">log in</a> to manage your remote PCs.</p>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
|||||||
@@ -4,10 +4,32 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<main class="flex grow h-full">
|
<main class="flex grow h-full">
|
||||||
<aside class="border-r-4 border-r-ctp-mantle">
|
<aside class="border-r-4 border-r-ctp-mantle w-80">
|
||||||
<ul id="client-list"></ul>
|
<ul id="client-list"></ul>
|
||||||
</aside>
|
</aside>
|
||||||
<div id="content" class="grow"></div>
|
<div id="panel-content" class="flex flex-row grow">
|
||||||
|
<nav class="border-r-4 border-r-ctp-mantle">
|
||||||
|
<ul>
|
||||||
|
<li class="px-4 py-2 hover:bg-ctp-mantle cursor-pointer" panel="summary">Summary</li>
|
||||||
|
<li class="px-4 py-2 hover:bg-ctp-mantle cursor-pointer" panel="settings">Settings</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<div id="summary" class="panels hidden grow p-4">
|
||||||
|
<h1 class="text-2xl font-bold mb-4">Summary</h1>
|
||||||
|
<div class="flex grow flex-col gap-4">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h2 class="text-xl font-semibold"><span id="client-hostname"></span> (<span id="client-status"></span>)</h2>
|
||||||
|
<h2 class="text-xl font-semibold">Last seen: <span id="client-last_seen"></span></h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="settings" class="panels hidden">
|
||||||
|
<h1 class="text-2xl font-bold mb-4">Settings</h1>
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<!-- Settings content will be dynamically inserted here -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
1
tailwind/.gitignore
vendored
Normal file
1
tailwind/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
node_modules/
|
||||||
37
tailwind/input.css
Normal file
37
tailwind/input.css
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
@source "../src/judas_web/templates/**/*.html";
|
||||||
|
@source "../src/judas_web/static/js/**/*.js";
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
@apply px-2 py-1 rounded text-sm font-medium text-ctp-base bg-ctp-blue hover:bg-ctp-lavender active:bg-ctp-sapphire;
|
||||||
|
}
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--color-ctp-rosewater: #f5e0dc;
|
||||||
|
--color-ctp-flamingo: #f2cdcd;
|
||||||
|
--color-ctp-pink: #f5c2e7;
|
||||||
|
--color-ctp-mauve: #cba6f7;
|
||||||
|
--color-ctp-red: #f38ba8;
|
||||||
|
--color-ctp-maroon: #eba0ac;
|
||||||
|
--color-ctp-peach: #fab387;
|
||||||
|
--color-ctp-yellow: #f9e2af;
|
||||||
|
--color-ctp-green: #a6e3a1;
|
||||||
|
--color-ctp-teal: #94e2d5;
|
||||||
|
--color-ctp-sky: #89dceb;
|
||||||
|
--color-ctp-sapphire: #74c7ec;
|
||||||
|
--color-ctp-blue: #89b4fa;
|
||||||
|
--color-ctp-lavender: #b4befe;
|
||||||
|
--color-ctp-text: #cdd6f4;
|
||||||
|
--color-ctp-subtext1: #bac2de;
|
||||||
|
--color-ctp-subtext0: #a6adc8;
|
||||||
|
--color-ctp-overlay2: #9399b2;
|
||||||
|
--color-ctp-overlay1: #7f849c;
|
||||||
|
--color-ctp-overlay0: #6c7086;
|
||||||
|
--color-ctp-surface2: #585b70;
|
||||||
|
--color-ctp-surface1: #45475a;
|
||||||
|
--color-ctp-surface0: #313244;
|
||||||
|
--color-ctp-base: #1e1e2e;
|
||||||
|
--color-ctp-mantle: #181825;
|
||||||
|
--color-ctp-crust: #11111b;
|
||||||
|
}
|
||||||
1037
tailwind/package-lock.json
generated
Normal file
1037
tailwind/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
tailwind/package.json
Normal file
17
tailwind/package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "tailwind",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"type": "commonjs",
|
||||||
|
"dependencies": {
|
||||||
|
"@tailwindcss/cli": "^4.2.1",
|
||||||
|
"tailwindcss": "^4.2.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user