diff --git a/docs/PARTS_LABELS.md b/docs/PARTS_LABELS.md index 9f382e7..54dbac5 100644 --- a/docs/PARTS_LABELS.md +++ b/docs/PARTS_LABELS.md @@ -1,7 +1,8 @@ # Parts Drawer Labels Admin-only labelling system for sorting drawers and bags. Browse a part -taxonomy, define a label per drawer, and print them onto sticker sheets. +taxonomy, define a label per drawer, and print them onto sticker sheets or +continuous tape. Lives at **`/admin/labels`** — in the admin menu as *Parts Labels*. @@ -24,17 +25,18 @@ If you'd rather make the database change deliberately before restarting: ``` python migrate_add_part_labels.py +python migrate_add_parts_catalogue.py ``` Optional extras: | What | Why | How | |------|-----|-----| -| Rebrickable API key | Part lookup: numbers, names, artwork | `REBRICKABLE_API_KEY=...` in `.env`, or paste it into *Labels → Settings* | -| ReportLab | PDF export button | `pip install reportlab` | +| Rebrickable API key | Part photos when importing a label | `REBRICKABLE_API_KEY=...` in `.env`, or paste it into *Labels → Settings* | +| ReportLab | PDF export button for sheets | `pip install reportlab` | Neither is required. Without them you type labels in by hand, upload your own -images, and print from the browser. +images, and print from the browser. The part catalogue works without a key. --- @@ -63,9 +65,9 @@ and use them; this is for generating your own. - *New Label* — name, dimensions, part number, alternates, category, drawer, colour, image. -- Or, with a Rebrickable key, search on the labels page and hit *Add label* on - a result. It pulls the name, number and image, caches the image locally so - printing works offline, then drops you on the edit form to set the drawer. +- Or pick them off the *Part Catalogue* tab (see below), which is much faster + for more than a handful. +- Or, with a Rebrickable key, use the quick lookup box on the labels page. **The `name` + `dimensions` split matters.** Name is the big bold line ("Brick", "Plate, Modified with Clip"); dimensions is the geometry ("2 x 4"). @@ -75,9 +77,9 @@ mixed drawers. **Alternate part numbers** are for old moulds that live in the same drawer — `3001a, 3001b`. Comma separated, searchable, optionally printed. -**Printing** +**Printing to sheets** -1. Tick labels (or *Print whole category*). +1. Tick labels (or *Print whole category*), press **Sheet**. 2. Pick a sheet, set the options, hit *Update preview*. 3. Print from the browser: **margins None, scale 100%** — not "Fit to page", which is what ruins most label sheets. @@ -100,15 +102,116 @@ or paper-and-tape. --- +## The part catalogue (the Update button) + +*Labels → Part Catalogue*, then **Update catalogue**. + +This pulls Rebrickable's published catalogue dumps into a local table so that +making a label is picking a part off a list rather than typing it out: + + https://cdn.rebrickable.com/media/downloads/part_categories.csv.gz + https://cdn.rebrickable.com/media/downloads/parts.csv.gz + +Two gzipped CSVs, about 60,000 parts, regenerated monthly by Rebrickable and +free to use with a credit. **No API key is needed for this** — the key only +adds the real part photo at the moment a catalogue row becomes a label. + +The sync runs on a background thread and reports progress to the page, so you +can close the tab. Re-running it is cheap and idempotent: it only writes rows +that are new or actually changed (a second run on an unchanged catalogue +writes nothing). + +**Category mapping.** Rebrickable's categories are theirs; the drawer +taxonomy is yours. Open a Rebrickable category and set *"Parts in this +category become labels in …"* once, and from then on importing any part from +it drops the label straight into the right drawer group. Unmapped categories +just ask you each time. + +**Making labels.** Tick parts, optionally override the drawer category, press +*Make labels*. Parts already labelled are flagged and skipped, so you can +re-import a category without creating duplicates. `Brick 2 x 4` is split into +name `Brick` + dimensions `2 x 4` on the way in, because the label stores them +separately so the print options can show or hide the geometry. + +Thumbnails in the browse list use Rebrickable's predictable LDraw render path +and quietly disappear for parts that have no LDraw model. That is expected — +the real image is fetched per-part when you create the label. + +--- + +## Printing to the Brother VC-500W + +*Labels → tick some labels → **Tape***, or the tape icon on any row. + +The VC-500W is AirPrint-enabled, which means it speaks **IPP on port 631** — +an open, documented protocol. So LIM talks to it directly over the network: +no Brother driver, no P-touch Editor, no exporting a PDF and printing it by +hand. Brother publish no raw command protocol for this printer and none is +reverse-engineered here; it is plain standard IPP (RFC 8010/8011). + +**Setup.** Put the printer's IP address into *Labels → Settings → Tape +printer*. Give it a DHCP reservation first or the address will wander. Then +hit **Test connection** on the tape page: it reports the model, state, and +exactly which document formats the printer will accept. + +**Format negotiation.** LIM renders at the printer's native 313 dpi and sends +whichever format the printer lists that LIM can produce — JPEG, PNG or PDF, in +that order. If your firmware only offers `image/urf` or raster formats, the +test will say so and you use *Download PDF* instead. You can pin a format in +Settings if auto-negotiation ever picks wrong. + +**Tape widths.** CZ tape in 9, 12, 19, 25 and 50 mm. Each preset knows its +printable width; labels are sized to the content, or to a fixed length if you +set one. Maximum length is about 430 mm. + +> **Check this on your first print:** labels are rotated 90° by default, +> because the tape feeds lengthwise. If your first one comes out sideways, +> untick *Rotate for tape feed* and print again. It is the one setting worth +> testing on a fresh printer, so print one before queueing fifty. + +Copies are sent as repeated jobs rather than via the IPP `copies` attribute, +because tape printers vary wildly in whether they honour it. + +### What to do when it won't print + +| Symptom | Likely cause | +|---|---| +| *Could not reach the printer* | Wrong IP, printer asleep, or on its own ad-hoc Wi-Fi rather than your LAN | +| *Printer rejected the job: …not-supported* | It won't take JPEG/PNG/PDF. Use Download PDF | +| Prints sideways | Untick *Rotate for tape feed* | +| Text clipped at the edges | Raise *Padding*, or lower *Text size* | +| Blank or faint | Cleaning cassette (CK-1000), or the tape is in backwards | + +--- + +## The catalogue look + +The labelling pages use a denser, cooler-toned skin than the rest of LIM +(`app/static/css/labels-bricklink.css`, scoped to `.bl`). That is deliberate: +this is a reference catalogue where you scan hundreds of rows, not a library +you browse by cover art — so small type, tight rows, thin rules and counts on +everything. It is our own stylesheet, not a copy of anyone's site, and it does +not leak into the red LEGO-themed pages. + +--- + ## Where things live ``` app/models/part_label.py PartCategory (tree) + PartLabel -app/services/part_catalog.py taxonomy seeding, Rebrickable client +app/models/part_catalog_item.py local Rebrickable mirror + sync history +app/services/part_catalog.py taxonomy seeding, Rebrickable API client +app/services/catalog_sync.py the Update button: CSV dumps -> database app/services/label_render.py sheet geometry, layout, optional PDF -app/routes/labels.py the blueprint (all admin_required) +app/services/tape_printer.py 313dpi tape rendering, CZ tape presets +app/services/ipp_client.py minimal IPP client (RFC 8010/8011) +app/routes/labels.py /admin/labels (all admin_required) +app/routes/labels_catalog.py /admin/labels/catalog +app/routes/labels_tape.py /admin/labels/tape app/data/part_taxonomy.json the starter taxonomy -app/templates/admin/labels/ index, form, categories, settings, print +app/static/css/labels-bricklink.css the catalogue skin +app/templates/admin/labels/ index, form, categories, settings, print, + catalog, tape, _nav /parts/ cached and uploaded part images ```