30 Commits
Author SHA1 Message Date
Donkie 6520ce6d1b Let NFC tags identify filaments as well as spools
A tag can now be linked to a filament type, not just to one spool of it. The
tag table already carried filament_id and target_type for exactly this, so
there is no migration.

API, all additive:

  POST   /filament/{id}/tag        link; 409 if anything else holds the UID
  DELETE /filament/{id}/tag/{uid}  unlink
  GET    /filament?tag=<uid>       exact lookup on the normalized UID
  Filament.tags                    also inside every spool's embedded filament
  TagScan.matched_filament_id      always present, like matched_spool_id
  TagConflictMessage.filament_id   names a filament holder on a 409

One UID still identifies one thing across both kinds: a spool's tag cannot be
linked to a filament or the reverse, and neither ?tag= lookup answers with the
other kind. The scan debounce key now includes the kind, since spool 7 and
filament 7 are different answers.

SpoolTag and SpoolTagParameters are renamed Tag and TagLinkParameters while
they are unreleased, so the schema does not describe filament tags as spool
tags forever.

client_v2: the filament inspector gets the Tags section, the link dialog names
and moves a tag held by either kind, and scanning a filament's tag opens that
filament when auto-navigate is on.

Tag having two delete-orphan parents was checked on SQLAlchemy 2.0.51: new tags
flush, unlinking deletes the row, and deleting either parent cascades.

Proven on sqlite, postgres, mariadb and cockroachdb: 558 integration tests
each. Unit tests, svelte-check and the Playwright tag specs pass.
2026-09-13 10:10:13 +02:00
Donkie 5144b64a8a scripts: add a fake tag reader
The reader-to-Spoolman contract is one ordinary HTTP POST, which means a
complete conforming reader fits in a hundred lines of stdlib and needs no NFC
hardware at all. That is worth having as a tool: pairing, auto-navigate and
filling the link dialog are otherwise only reachable by someone who owns an
ESP32 and has already flashed it.

Interactive by default, because the thing you want while clicking around the
UI is to tap the same tag again, or a new one, without retyping a command.
Blank input re-taps the last UID -- which is also how to watch the server's
de-duplication behave, since it answers every repeat while broadcasting only
the first, exactly as it does for a real reader re-reading a tag that is
sitting on it.

Writes nothing and deletes nothing, unlike its neighbours in this directory:
a scan is an event, not a record.
2026-08-15 09:05:17 +02:00
Donkie b00c1b875d Add dashboard and label-designer screenshots to the README
The library screenshot shows one of the client's four pages. The two
that are hardest to guess at from a feature list -- spools as draggable
cards grouped by location, and labels built from arbitrary spool fields
-- now sit under it in a two-column table, so they cost one screen's
height between them rather than one each.

They are captured at a narrower viewport than the library shot rather
than scaled down from it: at half width a 1440px page reduces to
unreadable, whereas 900px reflows the dashboard to two columns and the
designer to a tighter grid, so the text survives the downscale. Both are
cropped to a 3:2 aspect and have the nav bar removed -- it is already in
the shot above -- so the pair sits level.

