Commit Graph

48 Commits

Author SHA1 Message Date
046fe99c72 Fix canvas coordinate mismatch and handle jump-on-grab in Grid_Setup
- Canvas width now read via getBoundingClientRect after setting style.width=100%,
  avoiding the parentElement.clientWidth padding issue that made css_w exceed
  the actual rendered width and broke hit-testing
- All handle drags (corners + midpoints) now use relative delta via drag_prev_img
  instead of absolute cursor position, preventing handle teleport on grab

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 03:20:09 +00:00
1aa7350c4d Add maintenance: purge orphaned source image KV entries
When a source image file is deleted without going through the API
(e.g. the old bin delete bug), the KV entry remains and shows a
broken image. The new maintenance action scans all source image
entries, removes any whose file is missing on disk, and reports
how many were cleaned up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 03:08:38 +00:00
090f6f3154 Add bin types: reusable named dimension presets for bins
Bin types store a name, physical W×H in mm, and optional description.
When editing a bin, a type can be selected from a dropdown; this
pre-fills and locks the dimension inputs. Custom dimensions remain
available when no type is selected.

- lib/storage.mjs: bin type CRUD with bt: prefix
- server.mjs: /api/bin-types CRUD routes; type_id accepted on bin
  create/update routes; DELETE protected if any bin references the type;
  type dims copied onto bin when type_id is set
- public/lib/api.mjs: bin type wrappers; rename_bin → update_bin (accepts
  any fields)
- public/templates.html: Types tab in bins section; t-bin-type-row;
  t-dialog-bin-type; type selector in bin editor dialog
- public/app.mjs: all_bin_types state loaded at startup; render_bin_types_list();
  open_bin_type_dialog(); type selector in open_bin_editor(); /bins/types routing
- public/style.css: bin types list styles

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 03:04:04 +00:00
320c6f1bd9 Add physical dimensions to bin editor for correct aspect ratio
When de-perspectiving a bin photo taken at an angle, inferring the
output size from the quadrilateral shape squishes the result. Entering
real-world W×H (mm) lets the server use the correct aspect ratio,
scaled to the same resolution as the inferred size.

- Bin editor dialog: W×H number inputs, pre-filled from saved phys_w/phys_h
- PUT /api/bins/:id/corners: accepts optional phys_w/phys_h; when provided,
  derives bin_w/bin_h from the physical aspect ratio at equivalent area
- phys_w/phys_h stored on the bin record for re-use on next edit
- future-plans.md: bin types note (reusable dimensions per model)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 05:13:57 +00:00
1ea14f8953 Fix bin editor handle hit-test mismatch
showModal() must be called before load_image() so the canvas has its
correct layout dimensions when parentElement.clientWidth is read.
Calling it after caused css_w to be computed against an unlaid-out
dialog, making drawn handle positions not match hit-test positions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 05:12:16 +00:00
871ad7124a Add Images admin section for managing source image uses
New top-level nav section showing all source images in a list view
with checkboxes to edit the uses array (grid, bin) per image. Allows
correcting wrongly-tagged images without code changes.

Server PUT /api/source-images/:id was already in place; re-added the
frontend API wrapper that was prematurely removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 05:04:57 +00:00
53bd086661 Make source-use badges read-only display labels
Removing toggle interactivity from use badges — they were confusing
and the wrong place to manage uses. The uses array is now managed
automatically by upload context. Badges are plain spans.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 04:41:44 +00:00
38c2d89c9b Add tabbed sub-views to bins section, create-bin-from-source flow
Bins section now mirrors the grids section with two tabs:
- Bins: gallery of processed bin records
- Sources: source images tagged with uses=['bin'], with upload and
  '+ Bin' button to create a bin record from an existing source image

Server: POST /api/bins/from-source accepts source_id, creates bin
record and adds 'bin' to the source image's uses array.

URL state: /bins → bins tab, /bins/sources → sources tab.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 04:41:08 +00:00
e183988acb Hide inactive source-use badges
Inactive badges (uses not present on a source image) are now hidden
rather than shown at low opacity, which was visually noisy and
confusing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 04:30:37 +00:00
28b4590903 Add bins feature: upload, de-perspective, gallery
- lib/storage.mjs: bin CRUD with bin: prefix
- lib/grid-image.mjs: compute_bin_size() capped at 1024px
- server.mjs: POST/GET/PUT/DELETE /api/bins routes; PUT /api/bins/:id/corners
  re-processes image via process_grid_image with rows=1 cols=1
- public/lib/api.mjs: bin API wrappers including upload_bin()
- public/index.html: Bins nav button
- public/templates.html: t-section-bins, t-bin-card, t-dialog-bin-editor
- public/app.mjs: render_bins(), open_bin_editor() using Grid_Setup,
  save/cancel wiring in init()
- public/style.css: bin gallery and card styles

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 04:28:03 +00:00
67369b56be Add edge midpoint drag handles to Grid_Setup
Drag indices 4-7 correspond to top/right/bottom/left edge midpoints.
Dragging a midpoint applies the delta to both adjacent corners, making
it easier to align bins with rounded corners where corner handles may
be obscured.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 04:27:35 +00:00
4813a65a53 PDF: separate display name and filename; show filename in picker; fix rename
- Upload dialog now has distinct display name + filename fields, both pre-filled
  from the uploaded file but independently editable
- Rename in file picker shows and edits both display name and filename separately
- Filename conflict checked against both KV store and disk (via rename_no_replace)
- Display name and filename are fully independent — no longer derived from each other
- Add find_pdf_references() helper in storage.mjs for future use
- CSS: fp-name-wrap shows display name + dim monospace filename below it;
  rename mode stacks two inputs; fp-field-label for upload form labels

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 11:45:50 +00:00
d3df99a8f0 Fix mv-sync path; pre-fill PDF display name from filename on upload
- Fix MV_SYNC path: ../tools resolved to /workspace/tools, should be ./tools
  relative to server.mjs entry point
- Pre-populate display name input when file is selected (strips .pdf extension),
  only if the field is currently empty so manual edits are not overwritten

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 11:42:35 +00:00
58c93f2bd0 Many UX and correctness improvements
- Components URL reflects selected component (/components/:id), survives refresh
- Word-split search: "0603 res" matches "Resistor 0603"
- Left pane resizable with localStorage persistence
- Field values rendered via central render_field_value() (units, URLs, extensible)
- Fields sorted alphabetically in both detail view and edit dialog
- Edit component dialog widened; field rows use shared grid columns (table-like)
- No space between value and unit (supports prefix suffixes like k, M, µ)
- Grid viewer highlights and scrolls to cell when navigating from component detail
- Cell inventory overlay items are <a> tags — middle-click opens in new tab
- PDF files stored with sanitized human-readable filename, not random ID
- PDF rename also renames file on disk
- Atomic rename via renameat2(RENAME_NOREPLACE) through tools/mv-sync
- Fix .cell-thumb-link → .cell-thumb-preview (div, not anchor), cursor: zoom-in
- Fix field name overflow in detail view (auto column width, overflow-wrap)
- Fix link color: use --accent instead of browser default dark blue

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 02:49:11 +00:00
7ef5bb5381 Render URL-like field values as clickable links in component detail
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:29:55 +00:00
08b8e2dd4d Replace goto-grid button with clickable grid cell label in component detail
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:29:08 +00:00
d489c1e306 Inventory view: click component name to navigate to component detail
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:27:11 +00:00
bc339bd073 Right-align grid cell index, count stays left
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:25:27 +00:00
ad96a53246 Grid cell label: left-align, count left of index
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:24:21 +00:00
258f9b6491 Fix grid cell label and count: label below image, count as green text beside it
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:23:27 +00:00
e1c517c023 Grid viewer: improve cell labels and add green inventory count badge
Labels now overlay image with gradient background and visible colour.
Green badge top-right shows number of inventory entries for that cell.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:22:05 +00:00
8fa4a54f9e Widen inventory dialog; fix grid picker cell size to 64px with scroll
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:20:17 +00:00
64af0862f2 Replace row/col number inputs with graphical grid cell picker
Click a cell in the visual grid to select it. Cell images shown where
available. Selected cell highlighted with accent border.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:16:40 +00:00
488fa7ff53 Fix inventory dialog: hidden form-row not hiding due to display:flex override
Also clarify notes label as per-location, not per-component.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:13:47 +00:00
4a210047c8 Fix formatter in inventory component selector; add Duplicate button
- Inventory dialog now uses component_display_name() not c.name
- Duplicate copies name/description/fields and immediately opens edit dialog

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 01:11:11 +00:00
1d3a157d75 Add lightbox for all preview images (component, grid cell, PDF thumbs)
Click any thumbnail to open full-size in overlay. Click backdrop or
press Escape to close. PDF thumbs now clickable too.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 00:45:10 +00:00
cdefa70bd7 Match PDF thumb height to grid cell preview (128px)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 00:42:35 +00:00
8e0f7eb4d8 Add maintenance menu (top-right ⚙) with generate missing PDF thumbnails
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 00:41:40 +00:00
451b04ad03 Add PDF first-page thumbnails via pdftoppm
Generated at upload time, stored alongside the PDF in data/pdfs/.
Shown in the file picker (48px) and component detail view (80px).
Gracefully skipped if pdftoppm is unavailable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 00:40:43 +00:00
61d52d8076 Move file linking to component detail view, consistent with images
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 00:24:35 +00:00
f0bedc80a7 Add PDF file attachments to components
- Upload PDFs, rename them (conflict-checked), delete them
- Link/unlink files per component (many components can share a file)
- File picker dialog: browse existing files, rename inline, upload new
- Component detail shows linked files as clickable links
- Files stored in data/pdfs/, served at /pdf/:filename
- KV prefix: pdf:

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 00:19:30 +00:00
e91a656dc8 Fix grid horizontal scroll: remove overflow-x:hidden from body
body was silently clipping all horizontal overflow. min-width:0 on
#main prevents flex child from expanding beyond container.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 01:28:46 +00:00
dc0e822e9b Fix horizontal scroll in grid viewer: overflow-x on #main not body
body had overflow-x: hidden which ate the scrollbar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 01:25:19 +00:00
b9ba6d38b5 Fix grid viewer zoom: fixed cell px size + overflow-x scroll
Cells are sized in CSS px to fit at load time. Browser zoom now scales
everything uniformly; grid scrolls horizontally instead of reflowing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 01:22:55 +00:00
754f8504f1 Remove grid viewer zoom slider — browser zoom is sufficient
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 01:15:52 +00:00
faed2f8296 Fix grid viewer zoom: use CSS zoom so images and text scale together
Cells stay 1fr (always fill width), CSS zoom shrinks the whole grid
uniformly. No overflow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 01:15:05 +00:00
878b32f9e5 Add zoom/cell-size slider to grid viewer
Images and labels scale together with a range slider (40–300px).
Grid scrolls horizontally when cells exceed viewport width.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 01:08:25 +00:00
520728c62b Allow grid corners to be dragged outside image bounds
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 01:02:24 +00:00
38dba05ac0 Double grid cell thumbnail size to 128px 2026-03-21 00:21:32 +00:00
99299ed9f2 Show grid cell image in component detail inventory entries
Grid-type inventory entries now display the warped cell image from the
grid as a read-only thumbnail (highlighted with accent border) alongside
any user-uploaded images for that entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 00:20:41 +00:00
b66b2f95d3 Add test data box to template editor for live preview
Enter a JS snippet returning a fields object (e.g. return { resistance: '10k' })
to preview the formatter against synthetic data instead of the first real component.
Both the formatter and test data textareas update the preview on input.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 00:18:26 +00:00
896b6fcb39 Fix template formatters: expose c.fields by name not ID
c.fields was keyed by generated field IDs, so c.fields?.resistance
was always undefined. Now fields are remapped by name before being
passed to formatters, so the documented API works as expected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 00:15:37 +00:00
64157013ed Fix cell inventory: clickable entries navigate to component; use display name
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 00:14:19 +00:00
57c697cbfc Add component name formatters and grid-link navigation
Templates section:
- Define JS formatter functions per template (e.g. resistor, capacitor)
- First non-null result from any formatter is used as display name
- Live preview in template editor against first component
- Display names applied in component list, detail view, and inventory rows

