Document the catalogue sync, tape printing and the skin
This commit is contained in:
1 parent
b8571697dd
commit
bad4787e00
1 file changed
+115
-12
+115
-12
@@ -1,7 +1,8 @@
|
|||||||
# Parts Drawer Labels
|
# Parts Drawer Labels
|
||||||
|
|
||||||
Admin-only labelling system for sorting drawers and bags. Browse a part
|
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*.
|
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_part_labels.py
|
||||||
|
python migrate_add_parts_catalogue.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Optional extras:
|
Optional extras:
|
||||||
|
|
||||||
| What | Why | How |
|
| What | Why | How |
|
||||||
|------|-----|-----|
|
|------|-----|-----|
|
||||||
| Rebrickable API key | Part lookup: numbers, names, artwork | `REBRICKABLE_API_KEY=...` in `.env`, or paste it into *Labels → Settings* |
|
| Rebrickable API key | Part photos when importing a label | `REBRICKABLE_API_KEY=...` in `.env`, or paste it into *Labels → Settings* |
|
||||||
| ReportLab | PDF export button | `pip install reportlab` |
|
| ReportLab | PDF export button for sheets | `pip install reportlab` |
|
||||||
|
|
||||||
Neither is required. Without them you type labels in by hand, upload your own
|
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,
|
- *New Label* — name, dimensions, part number, alternates, category, drawer,
|
||||||
colour, image.
|
colour, image.
|
||||||
- Or, with a Rebrickable key, search on the labels page and hit *Add label* on
|
- Or pick them off the *Part Catalogue* tab (see below), which is much faster
|
||||||
a result. It pulls the name, number and image, caches the image locally so
|
for more than a handful.
|
||||||
printing works offline, then drops you on the edit form to set the drawer.
|
- 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
|
**The `name` + `dimensions` split matters.** Name is the big bold line
|
||||||
("Brick", "Plate, Modified with Clip"); dimensions is the geometry ("2 x 4").
|
("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 —
|
**Alternate part numbers** are for old moulds that live in the same drawer —
|
||||||
`3001a, 3001b`. Comma separated, searchable, optionally printed.
|
`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*.
|
2. Pick a sheet, set the options, hit *Update preview*.
|
||||||
3. Print from the browser: **margins None, scale 100%** — not "Fit to page",
|
3. Print from the browser: **margins None, scale 100%** — not "Fit to page",
|
||||||
which is what ruins most label sheets.
|
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
|
## Where things live
|
||||||
|
|
||||||
```
|
```
|
||||||
app/models/part_label.py PartCategory (tree) + PartLabel
|
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/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/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
|
||||||
<UPLOAD_FOLDER>/parts/ cached and uploaded part images
|
<UPLOAD_FOLDER>/parts/ cached and uploaded part images
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user