Fixed along the way, since it would otherwise have been immortalised in
the dashboard screenshot: the card separators lost a space where they
met an {#if} boundary, which Svelte trims, rendering "Bambu Lab -Bambu
Green" and "1 kg- Last used 2 days ago". The optional parts are now
built as one expression, which has no block edge to trim.

demo_seed gains a note on why label designs aren't seeded: they're a
blob of a client-side schema, so writing one from Python would duplicate
it. The designer's own "Create your first label" is the honest route.
2026-07-31 08:37:47 +02:00
Donkie 0c03f8b404 Stop promoting a spool's comment to its library row title
Grouped by filament, a row had nothing of its own to put in the bold
title slot -- #id, fill, weight and location all have columns -- so it
borrowed the comment when one was set, and dropped the usage status to a
quiet second line behind it.

That assumed comments are short labels. The field is a free-form
textarea: people keep order URLs, multi-line notes and pasted receipts
there. Whatever is in it got the widest, loudest slot in the row, pushed
out "used N ago" -- the one thing every row can say -- and, since .name
is nowrap, ran any newlines together into one line before ellipsing
mid-word.

Rows now always show the usage status. The comment is unabridged in the
inspector, which is the only place it was ever readable in full.

The screenshot is regenerated against the new behaviour, and demo_seed's
comments go back to natural length -- they were written short only to
survive the row.
2026-07-30 22:09:06 +02:00
Donkie 67022e7c6d Regenerate the README screenshot from catalog-imported filaments
The old one was seeded with stress_seed.py, which builds a filament name
from one random pool and its color hex from another, so the picture
contradicted itself: "PETG Copper Bronze" had a blue swatch and "PVA
Sparkle Silver" a tan one. That is the first thing a visitor sees.

scripts/demo_seed.py imports every filament from SpoolmanDB instead,
issuing the same request the client's Add-spools flow does, so names,
colors, densities and temperatures come from one source and agree with
each other. Twenty filaments across eight real vendors are pinned by
external id, chosen for material spread and a varied swatch column; if
one leaves the catalog the script fails with the list rather than
quietly drifting.

The spools on top of them are still made up, because that half really is
per-user data -- partial weights, locations, lot numbers, prices,
first/last-used dates, a few archived and a few still sealed -- plus the
handful of extra fields a real user defines, so the inspector shows
content where it used to show its empty state.

Two details are shaped by how the list renders rather than by realism:
spools consume a whole number of grams, since a decimal wraps onto a
second line in the narrow weight column, and comments stay under ~20
characters, since the list shows a comment in place of "used N ago" and
truncated the longer ones mid-word.
2026-07-30 22:03:19 +02:00
Donkie 6ca753bca0 Move the stress-seed script into scripts/
It has been sitting untracked in client_v2/ -- the wrong place twice
over: it is a backend tool that talks to the API over HTTP and knows
nothing about the client, and client_v2 is excluded from ruff, so
nothing was checking it.

scripts/ already holds the repo's operational scripts, and a poe task
puts it next to the other things you run against a dev instance. The
docstring gains the warning the flags deserve: --purge deletes every
vendor, filament and spool on the target, not only the generated ones.

Ruff now sees it, so scripts/ gets per-file ignores for the rules a
generator legitimately breaks -- stdout is its user interface, its data
is deliberately random and full of literal weights and diameters, and
the generators are long by nature. Type annotations and everything else
stay enforced.

Also fix --skip-fields: it skipped creating the extra-field definitions
but still generated values for them, so every POST failed with "Unknown
extra field" and the run produced nothing.

Claude-Session: https://claude.ai/code/session_01UB5KocsTBm9GL5x3Uuup5F
2026-07-30 20:59:41 +02:00
Donkie f585c51b18 Merge branch 'master' into master 2026-01-18 22:45:29 +01:00
Donkie b361aee956 CI fixes 2026-01-18 16:55:31 +01:00
Donkie b942d1f8a1 Replaced pdm with uv, updated backend deps, python 3.10 minimum, simplified install script 2026-01-07 22:01:02 +01:00
nebelung 21f46427e5 Add support for Fedora to install.sh 2025-11-18 23:10:44 -05:00
Khaos 45ea68bbc0 Enable install script to be automated
Added a script parameter to control the systemd service installation step
2024-12-28 20:24:57 +01:00
foxt 208e2f67e3 Install script: Don't bother using sudo if user is running as root
On some systems, sudo isn't present by default, so allow the user to manually elevate the script bypassing the use of sudo.
2024-08-09 10:01:59 +01:00
CooperGerman a6774dd054 Fix for https://github.com/Donkie/Spoolman/pull/335#discussion_r1578393582 2024-04-26 15:33:48 +02:00
CooperGerman c7f02f52e5 Fix for https://github.com/Donkie/Spoolman/pull/335#discussion_r1578391362 2024-04-26 15:33:48 +02:00
CooperGerman 047b0b286b Added os detection logging in terminal 2024-04-15 10:28:32 +02:00
CooperGerman 81ef9b115d Merged arch and debian install scripts for a generic one 2024-04-09 09:18:47 +02:00
CooperGerman 2a723da910 Create install_arch.sh 2024-03-21 16:37:03 +01:00
Donkie c6c75e6271 Prefix ExecStart with bash to circumvent execute permission issue
No matter how many ways we try to add execute permissions to these scripts they always seem to get lost in one way or another. Now for example Moonraker doesn't run the install_debian.sh script, so the chmod never gets run. A .zip file doesn't seem to properly store the execute permission, so this would never work.
2024-02-02 23:14:54 +01:00
Donkie e77623bab0 Fixed start script 2024-01-25 21:53:48 +01:00
Donkie 1479e13d94 Some script permission fixes 2024-01-25 20:49:16 +01:00
Donkie 52cdb01110 Updated scripts to not use PDM anymore 2024-01-25 20:13:24 +01:00
Donkie cf4add2753 Updated install script and README with new build setup 2023-12-29 13:02:24 +01:00
Donkie b59e0e12a5 Install script now installs Spoolman as a system-level service instead of user level 2023-11-25 21:38:18 +01:00
Donkie 26b5545a29 Fixed pip related stuff in install script not working on debian bookworm
It uses this new "externally managed environment" thing where you can't install system/user level pip packages
2023-11-25 21:38:18 +01:00
Donkie 6f241605f4 Run apt-get update in install script 2023-11-25 21:38:18 +01:00
Donkie dcf9a8f393 Force PDM to use venv as backend in the install script 2023-11-06 22:17:36 +01:00
Donkie 4c38557283 Fixed scripts not being executable 2023-10-23 21:45:42 +02:00
Donkie 6e2f2b08f3 Added systemd path verification to install script 2023-10-22 20:12:23 +02:00
Donkie 292ecbf166 Fixed install script systemd service script path 2023-10-21 23:20:39 +02:00
Donkie ecec122420 Added standalone installation
Resolves #27
2023-10-21 11:49:00 +02:00