Browse Source

Fix queue badge showing on printers without matching filament (#486)

The purple queue counter badge in the printer card header used the raw
unfiltered queue item count, so it appeared on ALL printers of the same
model when a job was scheduled for "any [model]" — even printers without
the matching filament color. The PrinterQueueWidget below it (which
shows "Clear Plate & Start") already filtered by filament type + color.

Apply the same filament compatibility filter (type check + color override
check) to the badge count so it only shows on printers that can actually
run the queued jobs.
maziggy 2 tháng trước cách đây
mục cha
commit
7eb7bf7

+ 1 - 0
CHANGELOG.md

@@ -13,6 +13,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **SpoolBuddy Kiosk Auth Bypass via API Key** — When Bambuddy auth is enabled, the SpoolBuddy kiosk (Chromium on RPi) was redirected to the login page because the `ProtectedRoute` requires a user object from `GET /auth/me`, which only accepted JWT tokens. The `/auth/me` endpoint now also accepts API keys (via `Authorization: Bearer bb_xxx` or `X-API-Key` header) and returns a synthetic admin user with all permissions. The frontend's `AuthContext` reads an optional `?token=` URL parameter on first load, stores it in localStorage, and strips it from the URL to prevent leakage via browser history or referrer. The install script now includes the API key in the kiosk URL (`/spoolbuddy?token=${API_KEY}`), so the device authenticates automatically on boot without manual login.
 
 ### Fixed
+- **Queue Badge Shows on Incompatible Printers** ([#486](https://github.com/maziggy/bambuddy/issues/486)) — The purple queue counter badge in the printer card header showed on all printers of the same model when a job was scheduled for "any [model]", even if the printer didn't have the matching filament color loaded. The `PrinterQueueWidget` (which shows "Clear Plate & Start") already filtered by filament type and color, but the badge count used the raw unfiltered queue length. Now applies the same filament compatibility filter to the badge count.
 - **SpoolBuddy Daemon Can't Find Hardware Drivers** — The daemon's `nfc_reader.py` and `scale_reader.py` import `read_tag` and `scale_diag` as bare modules, but these files live in `spoolbuddy/scripts/` which isn't on Python's module search path. The systemd service sets `WorkingDirectory` to `spoolbuddy/` and runs `python -m daemon.main`, so only the `spoolbuddy/` and `daemon/` directories are on `sys.path`. Added `scripts/` to `sys.path` at daemon startup, resolved relative to the module file so it works regardless of install path. Also moved the `read_tag` import inside `NFCReader.__init__`'s try/except block — it was previously outside, so a missing module crashed the entire daemon instead of gracefully skipping NFC polling. Demoted hardware-not-available log messages from ERROR to INFO since missing modules are expected when hardware isn't connected.
 
 ### Improved

+ 21 - 1
frontend/src/pages/PrintersPage.tsx

@@ -1672,7 +1672,27 @@ function PrinterCard({
     queryKey: ['queue', printer.id, 'pending'],
     queryFn: () => api.getQueue(printer.id, 'pending'),
   });
-  const queueCount = queueItems?.length || 0;
+  // Filter queue items by filament compatibility (same logic as PrinterQueueWidget)
+  // so the badge only shows on printers that can actually run the queued jobs.
+  const queueCount = useMemo(() => {
+    if (!queueItems?.length) return 0;
+    return queueItems.filter(item => {
+      if (item.required_filament_types?.length && loadedFilamentTypes?.size) {
+        if (!item.required_filament_types.every((t: string) => loadedFilamentTypes.has(t.toUpperCase()))) {
+          return false;
+        }
+      }
+      if (item.filament_overrides?.length && loadedFilaments?.size) {
+        const hasColorMatch = item.filament_overrides.some((o: { type?: string; color?: string }) => {
+          const oType = (o.type || '').toUpperCase();
+          const oColor = (o.color || '').replace('#', '').toLowerCase().slice(0, 6);
+          return loadedFilaments.has(`${oType}:${oColor}`);
+        });
+        if (!hasColorMatch) return false;
+      }
+      return true;
+    }).length;
+  }, [queueItems, loadedFilamentTypes, loadedFilaments]);
 
   // Fetch currently printing queue item to show who started it (Issue #206)
   const { data: printingQueueItems } = useQuery({

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
static/assets/index-BKdrvUCu.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
static/assets/index-CS9we2y6.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 1
static/assets/index-CxFtC4Kb.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
static/assets/index-DJjXosw8.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
static/assets/index-OUDlnhQe.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
static/assets/index-tKUolDFn.js


+ 2 - 2
static/index.html

@@ -23,8 +23,8 @@
 
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-CS9we2y6.js"></script>
-    <link rel="stylesheet" crossorigin href="/assets/index-OUDlnhQe.css">
+    <script type="module" crossorigin src="/assets/index-tKUolDFn.js"></script>
+    <link rel="stylesheet" crossorigin href="/assets/index-BKdrvUCu.css">
   </head>
   <body>
     <div id="root"></div>

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác