More work on the management UI, multi printer is working, temps is sometimes working
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
<div id="connect-Button">
|
||||
{% if connected %}
|
||||
<form
|
||||
hx-post="/disconnect"
|
||||
hx-target="#connect-Button"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<button class="px-4 py-2 rounded bg-green-600 text-white hover:bg-red-600">
|
||||
Printer is connected. (Press to disconnect)
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Live status panel, will load once when revealed and then the returned fragment polls itself -->
|
||||
<div id="live-status" hx-post="/status" hx-trigger="revealed" hx-swap="outerHTML" class="mt-4"></div>
|
||||
{% else %}
|
||||
<form
|
||||
hx-post="/connect"
|
||||
hx-target="#connect-Button"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<button class="px-4 py-2 rounded bg-indigo-600 text-white hover:bg-indigo-500">
|
||||
Connect to Printer
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
34
Web UI Project/app/templates/_printer_card.html
Normal file
34
Web UI Project/app/templates/_printer_card.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<div id="printer-{{ printer.id }}" class="p-6 rounded border border-slate-700 bg-slate-800 w-full h-fit">
|
||||
<h2 class="text-xl font-bold mb-4 text-white" title="{{ printer.name }}">{{ printer.name }}</h2>
|
||||
|
||||
<!-- Connect/Disconnect button -->
|
||||
{% if printer.connected %}
|
||||
<form
|
||||
hx-post="/disconnect/{{ printer.id }}"
|
||||
hx-target="#printer-{{ printer.id }}"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<button class="w-full px-4 py-2 rounded bg-green-600 text-white hover:bg-red-600">
|
||||
{{ printer.name }} is connected (Press to disconnect)
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Live status panel -->
|
||||
<div id="status-{{ printer.id }}"
|
||||
hx-post="/status/{{ printer.id }}"
|
||||
hx-trigger="every 500ms[!document.activeElement.matches('#status-{{ printer.id }} input')]"
|
||||
hx-swap="outerHTML"
|
||||
class="mt-4">
|
||||
</div>
|
||||
{% else %}
|
||||
<form
|
||||
hx-post="/connect/{{ printer.id }}"
|
||||
hx-target="#printer-{{ printer.id }}"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<button class="w-full px-4 py-2 rounded bg-indigo-600 text-white hover:bg-indigo-500">
|
||||
Connect to {{ printer.name }}
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
14
Web UI Project/app/templates/_printer_grid.html
Normal file
14
Web UI Project/app/templates/_printer_grid.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 auto-rows-fr">
|
||||
{% for printer in printers.values() %}
|
||||
{% include "_printer_card.html" %}
|
||||
{% else %}
|
||||
<div class="col-span-full text-center text-slate-400">
|
||||
No printers configured. Check config.json file.
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Debug info -->
|
||||
<div class="mt-8 text-sm text-slate-500">
|
||||
Total Printers: {{ printers|length }}
|
||||
</div>
|
||||
@@ -1,37 +1,104 @@
|
||||
<div id="status-panel" hx-post="/status" hx-trigger="every 500ms" hx-swap="outerHTML" class="rounded bg-slate-800 border border-slate-700 p-4 text-slate-100">
|
||||
<div id="status-{{ printer.id }}"
|
||||
hx-post="/status/{{ printer.id }}"
|
||||
hx-trigger="every 1s"
|
||||
hx-swap="outerHTML"
|
||||
hx-target="#status-{{ printer.id }}"
|
||||
hx-select="#status-{{ printer.id }}">
|
||||
{% if status.error %}
|
||||
<div class="text-red-400">Error: {{ status.error }}</div>
|
||||
{% if status.debug_info %}
|
||||
<div class="mt-2 text-sm text-slate-400">
|
||||
<div>Printer ID: {{ status.debug_info.id }}</div>
|
||||
<div>Name: {{ status.debug_info.name }}</div>
|
||||
<div>Connected: {{ status.debug_info.connected }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="col-span-2">
|
||||
<div class="text-sm text-slate-400">Current File</div>
|
||||
<div class="font-medium">{{ status.current_file }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-slate-400">Nozzle Temperature</div>
|
||||
<div class="font-medium">{{ status.nozzle_temp }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-slate-400">Bed Temperature</div>
|
||||
<div class="font-medium">{{ status.bed_temp }}</div>
|
||||
<div class="w-full space-y-2">
|
||||
<!-- Current File -->
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-slate-400">Current File</span>
|
||||
<span class="font-medium">{{ status.current_file }}</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="text-sm text-slate-400">Chamber Temperature</div>
|
||||
<div class="font-medium">{{ status.chamber_temp }}</div>
|
||||
<!-- Status Items -->
|
||||
<style>
|
||||
/* Remove arrows/spinners from number inputs */
|
||||
input[type=number]::-webkit-inner-spin-button,
|
||||
input[type=number]::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-slate-400">Nozzle Temp</span>
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="font-medium">{{ status.nozzle_temp|int }}</span>
|
||||
<span class="text-slate-400">/</span>
|
||||
<form class="flex items-center"
|
||||
hx-post="/set-temperature/{{ printer.id }}"
|
||||
hx-trigger="blur from:input, keyup[key=='Enter'] from:input"
|
||||
hx-swap="none"
|
||||
onsubmit="event.preventDefault();">
|
||||
<input type="hidden" name="type" value="nozzle">
|
||||
<input type="number"
|
||||
name="value"
|
||||
class="w-[3ch] font-medium bg-transparent focus:outline-none focus:ring-1 focus:ring-blue-500 focus:rounded"
|
||||
value="{{ status.nozzle_target|default(status.nozzle_temp|int) }}"
|
||||
step="1"
|
||||
onblur="if(!this.value) { this.value = '0'; this.form.requestSubmit(); }"
|
||||
maxlength="3">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-slate-400">Progress</div>
|
||||
<div class="font-medium">{{ status.percentage }}</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-slate-400">Bed Temp</span>
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="font-medium">{{ status.bed_temp|int }}</span>
|
||||
<span class="text-slate-400">/</span>
|
||||
<form class="flex items-center"
|
||||
hx-post="/set-temperature/{{ printer.id }}"
|
||||
hx-trigger="blur from:input, keyup[key=='Enter'] from:input"
|
||||
hx-swap="none"
|
||||
onsubmit="event.preventDefault();">
|
||||
<input type="hidden" name="type" value="bed">
|
||||
<input type="number"
|
||||
name="value"
|
||||
class="w-[3ch] font-medium bg-transparent focus:outline-none focus:ring-1 focus:ring-blue-500 focus:rounded"
|
||||
value="{{ status.bed_target|default(status.bed_temp|int) }}"
|
||||
step="1"
|
||||
onblur="if(!this.value) { this.value = '0'; this.form.requestSubmit(); }"
|
||||
maxlength="3">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-slate-400">Remaining Time</div>
|
||||
<div class="font-medium">{{ status.remaining_time }}</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-slate-400">Chamber Temp</span>
|
||||
<span class="font-medium">{{ status.chamber_temp }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-slate-400">Time Done</div>
|
||||
<div class="font-medium">{{ status.finish_time }}</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-slate-400">Progress</span>
|
||||
<span class="font-medium">{{ status.percentage }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-slate-400">Time Left</span>
|
||||
<span class="font-medium">{{ status.remaining_time }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-sm text-slate-400">Est. Done</span>
|
||||
<span class="font-medium">{{ status.finish_time }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -10,9 +10,21 @@
|
||||
|
||||
<!-- HTMX: lets you call endpoints and swap HTML fragments, no custom JS needed -->
|
||||
<script src="https://unpkg.com/htmx.org@2.0.3"></script>
|
||||
|
||||
<script>
|
||||
// Handle messages from server
|
||||
document.body.addEventListener('showMessage', function(event) {
|
||||
const message = event.detail;
|
||||
const div = document.createElement('div');
|
||||
div.className = 'fixed top-4 right-4 bg-red-500 text-white px-6 py-3 rounded shadow-lg';
|
||||
div.textContent = message;
|
||||
document.body.appendChild(div);
|
||||
setTimeout(() => div.remove(), 3000);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body class="bg-slate-900 text-slate-100">
|
||||
<div class="max-w-3xl mx-auto p-6 bg-slate-800 rounded-lg shadow-md">
|
||||
<div class="w-11/12 max-w-[90%] lg:max-w-[95%] mx-auto p-6 bg-slate-800 rounded-lg shadow-md">
|
||||
<h1 class="text-2xl font-bold mb-4 text-white">X1 Carbon Connection</h1>
|
||||
{% block connect %}{% endblock %}
|
||||
<br>
|
||||
|
||||
@@ -1,52 +1,47 @@
|
||||
{% extends "base.html" %}
|
||||
{% block connect %}
|
||||
|
||||
<!-- Run action button -->
|
||||
<div id="connect-Button">
|
||||
{% if connected %}
|
||||
<div class="container mx-auto px-4 py-6">
|
||||
<!-- Connect All Button -->
|
||||
<div class="max-w-3xl mx-auto mb-8">
|
||||
<form
|
||||
hx-post="/disconnect"
|
||||
hx-target="#connect-Button"
|
||||
hx-swap="outerHTML"
|
||||
hx-post="/connect-all"
|
||||
hx-target="#printers-container"
|
||||
hx-swap="innerHTML"
|
||||
>
|
||||
<button class="px-4 py-2 rounded bg-green-600 text-white hover:bg-red-600">
|
||||
Printer is connected. (Press to disconnect)
|
||||
<button class="w-full px-6 py-3 rounded bg-indigo-600 text-white hover:bg-indigo-500 font-bold text-lg">
|
||||
Connect All Printers
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Live status panel, will load once when revealed and then the returned fragment polls itself -->
|
||||
<div id="live-status" hx-post="/status" hx-trigger="load" hx-swap="outerHTML" class="mt-4"></div>
|
||||
{% else %}
|
||||
<form
|
||||
hx-post="/connect"
|
||||
hx-target="#connect-Button"
|
||||
hx-swap="outerHTML"
|
||||
>
|
||||
<button class="px-4 py-2 rounded bg-indigo-600 text-white hover:bg-indigo-500">
|
||||
Connect to Printer
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<!-- Printer Grid Container -->
|
||||
<div id="printers-container" class="w-full">
|
||||
<div class="grid gap-6 grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
|
||||
{% for printer in printers.values() %}
|
||||
<div class="h-fit">
|
||||
{% include "_printer_card.html" %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-span-full text-center text-slate-400">
|
||||
No printers configured. Check config.json file.
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Debug info -->
|
||||
<div class="mt-8 text-sm text-slate-500">
|
||||
Total Printers: {{ printers|length }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block status %}
|
||||
<!--
|
||||
<form
|
||||
hx-post="/status"
|
||||
hx-target="#status-result"
|
||||
hx-swap="innerHTML"
|
||||
>
|
||||
<button class="px-4 py-2 rounded bg-indigo-600 text-white hover:bg-indigo-500">
|
||||
Get Printer Status
|
||||
</button>
|
||||
</form>
|
||||
<div id="status-result" class="mt-4"></div>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
/* Ensure grid items don't overlap at any screen size */
|
||||
@media (min-width: 1024px) {
|
||||
#printers-container .grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user