diff --git a/future-plans.md b/future-plans.md index 7a7b6cb..4879ea5 100644 --- a/future-plans.md +++ b/future-plans.md @@ -381,6 +381,16 @@ used/visited locations at the top so you can quickly re-select where you just we Useful when processing a batch of components into the same storage location — you shouldn't have to navigate the grid picker from scratch each time. +## Bins + +### Bin types +Define reusable bin type records (e.g. "Sortimo L-Boxx insert small", "Wago 221 +connector box") that store physical dimensions (mm), and optionally a default +compartment layout. When creating or editing a bin, the user picks a type and the +dimensions are pre-filled — no need to re-enter for every bin of the same model. +This also enables filtering/grouping bins by type, and makes it easy to re-process +all bins of a type if the corner algorithm improves. + ## Grids ### Grid view layers diff --git a/public/app.mjs b/public/app.mjs index 7d3b891..8ea418c 100644 --- a/public/app.mjs +++ b/public/app.mjs @@ -2106,6 +2106,8 @@ function open_bin_editor(bin) { bin_editor_bin_id = bin.id; document.getElementById('bin-editor-name').value = bin.name; + document.getElementById('bin-editor-width').value = bin.phys_w ?? ''; + document.getElementById('bin-editor-height').value = bin.phys_h ?? ''; // Show dialog first so the canvas has correct layout dimensions before // load_image reads parentElement.clientWidth to size itself. @@ -2353,6 +2355,8 @@ async function init() { document.getElementById('bin-editor-save').addEventListener('click', async () => { const corners = bin_editor_instance?.get_corners(); const name = document.getElementById('bin-editor-name').value.trim(); + const phys_w = parseFloat(document.getElementById('bin-editor-width').value) || null; + const phys_h = parseFloat(document.getElementById('bin-editor-height').value) || null; if (!corners) { alert('Load an image first.'); return; } const id = bin_editor_bin_id; try { @@ -2361,7 +2365,7 @@ async function init() { const r = await api.rename_bin(id, name); updated = r.bin; } - const r2 = await api.update_bin_corners(id, corners); + const r2 = await api.update_bin_corners(id, corners, phys_w, phys_h); updated = r2.bin; all_bins = all_bins.map(b => b.id === id ? updated : b); document.getElementById('dialog-bin-editor').close(); diff --git a/public/lib/api.mjs b/public/lib/api.mjs index fa38b67..ff90334 100644 --- a/public/lib/api.mjs +++ b/public/lib/api.mjs @@ -66,7 +66,7 @@ export const get_bins = () => req('GET', '/api/bins'); export const create_bin_from_source = (source_id, name) => req('POST', '/api/bins/from-source', { source_id, name }); export const get_bin = (id) => req('GET', `/api/bins/${id}`); export const rename_bin = (id, name) => req('PUT', `/api/bins/${id}`, { name }); -export const update_bin_corners = (id, corners) => req('PUT', `/api/bins/${id}/corners`, { corners }); +export const update_bin_corners = (id, corners, phys_w, phys_h) => req('PUT', `/api/bins/${id}/corners`, { corners, phys_w, phys_h }); export const delete_bin = (id) => req('DELETE', `/api/bins/${id}`); export async function upload_bin(file, name) { diff --git a/public/style.css b/public/style.css index a72029b..6cf08e0 100644 --- a/public/style.css +++ b/public/style.css @@ -1972,6 +1972,22 @@ nav { flex: 1; } +.bin-editor-dims { + display: flex; + align-items: center; + gap: 0.4rem; +} + +.bin-editor-dims input { + width: 5rem; +} + +.form-hint { + font-size: 0.78rem; + color: var(--text-faint); + margin-left: 0.25rem; +} + .bin-editor-canvas { display: block; border-radius: 4px; diff --git a/public/templates.html b/public/templates.html index 41aac83..9e2bd81 100644 --- a/public/templates.html +++ b/public/templates.html @@ -656,6 +656,15 @@ +