224 lines
9.2 KiB
Markdown
224 lines
9.2 KiB
Markdown
# 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 or
|
|
continuous tape.
|
|
|
|
Lives at **`/admin/labels`** — in the admin menu as *Parts Labels*.
|
|
|
|
---
|
|
|
|
## Deploying
|
|
|
|
The feature is already wired into `app/__init__.py`, `schema_upgrade.py` and
|
|
`base.html`, so a normal pull is enough:
|
|
|
|
```
|
|
git pull
|
|
```
|
|
|
|
Restart LIM. The tables are created automatically at boot by
|
|
`app/services/schema_upgrade.py`, and the taxonomy seeds itself the first time
|
|
an admin opens the page.
|
|
|
|
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 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. The part catalogue works without a key.
|
|
|
|
---
|
|
|
|
## Why not Brickset?
|
|
|
|
Brickset's API v3 covers sets, minifigs and instructions. It has **no parts
|
|
endpoint**, so it can't supply part numbers, names or part images.
|
|
[Rebrickable](https://rebrickable.com/api/) can, and a key is free. Brickset
|
|
stays where it is, doing sets.
|
|
|
|
## Why not Brick Architect's labels?
|
|
|
|
Tom Alphin's label PDFs and his category numbering are his own copyrighted
|
|
work. This feature doesn't scrape, copy or redistribute them. What ships is a
|
|
starter taxonomy built from standard LEGO/BrickLink part terminology, arranged
|
|
in the same *style* of hierarchy, and completely editable — rename, renumber,
|
|
recolour and restructure it from *Labels → Categories* so it matches how your
|
|
drawers actually run. If you want his exact labels, download them from his site
|
|
and use them; this is for generating your own.
|
|
|
|
---
|
|
|
|
## Day-to-day
|
|
|
|
**Adding labels**
|
|
|
|
- *New Label* — name, dimensions, part number, alternates, category, drawer,
|
|
colour, image.
|
|
- 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").
|
|
They're printed together but stored apart so you can turn dimensions off for
|
|
mixed drawers.
|
|
|
|
**Alternate part numbers** are for old moulds that live in the same drawer —
|
|
`3001a, 3001b`. Comma separated, searchable, optionally printed.
|
|
|
|
**Printing to sheets**
|
|
|
|
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.
|
|
|
|
Options worth knowing:
|
|
|
|
- **Skip positions** — start partway down a part-used sheet instead of wasting it.
|
|
- **Copies each** — same label on several drawers.
|
|
- **Offset X/Y** — per-printer alignment nudge in millimetres. Set your usual
|
|
value once in *Settings*.
|
|
- **Outline each label** — hairlines for cutting, and for test-printing on plain
|
|
paper before you commit a sheet of Averys.
|
|
- **Show on each label** — image, name, dimensions, part number, alternates,
|
|
category, category code, drawer, colour, category colour stripe.
|
|
|
|
**Sheet presets**: Avery L7651 (65/sheet, good for bags), L7160 (21/sheet, the
|
|
all-rounder), L7163 (14/sheet, wide), L7159 (24/sheet), L7169 (8/sheet, large),
|
|
Avery 5160 (US Letter), plus two plain-A4 grids for cut-your-own sticker paper
|
|
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/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/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/static/css/labels-bricklink.css the catalogue skin
|
|
app/templates/admin/labels/ index, form, categories, settings, print,
|
|
catalog, tape, _nav
|
|
<UPLOAD_FOLDER>/parts/ cached and uploaded part images
|
|
```
|
|
|
|
Labels are **not** an inventory. There's no quantity field on purpose — the
|
|
drawer tells you how many you have.
|
|
|
|
---
|
|
|
|
Created by: Jess Rogerson (yelling commands at Claude.AI)
|