Commit Graph
1478 Commits
Author SHA1 Message Date
Anonymous 8382a9037d Translated using Weblate (Korean)
Currently translated at 26.7% (137 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/ko/
2026-08-05 18:57:48 +02:00
Anonymous fc4cf78451 Translated using Weblate (Japanese)
Currently translated at 26.7% (137 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/ja/
2026-08-05 18:57:43 +02:00
Anonymous 13b1ab7f94 Translated using Weblate (Italian)
Currently translated at 26.7% (137 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/it/
2026-08-05 18:57:38 +02:00
Anonymous 7262563e4d Translated using Weblate (Hungarian)
Currently translated at 25.3% (130 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/hu/
2026-08-05 18:57:29 +02:00
Anonymous 7cf8f6f0eb Translated using Weblate (Hindi (Latin script))
Currently translated at 0.3% (2 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/hi_Latn/
2026-08-05 18:57:24 +02:00
Anonymous 01462d3df3 Translated using Weblate (French)
Currently translated at 26.3% (135 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/fr/
2026-08-05 18:57:19 +02:00
Anonymous faa4659b6d Translated using Weblate (Persian)
Currently translated at 26.3% (135 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/fa/
2026-08-05 18:57:14 +02:00
Anonymous aaa8714f66 Translated using Weblate (Estonian)
Currently translated at 3.1% (16 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/et/
2026-08-05 18:57:09 +02:00
Anonymous da5eeef1a0 Translated using Weblate (Spanish)
Currently translated at 26.7% (137 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/es/
2026-08-05 18:57:02 +02:00
Anonymous e73f603f39 Translated using Weblate (Greek)
Currently translated at 22.4% (115 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/el/
2026-08-05 18:56:56 +02:00
Anonymous a7be90ef4a Translated using Weblate (German)
Currently translated at 26.7% (137 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/de/
2026-08-05 18:56:49 +02:00
Anonymous 5b889c2e7a Translated using Weblate (Danish)
Currently translated at 26.7% (137 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/da/
2026-08-05 18:56:44 +02:00
Anonymous 796ef5941e Translated using Weblate (Czech)
Currently translated at 42.8% (220 of 513 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/cs/
2026-08-05 18:56:37 +02:00
github-actions[bot] 58f4b13cd2 Merge pull request #1023 from Donkie/weblate
Translations update
2026-08-05 16:45:44 +00:00
Anonymous e50c2ec72f Translated using Weblate (Latvian)
Currently translated at 4.5% (13 of 288 strings)

Translated using Weblate (Slovak)

Currently translated at 10.4% (30 of 288 strings)

Co-authored-by: Anonymous <noreply@weblate.org>
Translate-URL: https://hosted.weblate.org/projects/spoolman/web-client/lv/
Translate-URL: https://hosted.weblate.org/projects/spoolman/web-client/sk/
Translation: Spoolman/Web Client LEGACY
2026-08-05 18:41:21 +02:00
Donkie fcf0e8b145 Merge pull request #1021 from Donkie/worktree-weblate-ru-conflict
ci: merge Weblate PRs instead of squashing them
2026-08-05 18:38:51 +02:00
Donkie a4c113ba8e ci: merge Weblate PRs instead of squashing them
Squash merging replaces Weblate's commits with a new one whose hash, and
for multi-commit PRs whose patch-id, matches nothing Weblate knows. Its
clone then rebases those commits onto a master that already contains the
same strings and hits a content conflict, after which Weblate stops
syncing until it is reset by hand. PR #1004 squashed two Russian commits
and broke ru/common.json exactly this way.

A merge commit keeps each Weblate commit reachable at its original hash,
so the rebase drops them as already-upstream. Nothing required squash
here: allow_merge_commit is on, the master ruleset has no linear-history
rule, and human PRs already land as merge commits.
2026-08-05 18:36:16 +02:00
Donkie b12e129e5b Merge pull request #1020 from Donkie/worktree-v2-change-vendor
client_v2: let a filament's manufacturer be changed
2026-08-05 18:23:50 +02:00
Donkie b2f5088081 client_v2: let a filament's manufacturer be changed
The manufacturer was decided once, in the add-spool modal, and there was no
way back: a filament created under the wrong brand — or under none — stayed
there, and since the library groups by manufacturer that mis-files every
spool of it. The companion to the spool's change-filament (#1010), one level
up the chain.

Adds a "Change" action to the MANUFACTURER section of the filament
inspector, opening a dialog with the three destinations the API allows: one
of your manufacturers, a new one named on the spot (as the add-spool form
already allows), or none at all. There is no SpoolmanDB side to this one —
the external catalog carries filaments and materials, not manufacturers — so
the picker fetches the vendor list whole and filters it in the browser.

The dialog spells out the one consequence that isn't obvious. A filament
with no empty spool weight of its own takes its manufacturer's, and that is
the figure `PUT /spool/{id}/measure` subtracts from a reading off the scale,
so the note says what it becomes — or that it is about to have none. A
filament that has its own keeps it and gets no note: unlike the spool's full
weight, that field is editable right there in the panel.

Clearing the manufacturer travels as an explicit `vendor_id: null`, which is
what the API reads as "no manufacturer"; dropping the key instead would have
made that choice a silent no-op.
2026-08-05 18:14:28 +02:00
Donkie 7aa864e457 Merge pull request #1016 from Donkie/worktree-fix-1012-unused-grouping
client_v2: file unused spools under their own filament
2026-08-03 20:35:11 +02:00
Donkie 032b3f05c2 client_v2: file unused spools under their own filament
A collapsed "×N unused" row speaks for its whole pile with one filament's
name, swatch, weight and location, all read off the first spool. That only
holds within a filament group. Under Manufacturer (or Material/Location) a
group spans many filaments, so the whole unused pile was filed under
whichever filament happened to sort first: five different SUNLU woods
listed as "Wood Cherry ×5 unused" (#1012).

Bucket the pile by filament before collapsing it, keeping the backend's
order via first appearance. Buckets of one render inline as before.

Fixes #1012
2026-08-03 20:27:33 +02:00
Donkie 7db40b4036 Merge pull request #1015 from Donkie/worktree-spool-field-overrides
client_v2: per-spool weight and spool weight overrides
2026-08-03 20:17:42 +02:00
Donkie 4ed1fbfc67 client_v2: let a label print the spool's own tare weight
The v1 client offered the spool's empty-spool weight and its filament's as two
separate label tokens. v2 kept only the filament's, so `{spool_weight}` in a
migrated v1 design had no equivalent to map to and resolved to "?" — and a
design rebuilt in v2 could only print the filament's figure, which is not
necessarily the one that spool is measured against.

`spool.spoolWeight` falls back to the filament the way `spool.price` already
does, so a `spool.*` token prints what actually applies to that spool.
2026-08-03 20:09:42 +02:00
Donkie 155e8f3737 client_v2: make the override marks footnotes rather than badges
Accent-coloured pills next to four fields read as warnings about something
being wrong, when all they report is that a spool holds a value of its own.
Keep the accent colour, which is what makes them findable, and drop the border,
weight and uppercasing that gave them the urgency.

Both ends now render identically. The winning and shadowed levels were
distinguished by colour, but the wording already says which is which
("Overrides filament" vs "Overridden by this spool"), so the variant carried
nothing the label didn't.
2026-08-03 19:59:45 +02:00
Donkie b885108a3d client_v2: let a spool override the values it inherits from its filament
A spool can hold its own full weight, empty-spool (tare) weight and price,
falling back to its filament's where it has none. The API has had all three
since #339, and the v1 client exposed them, but client_v2 never mapped
spool_weight at all and had no field for it or for the full weight.

The result was silent wrong arithmetic (#1013): the API gives every spool it
creates a copy of the filament's tare weight, so correcting the *filament*
later looked like it had worked — the spool panel showed the new figure — while
"adjust by measured weight" went on subtracting the old one. A reporter's empty
261 g spool came back with 129 g still on it, exactly the difference.

Both ends of a disagreement are now marked. The spool's field says what it
shadows, the filament's row says what applies instead and is struck through,
and the same treatment covers the manufacturer's empty-spool weight, which
seeds a filament and is then left behind. Only where the values actually
differ: merely having one of its own is already visible in the field, and
marking every spool would teach everyone to stop reading the marks.

Also fixes a 500 from PUT /spool/{id}/measure when nothing in the chain has a
tare weight — reachable in one click now that the field can be cleared.
2026-08-03 18:06:05 +02:00
Donkie 1d5b8c1d3d Merge pull request #1014 from Donkie/worktree-issue-1010-change-filament
client_v2: let a spool's filament be changed
2026-08-03 17:24:30 +02:00
Donkie f2b060f6ca client_v2: let a spool's filament be changed
The v1 client had a filament dropdown on the spool edit form; client_v2
dropped it, leaving no way to re-point a spool at a different filament
(#1010). People who organise their shelves by spool number need slot #37
to stay slot #37 when the roll in it is replaced, and deleting and
re-adding the spool hands them a new id.

Adds a "Change" action to the FILAMENT section of the spool inspector,
opening a dialog that searches the local catalog and SpoolmanDB (an
external pick is imported on apply, as in the add-spools flow). The spool
keeps its id, location, dates, lot, comment and used weight.

The full weight needs a decision the dialog makes explicit: a spool
created from a filament records that filament's weight as its own, so it
would otherwise keep the old figure forever and this client has no other
field for it. When the new filament's weight differs, the dialog offers
to take it (checked by default) and spells out the resulting remaining
weight. A spool with no weight of its own follows its filament anyway —
that case just says so.
2026-08-02 22:51:16 +02:00
Donkie 9d53a3f292 Merge pull request #1008 from Donkie/worktree-client-v2-401-reload
Reload on 401 so a forward-auth session can recover
2026-08-02 15:06:57 +02:00
Donkie 708af05ab2 ci: run the client_v2 unit tests
The ci hook lints, formats and type checks client_v2 but never ran its unit
tests, so everything under src/**/*.test.ts was local only and nothing would
have caught a broken one. The backend group already runs pytest here, so this
is just the missing counterpart. The browser suite in tests_frontend_v2/ is
unaffected, it covers different ground and runs in its own job.

Adds about 4s to the style job, which already installs client_v2 deps. Left
out of pre-commit so committing stays fast.

Also points the type check comment at the pre-commit copy it meant, rather
than at itself.
2026-08-02 14:59:38 +02:00
Donkie ae12072cdd Merge remote-tracking branch 'origin/master' into worktree-client-v2-401-reload
# Conflicts:
#	client_v2/src/lib/api/search.ts
2026-08-02 14:13:41 +02:00
Donkie 2a03f9f64c client_v2: reload on 401 so a forward-auth session can recover
Behind a forward-auth proxy (Authelia, Authentik, oauth2-proxy) an idle
tab starts getting 401s once the session expires. The proxy can only
redirect a top-level navigation, so a page that is already loaded never
gets offered the login portal and simply fails every request until the
user works out that a manual reload fixes it.

Do that reload for them. It counts as a navigation, so it earns the
redirect and brings the user back to the page they were on. Rate limited
to once per 30s so a 401 that a reload cannot fix does not put the tab in
a loop, and skipped for writes so a half filled form is not lost to a
login redirect.

Both transports are covered. REST goes through http.ts. Websockets get an
HTTP probe instead, since a handshake refused by a proxy exposes no status
to the browser and is otherwise indistinguishable from a backend that is
down. search.ts moves onto the shared fetch helper so it is covered too.

Dormant without a proxy in front, since Spoolman never answers 401 itself.

Refs #923
2026-08-02 12:47:13 +02:00
Donkie cefd2caa42 Merge pull request #987 from Sanjays2402/fix/color-hex-strip-hash
fix(api): strip leading # from filament color codes
2026-08-02 11:23:16 +02:00
Donkie 3beb2b4483 Merge pull request #1006 from Donkie/worktree-search-spool-pills
Offer a filament's spools in the search results
2026-08-02 10:32:08 +02:00
Donkie 0c3ce54da9 Merge pull request #1007 from Donkie/worktree-issue-994-reorder-choices
Allow reordering of extra field choices
2026-08-02 10:31:55 +02:00
Donkie ac3ec7d1a2 Merge pull request #1005 from Donkie/search-material-tag
Distinguish the search result material tag from the match tag
2026-08-02 10:26:44 +02:00
Sanjay Santhanam 7e4d2ee419 fix(api): repair filament rows already stored with a leading #
The validator fix only guards the write path. Instances that already hit #780
keep 500ing on GET /filament because the stored value exceeds the response
model's max_length, and the UI can't repair what it can't list.

Filament.from_db now strips the # and returns None when the stored value still
isn't a valid 6/8 character code, so a single bad row no longer takes down the
whole list. A migration chained from 415a8f855e14 rewrites existing rows one by
one through op.get_bind() rather than with SQL string functions, so it behaves
the same on sqlite, postgres, mysql and cockroachdb. downgrade() is a no-op.
2026-08-02 00:22:27 -07:00
Donkie 46beda2264 Offer a filament's spools in the search results
Searching a filament name only ever returned the filament: a spool matches
on its own text (comment, location, lot number, extra fields) or its exact
id, so a name that lives on the filament could not reach any of its spools.
The hit named the filament you own and then dead-ended.

Each filament result now carries its first few spools as pills, with an
overflow link to the filament for the rest. GET /search gains an opt-in
spools_per_filament parameter; at 0, the default, the response is byte for
byte what it was, so nothing else that reads the endpoint changes.

The spools are fetched in one query over the matched filaments and grouped
in Python rather than with a per-group window function, which keeps the
behaviour identical on all four supported databases, and yields the exact
total count for free. They obey allow_archived like the rest of the
response, and are ordered by id so "first" means the same thing everywhere.

Fixes #993
2026-08-02 08:40:41 +02:00
Donkie 18f114419f Let extra field choices be reordered by dragging
Choice values could only be appended, so the only way to get a value into
the right place was to remove everything after it and type it all back in.
Both clients now render each choice with a grip: drag it, or focus it and
press the left/right arrow keys, to move it. The backend already accepts a
reordered list — it only refuses removals.

Fixes #994
2026-08-02 08:35:18 +02:00
Donkie 3c1d8bfa6d client_v2: separate the search result's material tag from the match tag
The material chip and the "matched: <field>" chip sat side by side at the
trailing edge with identical styling, so two unrelated facts read as one kind
of thing. Move material next to the filament name (mirroring the group header)
and give it an outline variant, leaving the filled chip to mean "why this
result matched".
2026-08-02 08:23:10 +02:00
Weblate (bot)andDr_Perry_Coke 20462e86e2 Translations update from Hosted Weblate (#1004)
* Translated using Weblate (Russian)

Currently translated at 74.4% (344 of 462 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/ru/

* Translated using Weblate (Russian)

Currently translated at 76.0% (353 of 464 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/ru/

---------

Co-authored-by: Dr_Perry_Coke <dr.perrycoke@gmail.com>
2026-08-02 06:21:00 +00:00
Donkie a2cfe33cd3 Merge pull request #1003 from tomaioo/fix/security/unsafe-json-parsing-of-application-setti
Security: Unsafe JSON parsing of application settings
2026-08-02 08:16:32 +02:00
Donkie f8db2a0f09 Merge pull request #1001 from Donkie/fix/library-header-affordances
fix(library): make the group header's destinations findable
2026-08-02 08:15:07 +02:00
tomaioo 95230eaa73 fix(security): unsafe json parsing of application settings
The `useCurrency` and `useCurrencyFormatter` functions parse currency settings using `JSON.parse` directly on values fetched from the backend. If the backend returns malformed JSON or unexpected data types, this will throw an unhandled exception and crash the UI component relying on these hooks.

Signed-off-by: tomaioo <203048277+tomaioo@users.noreply.github.com>
2026-08-01 23:12:38 -07:00
2cdfcc1bae Translations update from Hosted Weblate (#1002)
* Translated using Weblate (Czech)

Currently translated at 47.6% (220 of 462 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/cs/

* Translated using Weblate (Swedish)

Currently translated at 35.7% (165 of 462 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/sv/

---------

Co-authored-by: Miloslav Kos <kos.m@post.cz>
Co-authored-by: Daniel Hultgren <daniel.cf.hultgren@gmail.com>
2026-08-02 05:17:00 +00:00
Donkie e175708b3e fix(ci): diff PRs from the merge base in guard-translations
The guard compared the base branch tip against the PR head directly, so
every commit that landed on master after a PR forked counted as one of
that PR every time it re-ran. Merging a Weblate sync therefore failed
unrelated PRs with client_v2/locales/sv/common.json in the offending
list, and the only way out was rebasing a PR that had never touched a
translation file.

Diffing BASE...HEAD resolves the merge base first, which is what "the
changes this PR makes" means, and it stays right however far master
moves on. Verified against PR 1001: the old form flags sv, the new form
passes, and a real hand-edit of sv is still caught.
2026-08-01 22:11:42 +02:00
Donkie a5e4bc0bf3 fix(library): drop the group header arrow
The hover underline and colour already say the title is a link, and the
arrow was one more glyph on a row that has a chevron doing something
else. Touch users lose the at-rest cue, but the manufacturer link below
is visible without hover either way.
2026-08-01 21:55:42 +02:00
Weblate (bot)andDaniel Hultgren cbc6458c5d Translated using Weblate (Swedish) (#1000)
Currently translated at 36.6% (161 of 439 strings)

Translation: Spoolman/Spoolman Web UI v2
Translate-URL: https://hosted.weblate.org/projects/spoolman/spoolman-web-ui-v2/sv/

Co-authored-by: Daniel Hultgren <daniel.cf.hultgren@gmail.com>
2026-08-01 15:18:43 +00:00
Donkie 13b7a9b62f Merge pull request #999 from Donkie/worktree-issue-992-detail-fields
Show all filament and manufacturer fields in the library detail views
2026-08-01 17:18:29 +02:00
Donkie 7c29d5f54a Merge pull request #998 from Donkie/worktree-client-v2-delete-991
client_v2: add delete for filaments and manufacturers
2026-08-01 11:14:23 +02:00
Donkie 6663a42ab5 client_v2: add delete for spools
The old client could delete spools (canDelete on the resource, rendered
by Refine's Show header buttons); client_v2 shipped with archive only.
That left the filament delete a dead end: archiving does not release the
foreign key, and there is no way to reassign a spool either, so a
filament that had ever held a spool could never be removed.

The confirm warns when filament is left on the spool, since archiving is
probably what was meant in that case.

Also corrects the blocked-filament hint, which suggested moving spools
to another filament - something this UI cannot do.
2026-08-01 11:03:24 +02:00