diff --git a/admin/admin.css b/admin/admin.css
new file mode 100644
index 0000000..2750abc
--- /dev/null
+++ b/admin/admin.css
@@ -0,0 +1,96 @@
+body {
+ font-family: Arial, sans-serif;
+ background: linear-gradient(135deg, #1f2933, #3a4a5a);
+ margin: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 100vh;
+ color: #333;
+}
+
+.card {
+ background: white;
+ padding: 30px;
+ border-radius: 12px;
+ width: 900px;
+ box-shadow: 0 10px 30px rgba(0,0,0,0.3);
+}
+
+h1 {
+ text-align: center;
+ margin-top: 0;
+}
+
+table {
+ width: 100%;
+ border-collapse: collapse;
+ margin-top: 15px;
+}
+
+th {
+ background: #4CAF50;
+ color: white;
+ padding: 10px;
+}
+
+td {
+ padding: 10px;
+ border-bottom: 1px solid #ddd;
+}
+
+.inactive {
+ background: #eee;
+ color: #888;
+}
+
+.button {
+ background: #4CAF50;
+ color: white;
+ padding: 8px 14px;
+ border-radius: 6px;
+ text-decoration: none;
+}
+
+.button.red {
+ background: #d9534f;
+}
+
+.test-result {
+ margin-left: 10px;
+ font-weight: bold;
+}
+
+.form-row {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex-wrap: wrap;
+}
+
+.form-row input[type="text"] {
+ width: 260px; /* pick what looks good */
+}
+
+form input[type="text"],
+form input[type="url"] {
+ width: 100%;
+ margin-bottom: 10px;
+}
+
+.form-row input[type="text"] {
+ width: auto;
+ margin-bottom: 0;
+}
+
+.form-row input.printer-name {
+ width: 180px;
+}
+
+.form-row input[name="url"] {
+ width: 200px;
+}
+
+.form-row input[name="apiKey"] {
+ width: 260px;
+}
diff --git a/admin/auth.php b/admin/auth.php
new file mode 100644
index 0000000..8fe1aa4
--- /dev/null
+++ b/admin/auth.php
@@ -0,0 +1,58 @@
+
+
diff --git a/admin/delete.php b/admin/delete.php
new file mode 100644
index 0000000..5acdab4
--- /dev/null
+++ b/admin/delete.php
@@ -0,0 +1,16 @@
+ '',
+ 'url' => '',
+ 'apiKey' => '',
+ 'active' => true
+];
+
+function getPrinterName($url, $apiKey) {
+
+ $base = rtrim($url, '/');
+
+ $opts = [
+ "http" => [
+ "method" => "GET",
+ "header" => "X-Api-Key: $apiKey\r\n",
+ "timeout" => 5
+ ]
+ ];
+
+ $context = stream_context_create($opts);
+ $json = @file_get_contents($base . '/api/settings', false, $context);
+
+
+ if ($json === false) {
+ error_log("API FAILED: " . $base . "/api/settings");
+ return '';
+ }
+
+ $data = json_decode($json, true);
+
+ return $data['appearance']['name'] ?? '';
+}
+
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+
+ // ALWAYS take values from the form first
+ $url = $_POST['url'] ?? '';
+ $apiKey = $_POST['apiKey'] ?? '';
+
+ // Fetch live name using the POSTed values
+ $printerName = getPrinterName($url, $apiKey);
+
+ // If editing and API failed → keep existing name
+ if ($id !== null && empty($printerName) && !empty($printers[$id]['printerName'])) {
+ $printerName = $printers[$id]['printerName'];
+ }
+
+ // If adding and API failed → stop
+ if ($id === null && empty($printerName)) {
+ die("Could not contact printer API.");
+ }
+
+ // Build data from POST (THIS IS CORRECT)
+ $data = [
+ 'printerName' => $printerName,
+ 'url' => $url,
+ 'apiKey' => $apiKey,
+ 'active' => isset($_POST['active'])
+ ];
+
+ // Save
+ if ($id !== null) {
+ $printers[$id] = $data;
+ } else {
+ $printers[] = $data;
+ }
+
+ file_put_contents($file, json_encode($printers, JSON_PRETTY_PRINT));
+
+ if (file_exists($cacheFile)) {
+ unlink($cacheFile);
+ }
+
+ header('Location: index.php');
+ exit;
+}
+?>
+
+
+
+
+
+
= $id !== null ? "Edit Printer" : "Add Printer" ?>
+
+
+
+
+
+
+
+
+
diff --git a/admin/index.php b/admin/index.php
new file mode 100644
index 0000000..5aee2bd
--- /dev/null
+++ b/admin/index.php
@@ -0,0 +1,162 @@
+ !empty($p['active'])));
+ } elseif ($group === 'inactive') {
+ $keys = array_keys(array_filter($printers, fn($p) => empty($p['active'])));
+ } else {
+ // fallback: whole list
+ $keys = array_keys($printers);
+ }
+
+ $pos = array_search($i, $keys, true);
+
+ if ($pos !== false) {
+
+ // move up within that group
+ if ($dir === 'up' && $pos > 0) {
+ $a = $keys[$pos];
+ $b = $keys[$pos - 1];
+ [$printers[$b], $printers[$a]] = [$printers[$a], $printers[$b]];
+ }
+
+ // move down within that group
+ if ($dir === 'down' && $pos < count($keys) - 1) {
+ $a = $keys[$pos];
+ $b = $keys[$pos + 1];
+ [$printers[$b], $printers[$a]] = [$printers[$a], $printers[$b]];
+ }
+
+ file_put_contents($file, json_encode($printers, JSON_PRETTY_PRINT));
+ if (file_exists($cacheFile)) {
+ unlink($cacheFile);
+ }
+ }
+
+ header("Location: index.php");
+ exit;
+}
+
+$active = [];
+$inactive = [];
+
+foreach ($printers as $index => $printer) {
+ if ($printer['active']) {
+ $active[$index] = $printer;
+ } else {
+ $inactive[$index] = $printer;
+ }
+}
+
+?>
+
+
+
+
+
+
Printer Admin
+
+
➕ Add Printer
+
+
Active Printers
+
+
+
+| Name |
+URL |
+Actions |
+
+
+ $p): ?>
+
+| = htmlspecialchars($p['printerName']) ?> |
+= htmlspecialchars($p['url']) ?> |
+
+Edit
+Delete
+
+
+
+
+
+
+ |
+
+
+
+
+
Inactive Printers
+
+
+
+| Name |
+URL |
+Actions |
+
+
+ $p): ?>
+
+| = htmlspecialchars($p['printerName']) ?> |
+= htmlspecialchars($p['url']) ?> |
+
+Edit
+Delete
+ |
+
+
+
+
+
+
+
+
+
diff --git a/admin/protect.php b/admin/protect.php
new file mode 100644
index 0000000..d0398d7
--- /dev/null
+++ b/admin/protect.php
@@ -0,0 +1,8 @@
+ false, 'message' => 'Missing URL or API key']);
+ exit;
+}
+
+/*
+ * Always normalize to base URL
+ * so it works whether user pastes:
+ * http://host
+ * http://host/
+ * http://host/api
+ */
+$base = preg_replace('#/api/?$#', '', rtrim($url, '/'));
+$endpoint = $base . '/api/settings'; // same source your main page uses
+
+$opts = [
+ "http" => [
+ "method" => "GET",
+ "header" => "X-Api-Key: $apiKey\r\n",
+ "timeout" => 5
+ ]
+];
+
+$context = stream_context_create($opts);
+$response = @file_get_contents($endpoint, false, $context);
+
+// error_log("DEBUG endpoint=" . $endpoint);
+// error_log("DEBUG response=" . $response);
+
+if ($response === false) {
+ echo json_encode(['success' => false, 'message' => 'Connection failed']);
+ exit;
+}
+
+$data = json_decode($response, true);
+
+if (!empty($data['appearance']['name'])) {
+ echo json_encode(['success' => true, 'name' => $data['appearance']['name']]);
+} else {
+ echo json_encode(['success' => false, 'message' => 'Invalid API response']);
+}
diff --git a/get_printer_data.php b/get_printer_data.php
index 0df36eb..80a8f7d 100644
--- a/get_printer_data.php
+++ b/get_printer_data.php
@@ -1,24 +1,6 @@
'printer1',
- 'url' => 'http://printer1.example.com/api/',
- 'apiKey' => 'apikey1',
- ),
-
- array(
- 'printerName' => 'printer2',
- 'url' => 'http://printer2.example.com/api/',
- 'apiKey' => 'apikey2',
- ),
- array(
- 'printerName' => 'printer3',
- 'url' => 'http://printer3.example.com/api/',
- 'apiKey' => 'apikey3',
- ),
-
-);
+$printers = json_decode(file_get_contents(__DIR__ . '/../private/printers.json'), true);
$cacheFile = '/tmp/printer_data_cache.json'; // Set the cache file path
@@ -40,12 +22,17 @@ function fetchPrinterData() {
// Loop through each printer
foreach ($printers as $printer) {
+ if (!($printer['active'] ?? true)) {
+ continue;
+ }
+
$printerName = $printer['printerName'];
$printerUrl = $printer['url'];
$printerApiKey = $printer['apiKey'];
// Make a request to get the current job information
- $urlJob = $printerUrl . 'job';
+ $apiBase = rtrim($printerUrl, '/') . '/api/';
+ $urlJob = $apiBase . 'job';
$chJob = curl_init();
curl_setopt($chJob, CURLOPT_URL, $urlJob);
curl_setopt($chJob, CURLOPT_RETURNTRANSFER, true);
@@ -54,7 +41,7 @@ function fetchPrinterData() {
curl_close($chJob);
// Make a request to get the server settings
- $urlSettings = $printerUrl . 'settings';
+ $urlSettings = $apiBase . 'settings';
$chSettings = curl_init();
curl_setopt($chSettings, CURLOPT_URL, $urlSettings);
curl_setopt($chSettings, CURLOPT_RETURNTRANSFER, true);
@@ -80,7 +67,7 @@ function fetchPrinterData() {
'progress' => '',
'elapsed' => '',
'left' => '',
- 'colorClass' => $colorClass,
+ 'colorClass' => $colorClass,
);
} else {
$printerData[] = array(
@@ -90,9 +77,11 @@ function fetchPrinterData() {
'elapsed' => (isset($job['progress']['printTime'])) ? formatTime($job['progress']['printTime']) : '',
'left' => (isset($job['progress']['printTimeLeft'])) ? formatTime($job['progress']['printTimeLeft']) : '',
'colorClass' => $colorClass,
+ 'active' => $printer['active'] ?? true
);
}
}
+ usort($printerData, fn($a, $b) => ($b['active'] ?? true) <=> ($a['active'] ?? true));
return $printerData;
}