Grid navigation:
- Grid-type inventory entries in component detail view show a '⊞' button
  to navigate directly to that grid's viewer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 00:07:01 +00:00
08501539dd Allow creating fields and components inline from dialogs
- Component dialog: 'New...' button next to field selector creates a
  new field definition and immediately adds it to the component form
- Inventory dialog: same pattern for component selector

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 23:54:34 +00:00
6c37912ec5 Add grid cell inventory linking and component quick-create
- New 'grid' location type on inventory entries (grid_id, grid_row, grid_col)
- Clicking a grid cell shows a popup with what's stored there
- Popup has '+ Add entry' pre-filled with the cell coordinates
- Inventory dialog: 'New...' button next to component selector opens
  component creation dialog on top, returns with new component selected
- Grid entries display as e.g. 'Black Component Box R3C5' in lists
- Store original filename on source image upload

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 23:53:06 +00:00
cf37759893 Add grid image system with multi-panel support and SPA routing
- Grid images: photograph component boxes in sub-sections, assemble
  into one logical grid via perspective warp (homography)
- Source image gallery: bulk upload photos separately from grid setup
- Grid drafts: persist partial work, resume across sessions
- Multi-panel grids: define rows/cols per photo, system computes panel
  layout; process partially configured grids, edit individual panels
- Pan/zoom canvas editor (HiDPI-aware, touch support) for corner alignment
- SPA routing with canonical URLs (history.pushState, server catch-all)
- Express error visibility: uncaughtException/unhandledRejection handlers
  and 4-arg error middleware
- Original filename stored on source image upload
- Various null-safety fixes and CSS [hidden] override fixes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 23:30:17 +00:00
ef2e53ea18 Initial electronics inventory webapp
KV-store backed Express 5 app for tracking electronic components,
their arbitrary fields, and inventory locations (physical, BOM, digital).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 19:11:13 +00:00