From 3cd9200d87e36b737a272cc41d76b49d56441723 Mon Sep 17 00:00:00 2001 From: jedi Date: Wed, 2 Sep 2026 21:30:37 +0200 Subject: [PATCH 01/10] stash --- docs/implementation.md | 3 +++ frontend/src/workflows.js | 2 ++ 2 files changed, 5 insertions(+) diff --git a/docs/implementation.md b/docs/implementation.md index 04adb81..f6c6f9c 100644 --- a/docs/implementation.md +++ b/docs/implementation.md @@ -229,6 +229,9 @@ In `FotoFirstBulkImportWorkflow.vue`, `photos`' durable state is the `WorkflowIn Once a photo finishes uploading, the gallery switches it to the server-fetched thumbnail by re-looking it up by hash rather than mutating the closed-over `photo` object from the upload closure - that reference predates the `this.photos.push()` call, so it's the raw object, not the reactive proxy Vue tracks, and writing to it wouldn't trigger a re-render. +### Bulk Label Print Workflow +`BulkLabelPrintWorkflow.vue` implements the `bulk-label-print` workflow: step 1 collects a kind/owner/id range plus a label layout (reusing `LabelLayoutPreview.vue` for the template grid, previewed against the range's first id); step 2 connects a printer (or falls back to PNG downloads, same device-chip/PNG-Export pattern as `Print.vue`) and, on start, sequentially renders and prints/downloads one label per id in the range via `label.js`'s `drawLabel`, logging each id's outcome. `MAX_RANGE_SIZE` caps a single run so a mistyped range can't queue an unbounded number of labels. + ### Foto First Bulk Import Workflow `FotoFirstBulkImportWorkflow2.vue` implements every step of the `foto-first-bulk-import` workflow (photo capture, image processing, item detail entry, import completion) in a single component. Keeping the whole workflow in one file avoids splitting closely related state (photos, processed images, completed items) across many small step components and their prop/emit boundaries. diff --git a/frontend/src/workflows.js b/frontend/src/workflows.js index 0d392f8..f772d11 100644 --- a/frontend/src/workflows.js +++ b/frontend/src/workflows.js @@ -6,6 +6,7 @@ import StorageOptimizationWorkflow from '@/components/workflow/workflows/Storage import MaintenanceScheduleWorkflow from '@/components/workflow/workflows/MaintenanceScheduleWorkflow.vue'; import ExpiryCheckWorkflow from '@/components/workflow/workflows/ExpiryCheckWorkflow.vue'; import BackupRestoreWorkflow from '@/components/workflow/workflows/BackupRestoreWorkflow.vue'; +import BulkLabelPrintWorkflow from '@/components/workflow/workflows/BulkLabelPrintWorkflow.vue'; const workflows = [ {...FotoFirstBulkImportWorkflow.meta, component: FotoFirstBulkImportWorkflow}, @@ -15,6 +16,7 @@ const workflows = [ {...MaintenanceScheduleWorkflow.meta, component: MaintenanceScheduleWorkflow}, {...ExpiryCheckWorkflow.meta, component: ExpiryCheckWorkflow}, {...BackupRestoreWorkflow.meta, component: BackupRestoreWorkflow}, + {...BulkLabelPrintWorkflow.meta, component: BulkLabelPrintWorkflow}, ]; export function getAllWorkflows() { From e88dc898b3c9c30099d56bdb0efe74ad3bee5a30 Mon Sep 17 00:00:00 2001 From: jedi Date: Fri, 4 Sep 2026 14:41:26 +0200 Subject: [PATCH 02/10] stash --- frontend/src/components/BaseLayout.vue | 2 +- frontend/src/components/Sidebar.vue | 22 +- frontend/src/components/UserDropdown.vue | 4 +- frontend/src/router.js | 67 ++++-- frontend/src/views/Dashboard.vue | 203 ++++++++++++++++++- frontend/src/views/Groups.vue | 4 +- frontend/src/views/Inventory.vue | 22 +- frontend/src/views/InventoryDetail.vue | 4 +- frontend/src/views/Login.vue | 4 +- frontend/src/views/Pairing.vue | 4 +- frontend/src/views/Register.vue | 4 +- frontend/src/views/Scan.vue | 4 +- frontend/src/views/Search.vue | 2 +- frontend/src/views/StorageLocation.vue | 24 ++- frontend/src/views/StorageLocationDetail.vue | 4 +- frontend/src/views/StorageLocationNew.vue | 2 +- frontend/src/views/WorkflowDetail.vue | 2 +- frontend/src/workflows.js | 4 +- 18 files changed, 298 insertions(+), 84 deletions(-) diff --git a/frontend/src/components/BaseLayout.vue b/frontend/src/components/BaseLayout.vue index 3ffe9a7..17b5ad0 100644 --- a/frontend/src/components/BaseLayout.vue +++ b/frontend/src/components/BaseLayout.vue @@ -9,7 +9,7 @@
- @@ -51,7 +51,7 @@ Delete diff --git a/frontend/src/views/Login.vue b/frontend/src/views/Login.vue index 31bd515..b53830c 100644 --- a/frontend/src/views/Login.vue +++ b/frontend/src/views/Login.vue @@ -53,11 +53,11 @@

Don’t have an account? - Sign up + Sign up

Connect with existing account? - Pairing + Pairing

diff --git a/frontend/src/views/Pairing.vue b/frontend/src/views/Pairing.vue index f57d2ce..8a88e36 100644 --- a/frontend/src/views/Pairing.vue +++ b/frontend/src/views/Pairing.vue @@ -97,11 +97,11 @@

Already have an account? - Login + Login

Don’t have an account? - Sign up + Sign up

diff --git a/frontend/src/views/Register.vue b/frontend/src/views/Register.vue index ef4cfb2..cb8f164 100644 --- a/frontend/src/views/Register.vue +++ b/frontend/src/views/Register.vue @@ -77,11 +77,11 @@

Already have an account? - Login + Login

Connect with existing account? - Pairing + Pairing

diff --git a/frontend/src/views/Scan.vue b/frontend/src/views/Scan.vue index 66d6a5f..7524968 100644 --- a/frontend/src/views/Scan.vue +++ b/frontend/src/views/Scan.vue @@ -101,8 +101,8 @@ function classifyScanText(text) { const [, handle, kindLetter, id] = ownerMatch; const kind = kindLetter === "s" ? "storage_location" : "item"; const to = kind === "storage_location" - ? `/storage-locations/${encodeHandleForUrl(handle)}/${id}` - : `/inventory/${encodeHandleForUrl(handle)}/${id}`; + ? {name: 'locations-detail', params: {handle: encodeHandleForUrl(handle), id}} + : {name: 'inventory-detail', params: {handle: encodeHandleForUrl(handle), id}}; return {to, ownerQualifiedId: {handle, kind, id}}; } return null; diff --git a/frontend/src/views/Search.vue b/frontend/src/views/Search.vue index 701b3d2..c922b5a 100644 --- a/frontend/src/views/Search.vue +++ b/frontend/src/views/Search.vue @@ -112,7 +112,7 @@ export default { // user handle - one route shape, no owner-is-me special case. this.fetchSearchResults({query: this.query}).then((results) => { this.search_results = results.map(e => ( - {...e, route: `/inventory/${encodeHandleForUrl(e.owner)}/${e.id}`})) + {...e, route: {name: 'inventory-detail', params: {handle: encodeHandleForUrl(e.owner), id: e.id}}})) }); } }, diff --git a/frontend/src/views/StorageLocation.vue b/frontend/src/views/StorageLocation.vue index 27c98b2..496b2e3 100644 --- a/frontend/src/views/StorageLocation.vue +++ b/frontend/src/views/StorageLocation.vue @@ -55,10 +55,10 @@ {{ location.visibility_policy }} - + - + @@ -94,7 +94,7 @@ - Edit
- @@ -44,7 +44,7 @@ Delete diff --git a/frontend/src/views/StorageLocationNew.vue b/frontend/src/views/StorageLocationNew.vue index f004bb1..5c2f040 100644 --- a/frontend/src/views/StorageLocationNew.vue +++ b/frontend/src/views/StorageLocationNew.vue @@ -81,7 +81,7 @@ export default { ...BIcons }, props: { - // Matches /storage-locations/new/:group?. See docs/implementation.md#owner-filtered-overview-routes-use-path-segments-not-query-strings. + // Matches /locations/new/:group?. See docs/implementation.md#owner-filtered-overview-routes-use-path-segments-not-query-strings. group: { type: String, default: null diff --git a/frontend/src/views/WorkflowDetail.vue b/frontend/src/views/WorkflowDetail.vue index c8b5a44..9d9596f 100644 --- a/frontend/src/views/WorkflowDetail.vue +++ b/frontend/src/views/WorkflowDetail.vue @@ -8,7 +8,7 @@