Bladeren bron

Read a renamed printer profile's model from its parent in the Slice dialog's online filter (#3172)

maziggy 3 dagen geleden
bovenliggende
commit
8a95eb9f7a
58 gewijzigde bestanden met toevoegingen van 58 en 22 verwijderingen
  1. 1 0
      CHANGELOG.md
  2. 20 0
      frontend/src/__tests__/utils/sliceLoadedSpools.test.ts
  3. 15 15
      frontend/src/components/SliceModal.tsx
  4. 19 2
      frontend/src/utils/sliceLoadedSpools.ts
  5. 0 0
      static/assets/AdditionalSection-CvIljGzG.js
  6. 0 0
      static/assets/AmsUnitCard-lzCbny5Q.js
  7. 0 0
      static/assets/ArchivesPage-CbKyfKjY.js
  8. 0 0
      static/assets/AssignToAmsModal-DVH0AGlC.js
  9. 0 0
      static/assets/CamWallPage-R5ywDSqy.js
  10. 0 0
      static/assets/CameraDiagnoseModal-DhqNPWqk.js
  11. 0 0
      static/assets/CameraPage-DNl3rhP3.js
  12. 0 0
      static/assets/CameraWall-BIdBKLRO.js
  13. 0 0
      static/assets/ColumnConfigModal-C66OrmbM.js
  14. 0 0
      static/assets/ConfigureAmsSlotModal-Cm4jIDNp.js
  15. 0 0
      static/assets/ConnectAuthorizePage-D624UV9Y.js
  16. 0 0
      static/assets/ContextMenu-DYUurM4Z.js
  17. 0 0
      static/assets/ExternalLinkPage-BxcCiE2o.js
  18. 0 1
      static/assets/FileManagerPage-_jIsA-Rt.js
  19. 0 0
      static/assets/FileUploadModal-C_-XkYZx.js
  20. 0 0
      static/assets/FinancePage-9YfWxI56.js
  21. 0 0
      static/assets/GCodeViewerPage-ClSDq6tw.js
  22. 0 0
      static/assets/GroupEditPage-CbcW-d5G.js
  23. 0 0
      static/assets/ImagePreviewModal-IbQRegjP.js
  24. 0 0
      static/assets/InventoryPage-LSqoic6w.js
  25. 0 0
      static/assets/LibraryTrashPage-BPIFqvPv.js
  26. 0 0
      static/assets/LoginPage-BDEd0_e6.js
  27. 0 0
      static/assets/MaintenancePage-C9GUBj6p.js
  28. 0 0
      static/assets/ModelSourcesPage-BrRENkCt.js
  29. 0 0
      static/assets/NotificationsPage-CYcn2S6P.js
  30. 0 1
      static/assets/PdfPreviewModal-DkhqhYrR.js
  31. 0 0
      static/assets/PhotoGalleryModal-Mn6ZL95X.js
  32. 0 0
      static/assets/PrinterLocationsPage-DG0X9nRX.js
  33. 0 0
      static/assets/PrintersPage-Detk2T2C.js
  34. 0 0
      static/assets/ProfilesPage-DZd3sCEa.js
  35. 0 0
      static/assets/ProjectDetailPage-Cmrd1p6c.js
  36. 0 0
      static/assets/ProjectsPage-BPTB0Pu2.js
  37. 0 0
      static/assets/QueuePage-B1qiE47g.js
  38. 0 0
      static/assets/RichTextEditor-BKKwfI5N.js
  39. 0 0
      static/assets/SettingsPage-atVlb8rl.js
  40. 0 0
      static/assets/SetupPage-CLkw_QQi.js
  41. 0 0
      static/assets/SliceModal-C00u-1ny.js
  42. 0 0
      static/assets/SliceModal-CJS4-5j8.js
  43. 0 0
      static/assets/SpoolBuddyAmsPage-WldaC1Bb.js
  44. 0 0
      static/assets/SpoolBuddyCalibrationPage-CHqr65fI.js
  45. 0 0
      static/assets/SpoolBuddyDashboard-AqPmHZr8.js
  46. 0 0
      static/assets/SpoolBuddyInventoryPage-B7-kNZOy.js
  47. 1 1
      static/assets/SpoolBuddySettingsPage-SN3GWbiA.js
  48. 0 0
      static/assets/SpoolBuddyWriteTagPage-B-OH-kjp.js
  49. 0 0
      static/assets/SpreadsheetPreviewModal-BdFAvinO.js
  50. 0 0
      static/assets/StatsPage-B61EFYKE.js
  51. 0 0
      static/assets/StreamOverlayPage-iDp20gBw.js
  52. 0 0
      static/assets/SystemInfoPage-C1fAljbz.js
  53. 0 0
      static/assets/index-C-0w3pwY.js
  54. 1 1
      static/assets/inventorySearch-Ch1PI4QC.js
  55. 0 0
      static/assets/locationSensorDefaults-WfOsrPZS.js
  56. 0 0
      static/assets/pdf-rfBQ5QKU.js
  57. 0 0
      static/assets/utils-ui-YAEyJ.js
  58. 1 1
      static/index.html

+ 1 - 0
CHANGELOG.md

@@ -149,6 +149,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **The frontend build no longer warns about `path` and `crypto` being externalized for the STEP previewer (#2976)** — `occt-import-js`, the Emscripten build behind STEP previews, requires both modules, but only inside its `ENVIRONMENT_IS_NODE` branches; in the browser it loads its `.wasm` from the URL the preview worker passes and draws randomness from `crypto.getRandomValues`. Vite still externalized both and printed two warnings on every build. `vite.config.ts` now drops exactly those two warnings for that one package through `build.rolldownOptions.onLog`, so an externalization anywhere else, or of any other module, still shows.
 
 ### Fixed
+- **Slice dialog hid renamed printer profiles while "Only printers that are online" was on (#3172, reported by @gregspatrick)** — The filter read the printer model from the profile's name, so a copy saved as `Bambu Lab P1S 0.4 nozzle - Copy` read as an unknown model and was hidden even with a P1S online, until **Show all** was picked. It now reads the model from the profile the copy was saved from, as the loaded-spools filter already did.
 - **Printer cards never showed the last print, nor the Good / Reject prompt for it** — Each card asked for its printer's archives with the arguments in the wrong order, so it requested none and always got an empty list. The **Last:** line on an idle card and the outcome prompt from #1898 never appeared there.
   - **One request for every card:** the cards now share a single request that returns the archive each printer printed last (a reprint of an older archive counts), instead of one per card. On a farm with 59 printers that was 59 requests on every page load and after every finished print, each scanning the whole archive table for duplicates.
 - **The File Manager and Archives page loaded every thumbnail at once** — With a few hundred files every thumbnail was requested on page load, and the queue of requests slowed down everything else on the server for several seconds. Thumbnails now load as they scroll into view.

+ 20 - 0
frontend/src/__tests__/utils/sliceLoadedSpools.test.ts

@@ -9,6 +9,7 @@ import {
   isConnectedModelPreset,
   matchSlotPreset,
   matchedFilamentRefs,
+  pickConnectedPrinterPreset,
   presetBaseName,
   printerPresetModel,
   printersOfModel,
@@ -92,6 +93,25 @@ describe('isConnectedModelPreset', () => {
   it('understands the short A1 Mini code', () => {
     expect(isConnectedModelPreset({ name: 'Bambu Lab A1 mini 0.4 nozzle' }, ['A1M'], MODELS)).toBe(true);
   });
+
+  it('reads a renamed copy by the profile it was saved from', () => {
+    const copy = { name: 'Bambu Lab H2D 0.4 nozzle - Copy' };
+    const parents = { [copy.name]: H2D };
+    expect(isConnectedModelPreset(copy, ['H2D'], MODELS, parents)).toBe(true);
+    expect(isConnectedModelPreset(copy, ['X1C'], MODELS, parents)).toBe(false);
+  });
+});
+
+describe('pickConnectedPrinterPreset', () => {
+  it('can pick a renamed copy of an online model', () => {
+    const copy = { id: 'copy-1', name: 'Bambu Lab H2D 0.4 nozzle - Copy', source: 'local' as const };
+    const data = presets({ local: { printer: [copy], process: [], filament: [] } });
+    expect(pickConnectedPrinterPreset(data, ['H2D'], MODELS)).toBeNull();
+    expect(pickConnectedPrinterPreset(data, ['H2D'], MODELS, { [copy.name]: H2D })).toEqual({
+      source: 'local',
+      id: 'copy-1',
+    });
+  });
 });
 
 describe('presetBaseName', () => {

+ 15 - 15
frontend/src/components/SliceModal.tsx

@@ -42,7 +42,7 @@ import {
   isConnectedModelPreset,
   matchedFilamentRefs,
   pickConnectedPrinterPreset,
-  printerPresetModel,
+  printerProfileModel,
   printersOfModel,
 } from '../utils/sliceLoadedSpools';
 
@@ -523,16 +523,7 @@ export function SliceModal({ source, onClose, defaultAutoArrange = false }: Slic
   // AMS says nothing about what an X1C job can start on. A profile whose
   // model can't be read keeps every connected printer.
   const spoolPrinters = useMemo(
-    // The parent names the model reliably; the user's own name may not.
-    () => printersOfModel(
-      loadedPrinters,
-      printerPresetModel(
-        (selectedPrinterName && Object.hasOwn(printerParents, selectedPrinterName)
-          ? printerParents[selectedPrinterName]
-          : null) || selectedPrinterName,
-        printerModels,
-      ),
-    ),
+    () => printersOfModel(loadedPrinters, printerProfileModel(selectedPrinterName, printerModels, printerParents)),
     [loadedPrinters, selectedPrinterName, printerModels, printerParents],
   );
   const filamentNameIndex = useMemo(
@@ -551,8 +542,8 @@ export function SliceModal({ source, onClose, defaultAutoArrange = false }: Slic
   const printerFilter = useMemo(() => {
     if (!onlyConnectedModels || loadedPrinters.length === 0) return null;
     const models = loadedPrinters.map((p) => p.model);
-    return (p: UnifiedPreset) => isConnectedModelPreset(p, models, printerModels);
-  }, [onlyConnectedModels, loadedPrinters, printerModels]);
+    return (p: UnifiedPreset) => isConnectedModelPreset(p, models, printerModels, printerParents);
+  }, [onlyConnectedModels, loadedPrinters, printerModels, printerParents]);
   const filamentFilter = useMemo(() => {
     if (!onlyLoadedSpools || loadedFilamentRefs.size === 0) return null;
     return (p: UnifiedPreset) => loadedFilamentRefs.has(`${p.source}:${p.id}`);
@@ -692,9 +683,18 @@ export function SliceModal({ source, onClose, defaultAutoArrange = false }: Slic
     const embeddedPreset = findPreset(data, embedded, 'printer');
     const next = embeddedPreset && printerFilter(embeddedPreset)
       ? embedded
-      : pickConnectedPrinterPreset(data, loadedPrinters.map((p) => p.model), printerModels);
+      : pickConnectedPrinterPreset(data, loadedPrinters.map((p) => p.model), printerModels, printerParents);
     if (next) setPrinterPreset(next);
-  }, [presetsQuery.data, printerFilter, printerPreset, embeddedPrinter, loadedPrinters, printerModels, useEmbedded]);
+  }, [
+    presetsQuery.data,
+    printerFilter,
+    printerPreset,
+    embeddedPrinter,
+    loadedPrinters,
+    printerModels,
+    printerParents,
+    useEmbedded,
+  ]);
 
   // Process pre-pick / re-pick (#1325): defaults to a process compatible with
   // the selected printer, and re-defaults when a printer change leaves the

+ 19 - 2
frontend/src/utils/sliceLoadedSpools.ts

@@ -77,13 +77,29 @@ export function printersOfModel(
   return printers.filter((p) => sameModel(p.model, model));
 }
 
+/**
+ * The model of a printer profile, read from the profile it was saved from
+ * when there is one: the parent names the model reliably, the user's own name
+ * ("Bambu Lab P1S 0.4 nozzle - Copy") may not (#3250, #3172).
+ */
+export function printerProfileModel(
+  name: string | null | undefined,
+  printerModels: Record<string, string>,
+  printerParents: Record<string, string> = {},
+): string | null {
+  if (!name) return null;
+  const parent = Object.hasOwn(printerParents, name) ? printerParents[name] : null;
+  return printerPresetModel(parent || name, printerModels);
+}
+
 /** Whether a printer profile belongs to a connected model, or can't be told. */
 export function isConnectedModelPreset(
   preset: Pick<UnifiedPreset, 'name'>,
   connectedModels: (string | null)[],
   printerModels: Record<string, string>,
+  printerParents: Record<string, string> = {},
 ): boolean {
-  const model = printerPresetModel(preset.name, printerModels);
+  const model = printerProfileModel(preset.name, printerModels, printerParents);
   if (model === null) return true;
   return connectedModels.some((c) => sameModel(c, model));
 }
@@ -97,11 +113,12 @@ export function pickConnectedPrinterPreset(
   data: UnifiedPresetsResponse,
   connectedModels: (string | null)[],
   printerModels: Record<string, string>,
+  printerParents: Record<string, string> = {},
 ): PresetRef | null {
   let fallback: PresetRef | null = null;
   for (const source of SLICE_MODAL_TIER_ORDER) {
     for (const preset of data[source].printer) {
-      const model = printerPresetModel(preset.name, printerModels);
+      const model = printerProfileModel(preset.name, printerModels, printerParents);
       if (model === null || !connectedModels.some((c) => sameModel(c, model))) continue;
       const ref = { source, id: preset.id };
       if (/\b0\.4\s*nozzle\b/i.test(preset.name)) return ref;

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


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


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


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


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


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


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


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


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


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


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


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


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


File diff suppressed because it is too large
+ 0 - 1
static/assets/FileManagerPage-_jIsA-Rt.js


File diff suppressed because it is too large
+ 0 - 0
static/assets/FileUploadModal-C_-XkYZx.js


File diff suppressed because it is too large
+ 0 - 0
static/assets/FinancePage-9YfWxI56.js


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


File diff suppressed because it is too large
+ 0 - 0
static/assets/GroupEditPage-CbcW-d5G.js


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


File diff suppressed because it is too large
+ 0 - 0
static/assets/SliceModal-C00u-1ny.js


File diff suppressed because it is too large
+ 0 - 0
static/assets/SliceModal-CJS4-5j8.js


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


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


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


File diff suppressed because it is too large
+ 0 - 0
static/assets/SpoolBuddyInventoryPage-B7-kNZOy.js


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


File diff suppressed because it is too large
+ 0 - 0
static/assets/SpoolBuddyWriteTagPage-B-OH-kjp.js


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


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


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


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


File diff suppressed because it is too large
+ 0 - 0
static/assets/index-C-0w3pwY.js


+ 1 - 1
static/assets/inventorySearch-yLBksvSK.js → static/assets/inventorySearch-Ch1PI4QC.js

@@ -1 +1 @@
-import{ft as e}from"./index-FgwaUb6h.js";function t(t,n){let r=n.trim().toLowerCase();if(!r)return!0;let i=r.match(/^#(\d+)$/);return i?t.id===Number(i[1]):String(t.id).includes(r)||t.material.toLowerCase().includes(r)||(t.brand?.toLowerCase().includes(r)??!1)||(t.color_name?.toLowerCase().includes(r)??!1)||(e(t.color_name,t.rgba,t.color_name_is_synthesized)?.toLowerCase().includes(r)??!1)||(t.subtype?.toLowerCase().includes(r)??!1)||(t.note?.toLowerCase().includes(r)??!1)||(t.slicer_filament_name?.toLowerCase().includes(r)??!1)||(t.storage_location?.toLowerCase().includes(r)??!1)||(t.material_number?.toLowerCase().includes(r)??!1)||(t.suppliers?.some(e=>e.supplier_name.toLowerCase().includes(r)||(e.supplier_article_number?.toLowerCase().includes(r)??!1))??!1)}function n(e,n){return n?e.filter(e=>t(e,n)):e}export{n as t};
+import{ft as e}from"./index-C-0w3pwY.js";function t(t,n){let r=n.trim().toLowerCase();if(!r)return!0;let i=r.match(/^#(\d+)$/);return i?t.id===Number(i[1]):String(t.id).includes(r)||t.material.toLowerCase().includes(r)||(t.brand?.toLowerCase().includes(r)??!1)||(t.color_name?.toLowerCase().includes(r)??!1)||(e(t.color_name,t.rgba,t.color_name_is_synthesized)?.toLowerCase().includes(r)??!1)||(t.subtype?.toLowerCase().includes(r)??!1)||(t.note?.toLowerCase().includes(r)??!1)||(t.slicer_filament_name?.toLowerCase().includes(r)??!1)||(t.storage_location?.toLowerCase().includes(r)??!1)||(t.material_number?.toLowerCase().includes(r)??!1)||(t.suppliers?.some(e=>e.supplier_name.toLowerCase().includes(r)||(e.supplier_article_number?.toLowerCase().includes(r)??!1))??!1)}function n(e,n){return n?e.filter(e=>t(e,n)):e}export{n as t};

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


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


File diff suppressed because it is too large
+ 0 - 0
static/assets/utils-ui-YAEyJ.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-FgwaUb6h.js"></script>
+    <script type="module" crossorigin src="/assets/index-C-0w3pwY.js"></script>
     <link rel="modulepreload" crossorigin href="/assets/chunk-aKtaBQYM.js">
     <link rel="modulepreload" crossorigin href="/assets/client-D0Q3EIO2.js">
     <link rel="modulepreload" crossorigin href="/assets/QueryClientProvider-CsMjD-7g.js">

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