Browse Source

Add a back link to the Printer Locations page

The page is opened from the Printers page and is not in the sidebar, so
the browser's back button was the only way out. Add a "Back to Printers"
link above the title, translated in all locales.
maziggy 1 day ago
parent
commit
4feea94912

+ 1 - 0
CHANGELOG.md

@@ -268,6 +268,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **Closing the bug-report panel no longer throws the capture away and leaves the logs running (#2847)** — Step 2 of the report flow asks you to reproduce the problem, and the panel sits over the part of the app you have to reach to do it. Closing it was the obvious move and it was the wrong one twice over. Reopening put you back on an empty step 1 — while the server was still logging at DEBUG, with nothing left in the flow that could stop it, because only **Stop & Submit** ever did. Leave it closed instead and the five-minute cap eventually fired behind your back: logging stopped and the report was filed with no window open and no confirmation that it had happened. Which of the two you got depended only on whether you reopened the panel inside five minutes. A capture is now a thing that outlives the panel. Closing keeps it running and says so — the bug button turns amber for as long as a capture is going, and clicking it returns you to step 2 with your description, your screenshot and the elapsed timer where you left them. If the cap does fire while the panel is closed, the panel reopens so the submission happens in front of you rather than behind you. The timer is measured against the capture's start time rather than counted in ticks, so a background tab, where browsers throttle timers hard, no longer stretches five minutes into something else. A capture also survives a page reload, which matters because reloading is a perfectly ordinary step in reproducing a bug: the report picks it back up where it was. One that outlived the cap while nobody was watching is not resumed and not filed — a description written an hour ago is not a report you are still expecting — but the log level is put back, which is the part that previously stayed wrong indefinitely. Translated in all locales; wiki updated. Covered by frontend tests.
 - **The File Manager's card menu no longer loses its top entry (#2846)** — In grid view a file card's action menu was drawn inside the card, and the card clipped anything its children painted outside it. A card is as tall as its square thumbnail plus whatever metadata the file has, so an STL — which has none beyond a name and a size — produced the shortest card in the library, about 270px against a seven-entry menu that needs closer to 310px. The difference was one row, and the row it took was the top one: **Slice**, since **Print** is only offered for a file that is already sliced. A 3MF carries a target model and a print count, two more rows, and its card was tall enough, which is why the button appeared there and looked like a file-type rule rather than a layout accident. Nothing about STL was special; the shortest card simply lost the first item, whichever it happened to be. The menu now opens against the viewport, the way the archive card's menu already did, so no card can crop it, and the card no longer clips its own children. List view was never affected — it has no menu, only inline buttons. Covered by a frontend test.
 - **A printer fault that kept coming and going was notified every time it came back (#3226, reported by @sgiffhorn)** — Bambuddy remembered which faults it had already notified as one list per printer, replaced on every status update, so a fault was forgotten the moment one update arrived without it. A 30-second grace period was meant to cover that, but only applied when the printer reported no faults at all, which never happens while it holds a notice such as the lubrication reminder. An H2D whose nozzle camera lens fault switched on and off beside two lubrication notices sent the same notification 9 times in 22 minutes. Each fault is now remembered on its own and notified again only after it has been gone for 10 minutes. So that a fault you fixed is still reported if it happens again soon, a fault seen before the print is resumed, started or finished is forgotten as soon as it is gone, without the wait; a filament runout fixed before resuming is notified again if it recurs a few minutes later. Covered by unit tests.
+- **The Printer Locations page had no way back to the Printers page** — the page is opened from the Printers page and is not in the sidebar, so the browser's back button was the only way out. It now has a "Back to Printers" link above the title.
 
 ### Security
 - **Bumped `PyJWT` to 2.15.1 and `urllib3` to 2.8.0** — PyJWT 2.14 and 2.15 fix thirteen advisories, most of them algorithm confusion when one `decode()` call accepts both an HMAC and an asymmetric algorithm, and JWKS fetching through `PyJWKClient`. Bambuddy's session tokens accept only HS256, and SSO fetches the identity provider's key set itself before handing it to PyJWT, so neither path was open to these. The fixes for deeply nested or malformed tokens, and for JWK Sets with one bad key (which now skip that key instead of failing the whole set), do reach the SSO sign-in. urllib3 2.8.0 fixes three advisories in response streaming and HTTPS-proxy TLS; Bambuddy doesn't use urllib3 itself, it arrives through other packages. `virtualenv`, which only the development tools pull in, is pinned to 21.7.13 or later so `pip-audit` stays clean.

+ 7 - 0
frontend/src/__tests__/pages/PrinterLocationsPage.test.tsx

@@ -177,6 +177,13 @@ describe('PrinterLocationsPage', () => {
     expect(screen.queryByRole('button', { name: /edit/i })).not.toBeInTheDocument();
     expect(screen.queryByRole('button', { name: /select all/i })).not.toBeInTheDocument();
   });
+
+  it('links back to the printers page', async () => {
+    render(<PrinterLocationsPage />);
+
+    const back = await screen.findByRole('link', { name: /back to printers/i });
+    expect(back).toHaveAttribute('href', '/');
+  });
 });
 
 describe('printer locations strings', () => {

+ 1 - 0
frontend/src/i18n/locales/de.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: 'Druckerstandorte',
+      backToPrinters: 'Zurück zu den Druckern',
       subtitle: '{{grouped}} mit Standort, {{ungrouped}} ohne',
       search: 'Standorte durchsuchen...',
       showEmpty: 'Leere anzeigen',

+ 1 - 0
frontend/src/i18n/locales/en.ts

@@ -241,6 +241,7 @@ export default {
     // they read correctly in every language without plural forms.
     locations: {
       title: 'Printer Locations',
+      backToPrinters: 'Back to Printers',
       subtitle: '{{grouped}} in a location, {{ungrouped}} without one',
       search: 'Search locations...',
       showEmpty: 'Show empty',

+ 1 - 0
frontend/src/i18n/locales/es.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: 'Ubicaciones de impresoras',
+      backToPrinters: 'Volver a las impresoras',
       subtitle: '{{grouped}} con ubicación, {{ungrouped}} sin ubicación',
       search: 'Buscar ubicaciones...',
       showEmpty: 'Mostrar vacías',

+ 1 - 0
frontend/src/i18n/locales/fr.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: 'Emplacements des imprimantes',
+      backToPrinters: 'Retour aux imprimantes',
       subtitle: '{{grouped}} avec emplacement, {{ungrouped}} sans',
       search: 'Rechercher des emplacements...',
       showEmpty: 'Afficher les vides',

+ 1 - 0
frontend/src/i18n/locales/it.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: 'Posizioni delle stampanti',
+      backToPrinters: 'Torna alle stampanti',
       subtitle: '{{grouped}} con posizione, {{ungrouped}} senza',
       search: 'Cerca posizioni...',
       showEmpty: 'Mostra vuote',

+ 1 - 0
frontend/src/i18n/locales/ja.ts

@@ -238,6 +238,7 @@ export default {
   printers: {
     locations: {
       title: 'プリンターの場所',
+      backToPrinters: 'プリンターに戻る',
       subtitle: '場所あり {{grouped}} 台、場所なし {{ungrouped}} 台',
       search: '場所を検索...',
       showEmpty: '空の場所を表示',

+ 1 - 0
frontend/src/i18n/locales/ko.ts

@@ -233,6 +233,7 @@ export default {
   printers: {
     locations: {
       title: '프린터 위치',
+      backToPrinters: '프린터로 돌아가기',
       subtitle: '위치 있음 {{grouped}}대, 위치 없음 {{ungrouped}}대',
       search: '위치 검색...',
       showEmpty: '빈 위치 표시',

+ 1 - 0
frontend/src/i18n/locales/nl.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: 'Printerlocaties',
+      backToPrinters: 'Terug naar printers',
       subtitle: '{{grouped}} met locatie, {{ungrouped}} zonder',
       search: 'Locaties zoeken...',
       showEmpty: 'Lege tonen',

+ 1 - 0
frontend/src/i18n/locales/pt-BR.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: 'Locais das impressoras',
+      backToPrinters: 'Voltar para as impressoras',
       subtitle: '{{grouped}} com local, {{ungrouped}} sem local',
       search: 'Buscar locais...',
       showEmpty: 'Mostrar vazios',

+ 1 - 0
frontend/src/i18n/locales/ru.ts

@@ -233,6 +233,7 @@ export default {
   printers: {
     locations: {
       title: "Расположение принтеров",
+      backToPrinters: "Назад к принтерам",
       subtitle: "С расположением: {{grouped}}, без расположения: {{ungrouped}}",
       search: "Поиск расположений...",
       showEmpty: "Показать пустые",

+ 1 - 0
frontend/src/i18n/locales/sv.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: 'Skrivarplatser',
+      backToPrinters: 'Tillbaka till skrivare',
       subtitle: '{{grouped}} med plats, {{ungrouped}} utan',
       search: 'Sök platser...',
       showEmpty: 'Visa tomma',

+ 1 - 0
frontend/src/i18n/locales/tr.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: 'Yazıcı konumları',
+      backToPrinters: 'Yazıcılara dön',
       subtitle: '{{grouped}} konumlu, {{ungrouped}} konumsuz',
       search: 'Konum ara...',
       showEmpty: 'Boşları göster',

+ 1 - 0
frontend/src/i18n/locales/uk.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: "Розташування принтерів",
+      backToPrinters: "Назад до принтерів",
       subtitle: "З розташуванням: {{grouped}}, без розташування: {{ungrouped}}",
       search: "Пошук розташувань...",
       showEmpty: "Показати порожні",

+ 1 - 0
frontend/src/i18n/locales/zh-CN.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: '打印机位置',
+      backToPrinters: '返回打印机',
       subtitle: '有位置 {{grouped}} 台,无位置 {{ungrouped}} 台',
       search: '搜索位置...',
       showEmpty: '显示空位置',

+ 1 - 0
frontend/src/i18n/locales/zh-TW.ts

@@ -239,6 +239,7 @@ export default {
   printers: {
     locations: {
       title: '印表機位置',
+      backToPrinters: '返回印表機',
       subtitle: '有位置 {{grouped}} 台,無位置 {{ungrouped}} 台',
       search: '搜尋位置...',
       showEmpty: '顯示空位置',

+ 8 - 1
frontend/src/pages/PrinterLocationsPage.tsx

@@ -1,7 +1,8 @@
 import { useEffect, useMemo, useState } from 'react';
 import { useMutation, useQueries, useQuery, useQueryClient } from '@tanstack/react-query';
 import { useTranslation } from 'react-i18next';
-import { Box, CheckSquare, ChevronDown, Loader2, Move, Pencil, Plus, Search, Square, Trash2, UserMinus, X } from 'lucide-react';
+import { Link } from 'react-router-dom';
+import { ArrowLeft, Box, CheckSquare, ChevronDown, Loader2, Move, Pencil, Plus, Search, Square, Trash2, UserMinus, X } from 'lucide-react';
 import { api } from '../api/client';
 import type { Printer, PrinterLocation } from '../api/client';
 import { Button } from '../components/Button';
@@ -471,6 +472,12 @@ export function PrinterLocationsPage() {
 
   return (
     <div className="p-4 md:p-8 pb-28">
+      <Link
+        to="/"
+        className="inline-flex items-center gap-1 mb-3 text-sm text-bambu-gray hover:text-white transition-colors"
+      >
+        <ArrowLeft className="w-4 h-4" /> {t('printers.locations.backToPrinters')}
+      </Link>
       <div className="mb-4">
         <div className="flex items-center gap-3 mb-1">
           <Box className="w-[25px] h-[25px] text-bambu-green" />

File diff suppressed because it is too large
+ 0 - 0
static/assets/ImagePreviewModal-B_nL3_8y.js


File diff suppressed because it is too large
+ 0 - 1
static/assets/PdfPreviewModal-DFgmChOn.js


File diff suppressed because it is too large
+ 0 - 0
static/assets/SpreadsheetPreviewModal-BZBKSNz6.js


File diff suppressed because it is too large
+ 1 - 1
static/assets/index-BljpHSYg.js


File diff suppressed because it is too large
+ 0 - 0
static/assets/pdf-KdLife5c.js


+ 1 - 1
static/index.html

@@ -26,7 +26,7 @@
 
     <!-- Splash screens for iOS -->
     <link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
-    <script type="module" crossorigin src="/assets/index-CFtTE_hL.js"></script>
+    <script type="module" crossorigin src="/assets/index-BljpHSYg.js"></script>
     <link rel="modulepreload" crossorigin href="/assets/chunk-aKtaBQYM.js">
     <link rel="stylesheet" crossorigin href="/assets/index-CaVfzyDI.css">
   </head>

Some files were not shown because too many files changed in this diff