Compare commits

..

678 Commits

Author SHA1 Message Date
Matthew Kilgore
e47a7ff6f2 Switch to minutes for uptime, remove duplicate event on startup 2025-07-12 20:42:12 -04:00
Matthew Kilgore
57385f9ada Some cleanup 2025-07-12 16:53:13 -04:00
Matthew Kilgore
94df40b718 Even better logic for scheduling the analytics (hopefully) 2025-07-12 16:50:31 -04:00
Matthew Kilgore
c9cb1abdd9 Better analytics scheduling 2025-07-12 16:46:03 -04:00
Matthew Kilgore
76d7b3d6ca Merge branch 'main' into mk/daily-analytics
# Conflicts:
#	backend/app/api/main.go
2025-07-12 16:38:17 -04:00
Matthew Kilgore
017b05452a Merge remote-tracking branch 'origin/main' 2025-07-12 16:37:09 -04:00
Matthew Kilgore
6a1f2549df Cleanup main file after revert, add freebsd build 2025-07-12 16:37:01 -04:00
Matthew Kilgore
2f51ba419b Revert "Support listening on unix sockets and systemd sockets (#878)"
This reverts commit 850ed476
2025-07-12 16:33:29 -04:00
Matias Godoy
bcd77ee796 Make search accent-insensitive (#887)
* Make search accent-insensitive

* Efficiendy improvements and small fixes

* Fix tests to improve coverage

* Fix SQL compatibility issues
2025-07-12 16:16:55 -04:00
Matt
23cecfb2a5 Refactor main file, add support for postgres certificate authentication (#897)
* Refactor main file, add support for postgres certificate authentication

* Fix potential issues.

* Remove legacy linting ignore comment

* Minor cleanup, documentation update
2025-07-12 16:11:50 -04:00
Matthew Kilgore
f4c8dd5450 Prep docs for Cloudflare worker migration (Pages is apparently deprecated/no longer recommended) 2025-07-12 14:56:05 -04:00
Copilot
72033341b4 Fix photo display issue when adding additional attachments to items (#895)
* Initial plan

* Fix attachment display issue - prevent photo primary status loss when updating non-photo attachments

Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>
2025-07-12 13:36:21 -04:00
Matthew Kilgore
e5ba3bb10e Clean up error handling, add uptime to analytics 2025-07-12 11:48:55 -04:00
Copilot
c2cfa10336 Fix nil pointer dereference panic in thumbnail subscription during shutdown (#892)
* Initial plan

* Fix nil pointer dereference in thumbnail subscription handling

Add nil check for msg after subscription.Receive() returns error to prevent
panic when accessing msg.Metadata. When an error occurs or msg is nil,
continue to next iteration instead of trying to process the message.

Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>
2025-07-12 11:40:50 -04:00
Matthew Kilgore
a73d5887c7 Send analytics daily 2025-07-12 11:36:30 -04:00
Balki
850ed476d4 Support listening on unix sockets and systemd sockets (#878) 2025-07-12 09:58:16 -04:00
Ahmosys
adea83d421 fix(frontend/location): preserve parent location when using "Create and Add another" (#879)
* fix(frontend/location): preserve parent in "Create and Add another" modal flow

* fix: normalize line endings

* fix: preserve parent location state when modal closed
2025-07-12 00:08:41 +00:00
Ahmosys
d678c35c57 fix(frontend/scanner): close scanner modal after successful QR code scan (#889)
* fix(frontend/scanner): close scanner modal after successful QR code scan

* fix: linting errors
2025-07-10 17:00:08 -04:00
Matt
d3073b472d Fix rootless 2025-07-10 16:58:23 -04:00
Matt
b274f81dbb Fix broken docker actions 2025-07-10 16:56:50 -04:00
Matt
721e407600 Update docker-publish.yaml 2025-07-10 14:32:12 -04:00
Copilot
ca4aed7bd3 Fix GitHub Actions Docker workflow syntax errors for secrets access (#882)
* Initial plan

* Fix GitHub Actions Docker workflow syntax errors

Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>

* Fix GitHub Actions expression syntax for if conditions

Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>
2025-07-10 14:29:30 -04:00
Weblate
746bd50f24 Translated using Weblate (Slovenian)
Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Murk <saso@workrum.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-07-10 13:52:06 +00:00
Weblate
945a768691 Translated using Weblate (Danish)
Currently translated at 99.7% (491 of 492 strings)

Co-authored-by: Heine Olsen <olsen10051988@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/da/
Translation: Homebox/Frontend
2025-07-10 02:06:57 +00:00
Weblate
27237ae6d3 Translated using Weblate (Danish)
Currently translated at 95.9% (472 of 492 strings)

Co-authored-by: Heine Olsen <olsen10051988@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/da/
Translation: Homebox/Frontend
2025-07-10 00:18:26 +00:00
Ahmed Al Hafoudh
4463867cf0 Pass label param to print command template (#886) 2025-07-09 12:11:16 -04:00
Weblate
95e2fb6a15 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.3% (489 of 492 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 99.3% (489 of 492 strings)

Co-authored-by: Anders Øyvind Urke-Sætre <andersoyvind@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nb_NO/
Translation: Homebox/Frontend
2025-07-09 12:35:25 +00:00
Copilot
e32dd0aaa5 Fix frontend duplicate tag creation in Label Selector (#861)
* Initial plan

* Fix frontend duplicate tag creation issue

Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>
2025-07-09 03:48:46 +00:00
Weblate
ee5c43dc29 Translated using Weblate (French)
Currently translated at 99.3% (489 of 492 strings)

Co-authored-by: buzz <buzz.eclair@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-07-08 20:00:40 +00:00
Matt
17c9685391 Better Copilot tooling 2025-07-07 11:46:41 -04:00
Copilot
fd41065250 Fix warranty section visibility when lifetime warranty is enabled (#875)
* Initial plan

* Fix warranty section visibility when lifetime warranty is enabled

Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>
2025-07-07 11:24:26 -04:00
Weblate
f9b1327507 Translated using Weblate (Slovak)
Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-07-07 14:00:40 +00:00
mcarbonne
5ed0e5c000 fix ghcr repo + disable dockerhub if not provided (#870) 2025-07-06 21:43:07 -04:00
mcarbonne
ce1e58828a Add migration for old sqlite timestamps (#869)
* add migration for old sqlite timestamps

* format python file + add support for negative timezones
2025-07-06 21:42:19 -04:00
Matt
d74508e214 Create .README FIRST.md 2025-07-06 08:26:40 -04:00
Weblate
178e676521 Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/
Translation: Homebox/Frontend
2025-07-06 12:14:50 +00:00
Weblate
c215373458 Translated using Weblate (Vietnamese)
Currently translated at 6.0% (30 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Ng. H. Duyên <huongduyen.work@gmail.com>
Co-authored-by: euforik <euforik22@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/vi/
Translation: Homebox/Frontend
2025-07-05 15:00:40 +00:00
Copilot
82bceb2185 Fix HBOX_LOG_LEVEL environment variable being ignored due to backwards logic (#862)
Co-authored-by: tankerkiller125 <3457368+tankerkiller125@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2025-07-04 23:44:20 -04:00
Matt
be1f3c0ad3 Use aspect ratio when making thumbnails and fix rotation (#857) 2025-07-04 11:44:08 -04:00
Weblate
518d13ccbb Added translation using Weblate (Vietnamese)
Co-authored-by: Ng. H. Duyên <huongduyen.work@gmail.com>
2025-07-04 14:30:49 +00:00
Weblate
8bef7b236b Translated using Weblate (Czech)
Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-07-04 03:20:53 +00:00
Weblate
e774e57bee Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (492 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (492 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: xdjohn99 <jh24cd@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-03 01:16:22 +00:00
Weblate
d6d0d6dc56 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.7% (466 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 94.7% (466 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: xdjohn99 <jh24cd@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-02 23:53:49 +00:00
Weblate
7e0ea5fee5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.3% (464 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 94.3% (464 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: xdjohn99 <jh24cd@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-02 23:50:20 +00:00
Weblate
10dcc1c01d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 92.0% (453 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 92.0% (453 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: xdjohn99 <jh24cd@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-02 23:42:07 +00:00
Weblate
38c37111cf Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 86.5% (426 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 86.5% (426 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: xdjohn99 <jh24cd@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-02 23:21:29 +00:00
Weblate
bf27d147dd Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 77.8% (383 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 77.8% (383 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: xdjohn99 <jh24cd@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-02 23:01:12 +00:00
Weblate
000ccd6d38 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 76.4% (376 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 76.4% (376 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: xdjohn99 <jh24cd@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-02 22:58:12 +00:00
Weblate
f6fc30e218 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 76.0% (374 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 76.0% (374 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: xdjohn99 <jh24cd@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-02 22:57:51 +00:00
Weblate
b444774f9b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 75.8% (373 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-02 22:57:31 +00:00
Weblate
91373dceb8 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 75.6% (372 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 75.6% (372 of 492 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (492 of 492 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Co-authored-by: xdjohn99 <jh24cd@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-02 22:56:25 +00:00
Weblate
ceb1bf89a1 Translated using Weblate (Spanish)
Currently translated at 98.5% (485 of 492 strings)

Translated using Weblate (Spanish)

Currently translated at 98.5% (485 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-07-02 20:12:09 +00:00
Weblate
eb1428d3ac Translated using Weblate (Spanish)
Currently translated at 98.3% (484 of 492 strings)

Translated using Weblate (Spanish)

Currently translated at 98.3% (484 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-07-02 20:11:48 +00:00
Weblate
e4ac7633a5 Translated using Weblate (Norwegian Bokmål)
Currently translated at 98.9% (487 of 492 strings)

Translated using Weblate (Spanish)

Currently translated at 97.9% (482 of 492 strings)

Translated using Weblate (Spanish)

Currently translated at 97.9% (482 of 492 strings)

Translated using Weblate (Swedish)

Currently translated at 68.0% (335 of 492 strings)

Translated using Weblate (Swedish)

Currently translated at 68.0% (335 of 492 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (492 of 492 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Co-authored-by: networked47 <nic.walsh@gmail.com>
Co-authored-by: terhoy <terjeho@hotmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nb_NO/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translation: Homebox/Frontend
2025-07-02 20:10:53 +00:00
Matt
bd604f5867 Update .goreleaser.yaml 2025-07-01 20:36:33 -04:00
Matthew Kilgore
b6b939db40 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	frontend/locales/fr.json
#	frontend/locales/sk-SK.json
#	frontend/locales/sl.json
2025-07-01 19:14:07 -04:00
Matthew Kilgore
d3f56b1b95 Fix version links for all languages 2025-07-01 19:13:52 -04:00
Weblate
a258e1d2bc Translated using Weblate (Slovak)
Currently translated at 99.1% (488 of 492 strings)

Translated using Weblate (Slovenian)

Currently translated at 100.0% (492 of 492 strings)

Translated using Weblate (French)

Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: Telectroboy <telectroboy@hotmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-07-01 23:13:32 +00:00
Stanley Jochman
5ca671a4ab fix: footer release link points to wrong link (#830) 2025-07-01 19:13:15 -04:00
Matthew Kilgore
ccdab8bac1 Fix attachments get method 2025-07-01 19:03:24 -04:00
Matt
0d2a6d6ac8 Revert weblate skipping 2025-07-01 10:09:40 -04:00
Matt
e159dd8a0b Merge commit from fork 2025-07-01 09:56:34 -04:00
Matt
b311a5c9ed Update CreateModal.vue 2025-07-01 08:53:12 -04:00
Matthew Kilgore
04c8e38ecf Escape file name for content-disposition. 2025-06-30 20:55:11 -04:00
Matthew Kilgore
1fd2f42282 Hopefully fixed ARMv7 Rootless build 2025-06-30 20:44:20 -04:00
Matthew Kilgore
d3cff18cc6 Ignore weblate for builds 2025-06-30 20:21:53 -04:00
Weblate
3e27c24fbd Translated using Weblate (Japanese)
Currently translated at 59.9% (295 of 492 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 96.5% (475 of 492 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 66.2% (326 of 492 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 74.5% (367 of 492 strings)

Translated using Weblate (German)

Currently translated at 97.7% (481 of 492 strings)

Translated using Weblate (English)

Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_PT/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-07-01 00:17:05 +00:00
Weblate
acd5acd4cf Translated using Weblate (Slovak)
Currently translated at 98.7% (486 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 23:57:40 +00:00
Weblate
71dc5fcb23 Translated using Weblate (Slovak)
Currently translated at 98.5% (485 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:45:18 +00:00
Weblate
2ff5f4ca0b Translated using Weblate (Slovak)
Currently translated at 91.0% (448 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 91.0% (448 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:27:53 +00:00
Weblate
12831a40d0 Translated using Weblate (Slovak)
Currently translated at 88.6% (436 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 88.6% (436 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:25:38 +00:00
Weblate
c966090889 Translated using Weblate (Slovak)
Currently translated at 87.3% (430 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 87.3% (430 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:24:27 +00:00
Weblate
f03eb637a7 Translated using Weblate (Slovak)
Currently translated at 85.1% (419 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 85.1% (419 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:22:40 +00:00
Weblate
49ea34f352 Translated using Weblate (Slovak)
Currently translated at 83.7% (412 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 83.7% (412 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:21:36 +00:00
Weblate
85d91667eb Translated using Weblate (Slovak)
Currently translated at 81.3% (400 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 81.3% (400 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:14:34 +00:00
Weblate
458554b6e1 Translated using Weblate (Slovak)
Currently translated at 78.2% (385 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 78.2% (385 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:05:37 +00:00
Weblate
79ff5cedc6 Translated using Weblate (Slovak)
Currently translated at 77.6% (382 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 77.6% (382 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:05:00 +00:00
Weblate
f0008abd04 Translated using Weblate (Slovak)
Currently translated at 77.4% (381 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 77.4% (381 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:04:12 +00:00
Weblate
8a377b3e4d Translated using Weblate (Slovak)
Currently translated at 77.2% (380 of 492 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 20:03:44 +00:00
Weblate
e7d31722f7 Translated using Weblate (Slovak)
Currently translated at 77.0% (379 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 77.0% (379 of 492 strings)

Translated using Weblate (German)

Currently translated at 99.3% (489 of 492 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Daniel Galle <smarthome@galle-fw.com>
Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-30 17:00:40 +00:00
Matthew Kilgore
52b4506e12 Fix docker builds 2025-06-29 20:44:20 -04:00
Matthew Kilgore
cb9631c999 Try this to fix the build? (More like the original) 2025-06-29 20:28:35 -04:00
Matthew Kilgore
6e3186a9de Merge remote-tracking branch 'origin/main' 2025-06-29 20:08:54 -04:00
Matthew Kilgore
a67070f965 Hopefully fix build 2025-06-29 20:08:43 -04:00
Matthew Kilgore
c61c54600d Add goreleaser added dependencies? 2025-06-29 14:29:23 -04:00
Matthew Kilgore
16dbada31a Update golang version in github actions 2025-06-29 14:02:47 -04:00
Weblate
df8b27d9a6 Translated using Weblate (Slovak)
Currently translated at 68.2% (336 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 68.2% (336 of 492 strings)

Translated using Weblate (Slovak)

Currently translated at 68.2% (336 of 492 strings)

Co-authored-by: Jose Riha <jose1711@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-06-29 16:43:10 +00:00
Matt
f30c9d9156 fix: foreign key issue with thumbnails (#824) 2025-06-29 12:24:22 -04:00
Weblate
d83767f4c2 Translated using Weblate (Czech)
Currently translated at 100.0% (492 of 492 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-06-29 00:55:20 +00:00
zebrapurring
0b75dbf888 fix: set page size to 24 in order to always display full rows of items (#810)
* fix: set page size to 24 in order to always display full rows of items

* feat: remove 2xl option for items

---------

Co-authored-by: zebrapurring <>
Co-authored-by: Tonya <tonya@tokia.dev>
2025-06-28 23:10:44 +00:00
Nikolai Oakfield
c9d055fe03 Prevent self-referencing locations and items as parents (#773)
* prevent current location and descendants from being selected as parent

* prevent an item from showing up in the parent items drop-down for itself

* pass location object to filter function to allow for more flexible filtering

* align exclude prop and fix type comparison, change item filter to array of ItemsObjects to allow for descendant filtering in future

* fix linting prop reference
2025-06-28 22:58:46 +00:00
zebrapurring
c1c8eb649c fix: display all item labels in the element card (#809)
Co-authored-by: zebrapurring <>
2025-06-28 22:58:34 +00:00
Crumbowl
97bfb2d470 Add --no-fork to prevent slow and hanging UI (#817) 2025-06-27 13:11:21 -04:00
Weblate
5d1b023d19 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 75.2% (370 of 492 strings)

Co-authored-by: Jixing Tang <jasontang1992@163.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-06-27 15:00:40 +00:00
Matt
4861a8537f More image type support for thumbnails (#814) 2025-06-26 10:19:34 -04:00
Weblate
09cccc63a7 Translated using Weblate (Norwegian Bokmål)
Currently translated at 99.7% (491 of 492 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (492 of 492 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (492 of 492 strings)

Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: yngveskog <yngve.skog@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nb_NO/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-06-25 11:55:11 +00:00
Michael Manganiello
230294ebb6 feat: Display number of items in Location/Label page (#805)
* feat: Display number of items in Location/Label page

When viewing a Location or Label page, the number of items directly
associated with that Location or Label is now displayed in the section
header.

* style: adjust the style on the item count

---------

Co-authored-by: Tonya <tonya@tokia.dev>
2025-06-25 03:24:34 +00:00
Weblate
d97bfb95e1 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (492 of 492 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (492 of 492 strings)

Translated using Weblate (Slovenian)

Currently translated at 99.1% (488 of 492 strings)

Translated using Weblate (French)

Currently translated at 97.7% (481 of 492 strings)

Translated using Weblate (English)

Currently translated at 97.5% (480 of 492 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Stephen Bennett <bennett18@gmail.com>
Co-authored-by: buzz <buzz.eclair@gmail.com>
Co-authored-by: terhoy <terjeho@hotmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nb_NO/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-24 15:01:03 +00:00
Weblate
8577273064 Translated using Weblate (Norwegian Bokmål)
Currently translated at 95.9% (472 of 492 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 95.9% (472 of 492 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 95.9% (472 of 492 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 79.4% (386 of 486 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 79.4% (386 of 486 strings)

Translated using Weblate (German)

Currently translated at 100.0% (486 of 486 strings)

Translated using Weblate (German)

Currently translated at 100.0% (486 of 486 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Sebastian <homeboxtranslate@sschefold.de>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: terhoy <terjeho@hotmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nb_NO/
Translation: Homebox/Frontend
2025-06-23 15:37:16 +00:00
Tonya
ef39549c37 Custom Colored Labels (#801)
* feat: custom coloured labels

* chore: lint

* feat: add ColorSelector component for improved color selection in labels and integrate it into CreateModal and Selector components

* style: lint

* fix: update ColorSelector and Selector components to use empty string instead of null for default color values for types
2025-06-23 15:52:32 +01:00
dependabot[bot]
2afa5d1374 Bump github.com/go-chi/chi/v5 (#799)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-22 21:51:56 -04:00
Matt
989100d299 Thumbnails (#797)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: tonya <tonya@tokia.dev>
2025-06-22 21:32:48 -04:00
Michael Manganiello
8493ec0c90 fix: Table sorting for ID and date columns (#802)
The usage of `parseFloat` was breaking the sorting of ID and date
columns in the table.

This is because `parseFloat("000-123")` returns `0` instead of `123` or
`NaN`, and `parseFloat("2025-01-02T03:04:05.678Z")` returns `2025`.

Replacing `parseFloat` with `Number` fixes the issue, as now the values
received for Asset ID and date columns will correctly return `NaN`, and
end up being sorted as strings.
2025-06-22 23:45:33 +00:00
Michael Manganiello
c53cefe6cb fix: Add page title for Label and Location pages (#803)
When accessing a specific label or location, the page title is now set
to the name of that label or location.

The issue was more notorious when opening these pages in new tabs, which
didn't inherit the title from the previous page, resulting in a
title with the raw page URL.
2025-06-22 23:39:37 +00:00
marcofenoglio
e664dfcfbd Corrected Single quote (#798) 2025-06-20 11:23:44 -04:00
Matt
e1b232e0d1 Abstract Attachment Storage (#777)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-06-19 10:26:12 -04:00
Weblate
799c36ec3b Translated using Weblate (Swedish)
Currently translated at 68.8% (331 of 481 strings)

Co-authored-by: networked47 <nic.walsh@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translation: Homebox/Frontend
2025-06-18 11:28:07 +00:00
Weblate
f3eebbaca0 Translated using Weblate (Dutch)
Currently translated at 100.0% (481 of 481 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (481 of 481 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (481 of 481 strings)

Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-06-16 20:35:29 +00:00
Weblate
73ca64f41c Translated using Weblate (Dutch)
Currently translated at 86.0% (414 of 481 strings)

Translated using Weblate (Dutch)

Currently translated at 86.0% (414 of 481 strings)

Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-06-16 19:54:42 +00:00
Weblate
354a3ae5c0 Translated using Weblate (Slovenian)
Currently translated at 99.3% (478 of 481 strings)

Translated using Weblate (Dutch)

Currently translated at 84.4% (406 of 481 strings)

Translated using Weblate (Dutch)

Currently translated at 84.4% (406 of 481 strings)

Translated using Weblate (Dutch)

Currently translated at 84.4% (406 of 481 strings)

Co-authored-by: 101br03k <warmerdamm03@gmail.com>
Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 19:51:19 +00:00
Weblate
f7e1e77e07 Translated using Weblate (Slovenian)
Currently translated at 94.1% (453 of 481 strings)

Translated using Weblate (Dutch)

Currently translated at 69.6% (335 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:59:21 +00:00
Weblate
12d3bdb6e6 Translated using Weblate (Slovenian)
Currently translated at 89.8% (432 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 89.8% (432 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:48:11 +00:00
Weblate
2a59c8200e Translated using Weblate (Slovenian)
Currently translated at 88.5% (426 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 88.5% (426 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:46:40 +00:00
Weblate
5e47ffd724 Translated using Weblate (Slovenian)
Currently translated at 87.3% (420 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 87.3% (420 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:45:11 +00:00
Weblate
5b7e0e4eee Translated using Weblate (Slovenian)
Currently translated at 85.0% (409 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 85.0% (409 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:41:48 +00:00
Weblate
74f51bd8a0 Translated using Weblate (Slovenian)
Currently translated at 84.1% (405 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 84.1% (405 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:40:27 +00:00
Weblate
ca1e651f8b Translated using Weblate (Slovenian)
Currently translated at 83.9% (404 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 83.9% (404 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:39:54 +00:00
Weblate
8b12bbd81d Translated using Weblate (Slovenian)
Currently translated at 83.5% (402 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 83.5% (402 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:37:22 +00:00
Weblate
70bccfef1f Translated using Weblate (Slovenian)
Currently translated at 83.3% (401 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 83.3% (401 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:37:08 +00:00
Weblate
423d20909b Translated using Weblate (Slovenian)
Currently translated at 82.3% (396 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 82.3% (396 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:34:03 +00:00
Weblate
523ad873e4 Translated using Weblate (Slovenian)
Currently translated at 80.4% (387 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 80.4% (387 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:22:43 +00:00
Weblate
ad51cb48b8 Translated using Weblate (Slovenian)
Currently translated at 80.0% (385 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 80.0% (385 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:22:24 +00:00
Weblate
5c594a10d4 Translated using Weblate (Slovenian)
Currently translated at 77.7% (374 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 77.7% (374 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:16:26 +00:00
Weblate
497cfcc3f5 Translated using Weblate (Slovenian)
Currently translated at 75.2% (362 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 75.2% (362 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:12:55 +00:00
Weblate
2f61c68981 Translated using Weblate (Slovenian)
Currently translated at 74.8% (360 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 74.8% (360 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:11:29 +00:00
Weblate
d7bd1bcfa8 Translated using Weblate (Slovenian)
Currently translated at 72.7% (350 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 72.7% (350 of 481 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-06-16 14:07:53 +00:00
Weblate
fde4660bba Translated using Weblate (Bosnian)
Currently translated at 14.3% (69 of 481 strings)

Translated using Weblate (Lithuanian)

Currently translated at 10.8% (52 of 481 strings)

Translated using Weblate (Luxembourgish)

Currently translated at 0.0% (0 of 481 strings)

Translated using Weblate (Albanian)

Currently translated at 19.5% (94 of 481 strings)

Translated using Weblate (Albanian)

Currently translated at 19.5% (94 of 481 strings)

Translated using Weblate (Tamil)

Currently translated at 1.4% (7 of 481 strings)

Translated using Weblate (Tamil)

Currently translated at 1.4% (7 of 481 strings)

Translated using Weblate (Korean)

Currently translated at 6.4% (31 of 481 strings)

Translated using Weblate (Korean)

Currently translated at 6.4% (31 of 481 strings)

Translated using Weblate (Indonesian)

Currently translated at 58.6% (282 of 481 strings)

Translated using Weblate (Indonesian)

Currently translated at 58.6% (282 of 481 strings)

Translated using Weblate (Thai)

Currently translated at 22.6% (109 of 481 strings)

Translated using Weblate (Thai)

Currently translated at 22.6% (109 of 481 strings)

Translated using Weblate (Thai)

Currently translated at 22.6% (109 of 481 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 59.4% (286 of 481 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 59.4% (286 of 481 strings)

Translated using Weblate (Slovak)

Currently translated at 64.8% (312 of 481 strings)

Translated using Weblate (Slovak)

Currently translated at 64.8% (312 of 481 strings)

Translated using Weblate (Danish)

Currently translated at 63.6% (306 of 481 strings)

Translated using Weblate (Danish)

Currently translated at 63.6% (306 of 481 strings)

Translated using Weblate (Romanian)

Currently translated at 58.4% (281 of 481 strings)

Translated using Weblate (Romanian)

Currently translated at 58.4% (281 of 481 strings)

Translated using Weblate (Romanian)

Currently translated at 58.4% (281 of 481 strings)

Translated using Weblate (Finnish)

Currently translated at 67.5% (325 of 481 strings)

Translated using Weblate (Japanese)

Currently translated at 61.3% (295 of 481 strings)

Translated using Weblate (Japanese)

Currently translated at 61.3% (295 of 481 strings)

Translated using Weblate (Ukrainian)

Currently translated at 67.5% (325 of 481 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 99.7% (480 of 481 strings)

Translated using Weblate (Chinese (Simplified) (zh_MO))

Currently translated at 38.0% (183 of 481 strings)

Translated using Weblate (Chinese (Simplified) (zh_MO))

Currently translated at 38.0% (183 of 481 strings)

Translated using Weblate (Chinese (Traditional Han script, Hong Kong))

Currently translated at 18.2% (88 of 481 strings)

Translated using Weblate (Chinese (Traditional Han script, Hong Kong))

Currently translated at 18.2% (88 of 481 strings)

Translated using Weblate (Chinese (Traditional Han script, Hong Kong))

Currently translated at 18.2% (88 of 481 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 67.9% (327 of 481 strings)

Translated using Weblate (Hungarian)

Currently translated at 68.8% (331 of 481 strings)

Translated using Weblate (Polish)

Currently translated at 67.3% (324 of 481 strings)

Translated using Weblate (Catalan)

Currently translated at 57.3% (276 of 481 strings)

Translated using Weblate (Catalan)

Currently translated at 57.3% (276 of 481 strings)

Translated using Weblate (Catalan)

Currently translated at 57.3% (276 of 481 strings)

Translated using Weblate (Slovenian)

Currently translated at 69.4% (334 of 481 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 70.8% (341 of 481 strings)

Translated using Weblate (Russian)

Currently translated at 59.4% (286 of 481 strings)

Translated using Weblate (Russian)

Currently translated at 59.4% (286 of 481 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 25.7% (124 of 481 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 25.7% (124 of 481 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 25.7% (124 of 481 strings)

Translated using Weblate (Swedish)

Currently translated at 67.3% (324 of 481 strings)

Translated using Weblate (Turkish)

Currently translated at 64.4% (310 of 481 strings)

Translated using Weblate (Turkish)

Currently translated at 64.4% (310 of 481 strings)

Translated using Weblate (Turkish)

Currently translated at 64.4% (310 of 481 strings)

Translated using Weblate (French)

Currently translated at 99.7% (480 of 481 strings)

Translated using Weblate (German)

Currently translated at 99.7% (480 of 481 strings)

Translated using Weblate (Italian)

Currently translated at 83.9% (404 of 481 strings)

Translated using Weblate (Dutch)

Currently translated at 69.4% (334 of 481 strings)

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Co-authored-by: stegl <primsteg@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/bs/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ca/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/da/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fi/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ko/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/lb/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/lt/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nb_NO/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_PT/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ro/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ru/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sq/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ta/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/th/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/tr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/uk/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hant/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hant_HK/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_MO/
Translation: Homebox/Frontend
2025-06-16 13:00:16 +00:00
Weblate
e1d625ae80 Translated using Weblate (Spanish)
Currently translated at 100.0% (481 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (481 of 481 strings)

Co-authored-by: Daniel Barea <dbarelop@gmail.com>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 12:58:48 +00:00
Weblate
1bb80f5537 Translated using Weblate (Spanish)
Currently translated at 100.0% (481 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (481 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 12:24:55 +00:00
Weblate
d3220d2862 Translated using Weblate (Spanish)
Currently translated at 99.5% (479 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:52:08 +00:00
Weblate
761d1660b4 Translated using Weblate (Spanish)
Currently translated at 99.3% (478 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 99.3% (478 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:51:41 +00:00
Weblate
19300d1b37 Translated using Weblate (Spanish)
Currently translated at 99.1% (477 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 99.1% (477 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:51:28 +00:00
Weblate
5aca7e2f62 Translated using Weblate (Spanish)
Currently translated at 98.9% (476 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 98.9% (476 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:51:05 +00:00
Weblate
475a1bbf39 Translated using Weblate (Spanish)
Currently translated at 98.7% (475 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 98.7% (475 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:50:42 +00:00
Weblate
2eafbb216e Translated using Weblate (Spanish)
Currently translated at 98.5% (474 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:49:53 +00:00
Weblate
3d66f4bb89 Translated using Weblate (Spanish)
Currently translated at 98.3% (473 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 98.3% (473 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 98.3% (473 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:49:21 +00:00
Weblate
021e4a39cf Translated using Weblate (Spanish)
Currently translated at 97.7% (470 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 97.7% (470 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:46:43 +00:00
Weblate
62a4086776 Translated using Weblate (Spanish)
Currently translated at 96.0% (462 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 96.0% (462 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:30:18 +00:00
Weblate
a04ae3c59a Translated using Weblate (Spanish)
Currently translated at 95.6% (460 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 95.6% (460 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:29:48 +00:00
Weblate
645ea4b1b5 Translated using Weblate (Spanish)
Currently translated at 95.4% (459 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 95.4% (459 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:29:38 +00:00
Weblate
1c4530cedd Translated using Weblate (Spanish)
Currently translated at 95.2% (458 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 95.2% (458 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:29:22 +00:00
Weblate
daacdc452d Translated using Weblate (Spanish)
Currently translated at 95.0% (457 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 95.0% (457 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:29:13 +00:00
Weblate
eb400c437f Translated using Weblate (Spanish)
Currently translated at 94.1% (453 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 94.1% (453 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:22:15 +00:00
Weblate
9160deb9b1 Translated using Weblate (Spanish)
Currently translated at 93.1% (448 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 93.1% (448 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:21:10 +00:00
Weblate
52f977497f Translated using Weblate (Spanish)
Currently translated at 92.9% (447 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 92.9% (447 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:20:53 +00:00
Weblate
be0493f5b5 Translated using Weblate (Spanish)
Currently translated at 91.4% (440 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 91.4% (440 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:19:40 +00:00
Weblate
28a47dce09 Translated using Weblate (Spanish)
Currently translated at 90.6% (436 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 90.6% (436 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:18:08 +00:00
Weblate
2b7ed6ff94 Translated using Weblate (Spanish)
Currently translated at 90.2% (434 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 90.2% (434 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:16:28 +00:00
Weblate
ac006c7a5f Translated using Weblate (Spanish)
Currently translated at 89.6% (431 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 89.6% (431 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:14:40 +00:00
Weblate
5c8a7918fa Translated using Weblate (Spanish)
Currently translated at 88.9% (428 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 88.9% (428 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:14:18 +00:00
Weblate
ec97ad6de1 Translated using Weblate (Spanish)
Currently translated at 88.7% (427 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 88.7% (427 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:13:43 +00:00
Weblate
a7b0fb3b79 Translated using Weblate (Spanish)
Currently translated at 87.7% (422 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 87.7% (422 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:13:10 +00:00
Weblate
d0e07e3d94 Translated using Weblate (Spanish)
Currently translated at 87.5% (421 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 87.5% (421 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:12:39 +00:00
Weblate
8631fa01e4 Translated using Weblate (Spanish)
Currently translated at 87.3% (420 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 87.3% (420 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:11:41 +00:00
Weblate
b2f77d4700 Translated using Weblate (Spanish)
Currently translated at 86.6% (417 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 86.6% (417 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:11:08 +00:00
Weblate
fdc909fd33 Translated using Weblate (Spanish)
Currently translated at 86.4% (416 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 86.4% (416 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:10:59 +00:00
Weblate
e5247cbc3d Translated using Weblate (Spanish)
Currently translated at 86.0% (414 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 86.0% (414 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:10:39 +00:00
Weblate
e122f6f422 Translated using Weblate (Spanish)
Currently translated at 84.6% (407 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 84.6% (407 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:08:05 +00:00
Weblate
024e23519a Translated using Weblate (Spanish)
Currently translated at 84.1% (405 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:07:35 +00:00
Weblate
6f73433112 Translated using Weblate (Spanish)
Currently translated at 83.9% (404 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 83.9% (404 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:07:05 +00:00
Weblate
3471098f75 Translated using Weblate (Spanish)
Currently translated at 83.7% (403 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 83.7% (403 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:06:33 +00:00
Weblate
42d61dcc9d Translated using Weblate (Spanish)
Currently translated at 83.5% (402 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 83.5% (402 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:06:03 +00:00
Weblate
ccc5509b15 Translated using Weblate (Spanish)
Currently translated at 82.5% (397 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 82.5% (397 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:04:31 +00:00
Weblate
73f772b2ea Translated using Weblate (Spanish)
Currently translated at 82.1% (395 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 82.1% (395 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:03:47 +00:00
Weblate
a5e3fe57e1 Translated using Weblate (Spanish)
Currently translated at 81.9% (394 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 81.9% (394 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:03:27 +00:00
Weblate
d90081a1e1 Translated using Weblate (Spanish)
Currently translated at 81.7% (393 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 81.7% (393 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 11:03:11 +00:00
Weblate
3633d4ba2d Translated using Weblate (Spanish)
Currently translated at 80.4% (387 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 80.4% (387 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:53:32 +00:00
Weblate
463f271732 Translated using Weblate (Spanish)
Currently translated at 80.2% (386 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 80.2% (386 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:53:12 +00:00
Weblate
1977596a63 Translated using Weblate (Spanish)
Currently translated at 79.8% (384 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 79.8% (384 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:51:51 +00:00
Weblate
1e90ba65f9 Translated using Weblate (Spanish)
Currently translated at 79.6% (383 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 79.6% (383 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:50:06 +00:00
Weblate
414359fc19 Translated using Weblate (Spanish)
Currently translated at 78.7% (379 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 78.7% (379 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:40:44 +00:00
Weblate
a90d40b26d Translated using Weblate (Spanish)
Currently translated at 78.3% (377 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 78.3% (377 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:39:16 +00:00
Weblate
17a658567a Translated using Weblate (Spanish)
Currently translated at 77.7% (374 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 77.7% (374 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:38:49 +00:00
Weblate
9932a7b5fd Translated using Weblate (Spanish)
Currently translated at 77.1% (371 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 77.1% (371 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:37:48 +00:00
Weblate
6388c0acce Translated using Weblate (Spanish)
Currently translated at 76.9% (370 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 76.9% (370 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:36:40 +00:00
Weblate
b96693ecde Translated using Weblate (Spanish)
Currently translated at 76.7% (369 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 76.7% (369 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:36:20 +00:00
Weblate
860fac28b7 Translated using Weblate (Spanish)
Currently translated at 76.2% (367 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 76.2% (367 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:35:58 +00:00
Weblate
dafcf3b8e4 Translated using Weblate (Spanish)
Currently translated at 76.0% (366 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 76.0% (366 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:35:41 +00:00
Weblate
90e2505941 Translated using Weblate (Spanish)
Currently translated at 75.2% (362 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 75.2% (362 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:34:50 +00:00
Weblate
c76cb13ec5 Translated using Weblate (Spanish)
Currently translated at 75.0% (361 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 75.0% (361 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:34:36 +00:00
Weblate
e825f4ea71 Translated using Weblate (Spanish)
Currently translated at 74.4% (358 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 74.4% (358 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:33:36 +00:00
Weblate
4157e47660 Translated using Weblate (Spanish)
Currently translated at 73.5% (354 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 73.5% (354 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-16 10:32:28 +00:00
Weblate
1b84bf7d2c Translated using Weblate (Spanish)
Currently translated at 73.1% (352 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 73.1% (352 of 481 strings)

Translated using Weblate (Italian)

Currently translated at 83.9% (404 of 481 strings)

Translated using Weblate (Italian)

Currently translated at 83.9% (404 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-06-16 10:12:21 +00:00
Weblate
9f77b98f4b Translated using Weblate (Czech)
Currently translated at 100.0% (481 of 481 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-06-15 13:00:40 +00:00
Weblate
f71ccb76a0 Translated using Weblate (Spanish)
Currently translated at 71.7% (345 of 481 strings)

Co-authored-by: j richardson <jrichocean@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-14 00:00:40 +00:00
Weblate
1e136ef41d Translated using Weblate (Spanish)
Currently translated at 71.7% (345 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 71.7% (345 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: j richardson <jrichocean@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-13 20:00:20 +00:00
Weblate
bb5fb34114 Translated using Weblate (Spanish)
Currently translated at 71.5% (344 of 481 strings)

Translated using Weblate (Spanish)

Currently translated at 71.5% (344 of 481 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: j richardson <jrichocean@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-06-13 19:56:03 +00:00
Tonya
f16ad427eb Fix small bugs in UI (#786)
* chore: added `rel="noopener noreferrer"` to external links for improved security on homepage

* fix: reused variable name

* feat: make the item table use a link instead of a click event

* fix: pagination now shows correct page if loading page that isnt 1

* fix: make save button sticky again on item edit page

* fix: adjust sticky header positioning based on whether legacy header is enabled

* fix: navigate to homepage on unauthorized request in useUserApi function

* fix: enhance link handling in DetailsSection

* fix: improve markdown rendering, don't add big breaks between lines, make the gap smaller and dont have a trailing newline

* fix: use secondary colour as switch secondary colour so its more visible against bg

* fix: call refresh methods on location and label stores during component mount for better data consistency

* fix: loading indicators

* fix: convert detail.text to string for correct URL handling in DetailsSection component

* fix: use replace instead of splice to remove newline at end of markdown

* fix: use css vars for header height
2025-06-13 09:29:33 +01:00
Weblate
1ac688f08d Translated using Weblate (French)
Currently translated at 100.0% (480 of 480 strings)

Translated using Weblate (French)

Currently translated at 100.0% (480 of 480 strings)

Translated using Weblate (French)

Currently translated at 100.0% (480 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 15:00:40 +00:00
Weblate
9a5c798346 Translated using Weblate (French)
Currently translated at 96.4% (463 of 480 strings)

Translated using Weblate (French)

Currently translated at 96.4% (463 of 480 strings)

Translated using Weblate (French)

Currently translated at 96.4% (463 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 10:23:24 +00:00
Weblate
364599e6ac Translated using Weblate (French)
Currently translated at 95.0% (456 of 480 strings)

Translated using Weblate (French)

Currently translated at 95.0% (456 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 10:21:48 +00:00
Weblate
a6d03e37aa Translated using Weblate (French)
Currently translated at 89.3% (429 of 480 strings)

Translated using Weblate (French)

Currently translated at 89.3% (429 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 09:58:33 +00:00
Weblate
3d7146582b Translated using Weblate (French)
Currently translated at 87.0% (418 of 480 strings)

Translated using Weblate (French)

Currently translated at 87.0% (418 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 09:54:36 +00:00
Weblate
477b7b9eda Translated using Weblate (French)
Currently translated at 82.7% (397 of 480 strings)

Translated using Weblate (French)

Currently translated at 82.7% (397 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 09:47:43 +00:00
Weblate
b4184db27b Translated using Weblate (French)
Currently translated at 79.7% (383 of 480 strings)

Translated using Weblate (French)

Currently translated at 79.7% (383 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 09:32:17 +00:00
Weblate
52e375e680 Translated using Weblate (French)
Currently translated at 79.3% (381 of 480 strings)

Translated using Weblate (French)

Currently translated at 79.3% (381 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 09:31:10 +00:00
Weblate
3839ced4fe Translated using Weblate (French)
Currently translated at 78.9% (379 of 480 strings)

Translated using Weblate (French)

Currently translated at 78.9% (379 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 09:30:38 +00:00
Weblate
e1e4b72f94 Translated using Weblate (French)
Currently translated at 73.1% (351 of 480 strings)

Translated using Weblate (French)

Currently translated at 73.1% (351 of 480 strings)

Co-authored-by: Lucas Placentino <23436953+LucasPlacentino@users.noreply.github.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-06-11 09:13:29 +00:00
Weblate
7c42130c46 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 71.0% (341 of 480 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 71.0% (341 of 480 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: WilliamStark <yujinghao007@163.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-06-10 12:00:40 +00:00
LunarEclipse363
04df4d8a08 Fixed labelmaker pagination on PostgreSQL (#779)
Fixes #753
2025-06-09 15:23:56 -04:00
Matthew Kilgore
1d3d7b4788 Revert "fix: Uploads, downloads, etc. now work properly."
This reverts commit c02b77c3fd.
2025-06-07 12:43:39 -04:00
Matthew Kilgore
d65368b20c Merge remote-tracking branch 'origin/main' 2025-06-07 12:41:11 -04:00
Matthew Kilgore
c02b77c3fd fix: Uploads, downloads, etc. now work properly. 2025-06-07 12:40:59 -04:00
Michael Manganiello
e955183dc1 fix: Show item Purchase and Sold sections when date is set (#769)
Consider the case where an item has a purchase or sold date set, but no
other details, and display the sections in this case.

Fixes #759.
2025-06-05 21:35:53 +00:00
Matt Kilgore
f000e14f07 Update passwords to use Argon2ID (#695)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-06-05 10:19:05 -04:00
Michael Manganiello
4988c22250 feat: Add table column for Asset ID (#766)
Include a new `Asset ID` column in the item view table, disabled by
default.
2025-06-05 10:40:47 +01:00
Weblate
9db59d3822 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (480 of 480 strings)

Co-authored-by: FilipeAb <filipe_abreu@live.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_PT/
Translation: Homebox/Frontend
2025-06-04 14:23:13 +00:00
Matt Kilgore
676b87d87e Fix #763
See https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/capture
2025-06-03 19:54:43 -04:00
Weblate
329a8d8741 Translated using Weblate (Portuguese (Portugal))
Currently translated at 55.4% (266 of 480 strings)

Co-authored-by: Luís Alves <luisalvesw@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_PT/
Translation: Homebox/Frontend
2025-06-02 18:00:40 +00:00
Weblate
7f1ea60e54 Translated using Weblate (Korean)
Currently translated at 6.4% (31 of 480 strings)

Translated using Weblate (Korean)

Currently translated at 6.4% (31 of 480 strings)

Co-authored-by: Jihyeon Gim <potatogim@potatogim.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ko/
Translation: Homebox/Frontend
2025-05-31 18:00:40 +00:00
Weblate
14c6e2672e Translated using Weblate (Catalan)
Currently translated at 57.5% (276 of 480 strings)

Translated using Weblate (Catalan)

Currently translated at 57.5% (276 of 480 strings)

Translated using Weblate (Catalan)

Currently translated at 57.5% (276 of 480 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: YamiGhor <yamighor@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ca/
Translation: Homebox/Frontend
2025-05-30 20:00:40 +00:00
Weblate
2f3f13b4b1 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 25.8% (124 of 480 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 25.8% (124 of 480 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 25.8% (124 of 480 strings)

Translated using Weblate (German)

Currently translated at 100.0% (480 of 480 strings)

Translated using Weblate (German)

Currently translated at 100.0% (480 of 480 strings)

Co-authored-by: Horst Späht <tnqazaa3@anonaddy.me>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: TonySu <susu2721404@gmail.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: tikoe29 <tikoe@koeppen.cc>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hant/
Translation: Homebox/Frontend
2025-05-30 14:00:40 +00:00
Weblate
f06ad96b35 Translated using Weblate (German)
Currently translated at 90.0% (432 of 480 strings)

Co-authored-by: Horst Späht <tnqazaa3@anonaddy.me>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-05-30 09:24:27 +00:00
Weblate
7038d57576 Translated using Weblate (German)
Currently translated at 90.0% (432 of 480 strings)

Translated using Weblate (German)

Currently translated at 90.0% (432 of 480 strings)

Co-authored-by: Horst Späht <tnqazaa3@anonaddy.me>
Co-authored-by: tikoe29 <tikoe@koeppen.cc>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-05-30 09:23:57 +00:00
Weblate
05c11c1c57 Translated using Weblate (German)
Currently translated at 86.2% (414 of 480 strings)

Translated using Weblate (German)

Currently translated at 86.2% (414 of 480 strings)

Translated using Weblate (German)

Currently translated at 86.2% (414 of 480 strings)

Co-authored-by: Horst Späht <tnqazaa3@anonaddy.me>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: tikoe29 <tikoe@koeppen.cc>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-05-30 09:19:59 +00:00
Weblate
b073b578bd Translated using Weblate (Czech)
Currently translated at 100.0% (480 of 480 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (480 of 480 strings)

Translated using Weblate (Catalan)

Currently translated at 56.8% (273 of 480 strings)

Translated using Weblate (Catalan)

Currently translated at 56.8% (273 of 480 strings)

Translated using Weblate (German)

Currently translated at 78.3% (376 of 480 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: YamiGhor <yamighor@gmail.com>
Co-authored-by: tikoe29 <tikoe@koeppen.cc>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ca/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-05-29 23:00:40 +00:00
Weblate
8db96b1f6e Translated using Weblate (Czech)
Currently translated at 75.2% (361 of 480 strings)

Translated using Weblate (Czech)

Currently translated at 75.2% (361 of 480 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-05-29 18:09:53 +00:00
Weblate
74cefafdb7 Translated using Weblate (Czech)
Currently translated at 70.6% (339 of 480 strings)

Translated using Weblate (English)

Currently translated at 100.0% (480 of 480 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translation: Homebox/Frontend
2025-05-29 18:00:40 +00:00
Nikolai Oakfield
3a4fae5eb8 Fix untranslated strings (#756)
* add missing translations and translate page titles

* fix: actually use the declared localized variables

* lint and prettier fixes

* add missing translations for toasts and confirms

* use components for shift/enter keys, add pluralization for photos, and fix primary photo conditional

* remove prop defaults since we're computing these anyways
2025-05-29 12:56:30 +00:00
tonya
e6f7397b30 feat: use dynamic view height for better mobile height 2025-05-29 09:39:38 +00:00
Weblate
6a4e47c617 Translated using Weblate (Czech)
Currently translated at 99.4% (332 of 334 strings)

Translated using Weblate (French)

Currently translated at 99.7% (333 of 334 strings)

Co-authored-by: Nikolai Oakfield <44122708+nikolaioak@users.noreply.github.com>
Co-authored-by: buzz <buzz.eclair@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-05-27 01:00:40 +00:00
Matthew Kilgore
c666fcab3d Actually enable devcache cleanup 2025-05-26 19:25:57 -04:00
Matthew Kilgore
9fac590100 Maybe the cleanup is fixed? 2025-05-26 18:11:48 -04:00
Matthew Kilgore
89fef7199f Maybe the cleanup is fixed? 2025-05-26 18:08:37 -04:00
Matthew Kilgore
3f6fa02ea7 Maybe the cleanup is fixed? 2025-05-26 18:07:02 -04:00
Matthew Kilgore
05c43b949e Maybe the cleanup is fixed? 2025-05-26 18:02:27 -04:00
Matthew Kilgore
ceb1272700 Maybe the cleanup is fixed? 2025-05-26 17:48:52 -04:00
Matthew Kilgore
636b849397 Maybe the cleanup is fixed? 2025-05-26 17:46:48 -04:00
Weblate
1234125bcd Translated using Weblate (Slovenian)
Currently translated at 100.0% (334 of 334 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (334 of 334 strings)

Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: Murk <saso@workrum.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-05-26 17:00:39 +00:00
Weblate
2acfdd8d2e Translated using Weblate (Dutch)
Currently translated at 99.7% (333 of 334 strings)

Translated using Weblate (Dutch)

Currently translated at 99.7% (333 of 334 strings)

Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-05-26 12:00:39 +00:00
Weblate
a4a3330a99 Translated using Weblate (Turkish)
Currently translated at 92.8% (310 of 334 strings)

Translated using Weblate (Turkish)

Currently translated at 92.8% (310 of 334 strings)

Translated using Weblate (Turkish)

Currently translated at 92.8% (310 of 334 strings)

Translated using Weblate (German)

Currently translated at 100.0% (334 of 334 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (334 of 334 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Ramazan Sancar <ramazansancar4545@gmail.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/tr/
Translation: Homebox/Frontend
2025-05-26 07:41:27 +00:00
tonyaellie
b00ba9c42f fix: request permission to access camera 2025-05-25 21:02:31 +00:00
Weblate
6e732b60d0 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/
Translation: Homebox/Frontend
2025-05-25 14:42:04 +00:00
Tonya
1a51839abd Topbar remake (#752)
* feat: begin work on topbar refresh

* feat: implement search input functionality

* feat: add ScannerModal component based on scanner page

* feat: add toggle to enable legacy topbar, remove scanner page

* feat: update scanner menu item to use SidebarMenuButton for legacy header support

* chore: lint

* style: make margin and padding more consistent

* feat: fun hack

* fix: remove uneeded log and class=""
2025-05-25 15:41:59 +01:00
Weblate
c1c61e5bd4 Translated using Weblate (Czech)
Currently translated at 100.0% (333 of 333 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-05-25 02:00:39 +00:00
tonyaellie
99691ca5bf chore: oops types for currency 2025-05-24 14:58:28 +00:00
tonyaellie
1e30dc0005 fix: remove some of the logs from the console so its more usable 2025-05-24 14:20:27 +00:00
tonyaellie
83d1ae69a0 chore: formatting oops 2025-05-23 17:22:32 +00:00
tonyaellie
cd43c5bd30 fix: use correct themes for tailwind typography 2025-05-23 17:22:08 +00:00
Alexander Gryson
0c6201f4c6 Force printable label sheets to be black on white background (#751)
Co-authored-by: Alex Gryson <alex@gryson.net>
2025-05-23 17:12:26 +00:00
Weblate
b1e6b67450 Translated using Weblate (Czech)
Currently translated at 100.0% (332 of 332 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (332 of 332 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-05-21 00:00:39 +00:00
Weblate
a4099a6ca5 Translated using Weblate (Bosnian)
Currently translated at 20.7% (69 of 332 strings)

Co-authored-by: Alex <me@alex.ba>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/bs/
Translation: Homebox/Frontend
2025-05-20 15:00:39 +00:00
Matt Kilgore
30e78f1872 Update ideas.yml 2025-05-20 08:47:52 -04:00
Matt Kilgore
1a384cd4b0 Delete .github/ISSUE_TEMPLATE/feature_request.yml 2025-05-20 08:37:07 -04:00
Matt Kilgore
7ef4e6547e Update config.yml 2025-05-20 08:36:45 -04:00
Matt Kilgore
ad14674082 Update ideas.yml 2025-05-20 08:32:57 -04:00
Matt Kilgore
2137dfae0c Create ideas.yml 2025-05-20 08:31:40 -04:00
Matt Kilgore
d6d1a84fd4 Update config.yml 2025-05-19 14:48:14 -04:00
Matt Kilgore
bf59305645 Create config.yml 2025-05-19 14:47:17 -04:00
Weblate
71de4a5240 Translated using Weblate (Czech)
Currently translated at 99.3% (330 of 332 strings)

Co-authored-by: Katos <katos@creatorswave.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-05-18 22:00:39 +00:00
Katos
c9af903228 Fix shortcut keys
Fixes #707
2025-05-18 18:19:09 +01:00
Weblate
2fb12f6139 Translated using Weblate (Swedish)
Currently translated at 97.8% (325 of 332 strings)

Co-authored-by: Daniel Söderström <daniel@opterion.se>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translation: Homebox/Frontend
2025-05-18 13:00:39 +00:00
Weblate
c2cb531c79 Translated using Weblate (French)
Currently translated at 100.0% (332 of 332 strings)

Co-authored-by: Alexander Gryson <agryson@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-05-16 14:00:39 +00:00
Weblate
bddbc270c6 Translated using Weblate (Slovak)
Currently translated at 94.2% (313 of 332 strings)

Co-authored-by: Stanley Jochman <s.jochman@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-05-15 01:00:39 +00:00
Weblate
1a779fdf03 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.4% (327 of 332 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 98.4% (327 of 332 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-05-14 12:00:39 +00:00
Weblate
b1b90c94ca Translated using Weblate (Italian)
Currently translated at 100.0% (332 of 332 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (332 of 332 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (332 of 332 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-05-13 11:00:39 +00:00
Weblate
ac33b7cbed Translated using Weblate (Czech)
Currently translated at 99.3% (330 of 332 strings)

Co-authored-by: Tonya <tonya@tokia.dev>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-05-12 19:00:39 +00:00
Weblate
9b3603ad61 Translated using Weblate (Hungarian)
Currently translated at 100.0% (332 of 332 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (332 of 332 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-05-12 12:57:50 +00:00
Weblate
4415563a8c Translated using Weblate (Hungarian)
Currently translated at 99.3% (330 of 332 strings)

Translated using Weblate (Hungarian)

Currently translated at 99.3% (330 of 332 strings)

Translated using Weblate (Hungarian)

Currently translated at 99.3% (330 of 332 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-05-12 08:14:50 +00:00
Weblate
b55963cbde Translated using Weblate (Hungarian)
Currently translated at 98.4% (327 of 332 strings)

Translated using Weblate (Slovenian)

Currently translated at 100.0% (332 of 332 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (332 of 332 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (332 of 332 strings)

Translated using Weblate (Turkish)

Currently translated at 88.7% (293 of 330 strings)

Translated using Weblate (Turkish)

Currently translated at 88.7% (293 of 330 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Ramazan Sancar <ramazansancar4545@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/tr/
Translation: Homebox/Frontend
2025-05-12 08:14:14 +00:00
greg1904
e4a45ddb59 Feat subitem create button (#691)
Co-authored-by: greg1904 <github@koppenatsch.de>
2025-05-11 15:46:53 -04:00
Weblate
469a7df448 Translated using Weblate (Slovenian)
Currently translated at 100.0% (330 of 330 strings)

Translated using Weblate (Slovenian)

Currently translated at 100.0% (330 of 330 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-05-11 14:00:39 +00:00
Weblate
0bb859238b Translated using Weblate (Slovenian)
Currently translated at 87.2% (288 of 330 strings)

Translated using Weblate (Slovenian)

Currently translated at 87.2% (288 of 330 strings)

Co-authored-by: Murk <saso@workrum.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-05-11 09:50:49 +00:00
Weblate
e4cc79e4de Translated using Weblate (Czech)
Currently translated at 100.0% (330 of 330 strings)

Co-authored-by: Martin Joneš <jondytmf@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-05-09 22:00:39 +00:00
Weblate
3a301e73ed Translated using Weblate (Czech)
Currently translated at 100.0% (330 of 330 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-05-08 23:00:39 +00:00
Weblate
ac1c9f7d67 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.4% (325 of 330 strings)

Co-authored-by: Jackxwb <xwb9606@163.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-05-08 13:00:39 +00:00
Tonya
9855474555 fix issues with actions (#680)
* chore: remove unused lunr and add types for semver

* fix: try pinning using dlx

* chore: update typecheck command in package.json and clean up tailwind config

* chore: add vite as a dep

* fix: tests

* fix: wait for toast

* fix: use first

* feat: try adding waiting?

* fix: i was stupid

* fix: one day it will work (apple)

* fix: api

* fix: booleans are the enemy

* feat: try switching from blob to file

* Revert "feat: try switching from blob to file"

This reverts commit 3728b444e6.
2025-05-08 12:48:31 +00:00
Tonya
0cd1b46ecb feat: use nuxts built in error page instead of a catch all page (#675)
* feat: use nuxts built in error page instead of a catch all page

* fix: require error prop in error.vue and remove optional chaining for more reliable error handling
2025-05-08 08:16:51 +00:00
Matthew Kilgore
588074f50a This should in theory fix the binary builds 2025-05-07 20:18:18 -04:00
Weblate
60b817a6fc Translated using Weblate (French)
Currently translated at 100.0% (330 of 330 strings)

Translated using Weblate (German)

Currently translated at 100.0% (330 of 330 strings)

Co-authored-by: Baptistecottey <batist37390@gmail.com>
Co-authored-by: mondstern <mondstern@monocles.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-05-07 20:00:39 +00:00
Weblate
3a3f33ec51 Translated using Weblate (Bosnian)
Currently translated at 7.2% (24 of 330 strings)

Co-authored-by: Alex <me@alex.ba>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/bs/
Translation: Homebox/Frontend
2025-05-07 13:00:39 +00:00
Weblate
f03796d25c Added translation using Weblate (Bosnian)
Co-authored-by: Alex <me@alex.ba>
2025-05-07 08:20:08 +00:00
Weblate
bc14d0303c Translated using Weblate (Spanish)
Currently translated at 100.0% (330 of 330 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (330 of 330 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-05-06 22:00:39 +00:00
Weblate
e4728d6887 Translated using Weblate (Dutch)
Currently translated at 100.0% (328 of 328 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (328 of 328 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-05-06 14:00:01 +00:00
Matt Kilgore
66a868f1bc Update binaries-publish.yaml 2025-05-06 09:59:57 -04:00
Matt Kilgore
243cda044c Add missing language names 2025-05-06 12:54:32 +00:00
Weblate
4a505cbef3 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (328 of 328 strings)

Translated using Weblate (French)

Currently translated at 100.0% (328 of 328 strings)

Co-authored-by: EdWorth120 <coragem.o.cao.covarde.81@gmail.com>
Co-authored-by: buzz <buzz.eclair@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translation: Homebox/Frontend
2025-05-06 03:00:39 +00:00
Weblate
57792eabf5 Translated using Weblate (Italian)
Currently translated at 100.0% (328 of 328 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (328 of 328 strings)

Translated using Weblate (English)

Currently translated at 96.9% (318 of 328 strings)

Co-authored-by: 101br03k <warmerdamm03@gmail.com>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-05-05 14:00:39 +00:00
Weblate
8185598dd0 Translated using Weblate (Italian)
Currently translated at 100.0% (328 of 328 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (328 of 328 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-05-05 09:23:31 +00:00
Weblate
9e53f1439c Translated using Weblate (Italian)
Currently translated at 99.6% (327 of 328 strings)

Translated using Weblate (Italian)

Currently translated at 99.6% (327 of 328 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-05-05 09:23:06 +00:00
Weblate
50adb48612 Translated using Weblate (Italian)
Currently translated at 99.3% (326 of 328 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-05-05 09:22:18 +00:00
Weblate
8ee48ec4ff Translated using Weblate (Dutch)
Currently translated at 99.6% (327 of 328 strings)

Co-authored-by: Erwin van Londen <translate.sysadminsm.treachery437@passmail.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-05-05 07:00:41 +00:00
Tonya
232dc08fcd enable primary button (#673)
* feat: enable primary button

* feat: better attachments

* fix: unneeded param
2025-05-05 01:43:38 +00:00
Weblate
8fb0ae64d7 Translated using Weblate (Czech)
Currently translated at 100.0% (328 of 328 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (328 of 328 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-05-04 22:00:39 +00:00
Matt Kilgore
9d13f41a2a Goreleaser build updates 2025-05-04 19:49:50 +00:00
Matt Kilgore
13ed91e9d5 Add Cosign binary to binary publish 2025-05-04 19:30:15 +00:00
Tonya
89aaa8c595 add override locale selector for dates and currencies (#648)
* feat: add override locale selector

* fix: dateExample computed property to ensure Vue updates with locale changes in LanguageSelector.vue
2025-05-04 13:11:28 -04:00
Tonya
16bcffac45 Remove shamefully hoist (#660)
* feat: remove shamefully hoist

* chore: remove .npmrc
2025-05-04 13:11:00 -04:00
EdWorth120
b89364d8c5 Create a rotate 90 degrees clockwise button for each image (#666)
* Create a rotate 90 degrees clockwise button for each image

* Added more error handling and turned rotate function to async as recommended by coderabbitai
2025-05-04 09:28:03 +00:00
Weblate
eb21da50e3 Translated using Weblate (Lithuanian)
Currently translated at 15.9% (52 of 326 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (326 of 326 strings)

Co-authored-by: mondstern <mondstern@monocles.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/lt/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/uk/
Translation: Homebox/Frontend
2025-05-03 23:00:39 +00:00
Matt Kilgore
606a92b5d5 Remove documents table (#618)
* Remove documents table (WIP)

* Further cleanup of documents table

* This should clean up the errors, but actual attachment handling still needs added.

* Full generation to update the JS side of things too

* Further fixes

* Fix cyclic dependency issue

* In theory the API side works now

* Fix go linting issues

* Fix frontend issues

* Way closer, but has a foreign key constrant issue

* UI actually works now

* Fix deduplication feature not working right

* Upgrade to `golangci-lint` v2 file

* Add ability to set primary during attachment creation

* Update swagger with new primary attachment during creation stuff

* Files are actually saved now, but there's still a bug

* Fix critical issue whith how deletions were working

* Fix the byte copy issue

* Hopefully everything is fixed now

* Fix golangci-lint config and lint files

* Fix lint issue

* Fix a few more tests

* Fix lint issues again

* More minor test fixes

* Update backend/internal/core/services/service_items_attachments.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix migration (I think)

* Fixed postgres migration

* Change some migration options to work better

* Some more little things that I tried

* Fix merge go.mod

* Fix migrations

* Little lint thing

* Fix AttachmentsList.vue with updated API

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-03 10:15:54 -04:00
Weblate
a64d0c5b4c Translated using Weblate (Thai)
Currently translated at 33.4% (109 of 326 strings)

Co-authored-by: yogokawaii <phonanb@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/th/
Translation: Homebox/Frontend
2025-05-03 06:00:39 +00:00
Weblate
a2d9fd9ee0 Translated using Weblate (Czech)
Currently translated at 100.0% (326 of 326 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-05-02 03:00:39 +00:00
Weblate
03860d6053 Translated using Weblate (Lithuanian)
Currently translated at 12.8% (42 of 326 strings)

Co-authored-by: mondstern <mondstern@monocles.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/lt/
Translation: Homebox/Frontend
2025-05-01 20:00:39 +00:00
Matt Kilgore
1ac86d9c04 Real Migrations System (#645)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-05-01 15:03:08 -04:00
EdWorth120
6bb196037c Fix create item modal form layout on mobile devices (#662) 2025-05-01 17:56:39 +00:00
Weblate
78c18aa654 Added translation using Weblate (Lithuanian)
Co-authored-by: mondstern <mondstern@monocles.de>
2025-05-01 15:18:17 +00:00
Weblate
88214dfc71 Added translation using Weblate (Luxembourgish)
Translated using Weblate (Romanian)

Currently translated at 86.5% (282 of 326 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (326 of 326 strings)

Translated using Weblate (Finnish)

Currently translated at 99.6% (324 of 325 strings)

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: mondstern <mondstern@monocles.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fi/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ro/
Translation: Homebox/Frontend
2025-05-01 15:16:41 +00:00
EdWorth120
60b2ffd023 Add a quantity field to the item create modal form. (#615)
* Add a quantity field to the item create modal form.

* Fix prettier code format complaint.

* Update en.json allowing the label of the field to be translated.

* Including changes generated by swag and typescript-types tasks.

* Fixed tests, item duplication and lint errors.

* Fix linter issues again and an error introduced in 912e5b2

* Fixed a test that creates an item through the go:coverage task
2025-04-30 19:42:24 -04:00
Weblate
ebf42a754a Translated using Weblate (Finnish)
Currently translated at 45.2% (147 of 325 strings)

Co-authored-by: mondstern <mondstern@monocles.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fi/
Translation: Homebox/Frontend
2025-04-29 22:00:39 +00:00
tonyaellie
f1c9aab9df style: make sure button is always big enough for text on tools page 2025-04-29 09:53:38 +00:00
Weblate
2a6366808c Translated using Weblate (Finnish)
Currently translated at 19.6% (64 of 325 strings)

Co-authored-by: mondstern <mondstern@monocles.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fi/
Translation: Homebox/Frontend
2025-04-28 23:00:39 +00:00
tonyaellie
3ea3ebb346 fix: incorrect text for TagsInputItem.vue 2025-04-28 22:07:08 +00:00
Matt Kilgore
92bb564dfa Update config.mts 2025-04-28 08:50:20 -04:00
Matt Kilgore
5943e2c7e3 Add Lemmy 2025-04-28 08:48:39 -04:00
Weblate
a22bb0e10e Translated using Weblate (Japanese)
Currently translated at 90.7% (295 of 325 strings)

Translated using Weblate (Japanese)

Currently translated at 90.7% (295 of 325 strings)

Translated using Weblate (Japanese)

Currently translated at 90.7% (295 of 325 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (325 of 325 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Ricardo González <notorius28@gmail.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-04-28 10:00:39 +00:00
Weblate
746dbafcc1 Translated using Weblate (Danish)
Currently translated at 94.4% (307 of 325 strings)

Co-authored-by: mondstern <mondstern@monocles.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/da/
Translation: Homebox/Frontend
2025-04-28 01:00:39 +00:00
Weblate
fe7067f255 Translated using Weblate (Czech)
Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (325 of 325 strings)

Co-authored-by: Martin Joneš <jondytmf@gmail.com>
Co-authored-by: mondstern <mondstern@monocles.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/uk/
Translation: Homebox/Frontend
2025-04-27 17:00:39 +00:00
Katos
0b08d26501 Update update-currencies.yml 2025-04-27 15:46:48 +01:00
Katos
30870bec54 PIP cache on Updating Currencies
Add caching for currencies update
2025-04-27 15:46:18 +01:00
Katos
06524b0f2c Merge pull request #655 from sysadminsmedia/katos/update-currencies-action
Amend the "Update currencies" action
2025-04-27 15:42:59 +01:00
Katos
400a29b993 Update update-currencies.yml 2025-04-27 15:39:01 +01:00
Katos
b7d6b32fdd Update update-currencies.yml 2025-04-27 15:31:11 +01:00
Katos
f99e5739da Update update_currencies.py 2025-04-27 15:30:57 +01:00
Katos
060062b484 Update update_currencies.py
Retries + logging: Set timestamped errors on 5xx/429 or JSON failures.

Empty-array guard: script exits non-zero if the API returns [], so won’t commit an empty file.

Exit codes: any API or I/O error yields sys.exit(1), triggering “no commit on failure” logic.
2025-04-27 15:21:57 +01:00
Katos
6a5d8d2ed7 Update update-currencies.yml
Upgrades to the latest Action versions (checkout@v3, setup-python@v4).

Caches Python dependencies.

Detects both “any file changes” and “empty array” in one step (so won’t ever commit an emty array).

Replaces manual branch/CURL logic with peter-evans/create-pull-request, which handles branch creation, rebasing and PR creation in one go.
2025-04-27 15:15:25 +01:00
Tonya
9afd20c513 Sort themes and remove daisyui (#643)
* feat: sort themes and remove daisyui

* docs: update docs to reflect daisyui being removed

* feat: remove specific colours for better theme compatibility
2025-04-27 09:01:27 +00:00
Weblate
de52959c5b Translated using Weblate (Czech)
Currently translated at 100.0% (325 of 325 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-04-26 20:00:39 +00:00
Weblate
472a0577c8 Translated using Weblate (Dutch)
Currently translated at 100.0% (325 of 325 strings)

Co-authored-by: 101br03k <warmerdamm03@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-04-26 13:00:39 +00:00
Matt Kilgore
17a4be85d8 Fix required go version for dev 2025-04-24 21:47:25 -04:00
Weblate
0830fd670b Translated using Weblate (French)
Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (French)

Currently translated at 100.0% (325 of 325 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: molusk <molusk@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-04-25 01:00:39 +00:00
Weblate
eb18f2d1f9 Translated using Weblate (French)
Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (French)

Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (French)

Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (French)

Currently translated at 100.0% (325 of 325 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: mcarbonne <maximilien.carbonne@gmail.com>
Co-authored-by: molusk <molusk@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-04-24 20:43:51 +00:00
github-actions[bot]
152f31a8c8 Update currencies.json (#647)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-04-23 16:18:54 -04:00
Weblate
fcafce04f2 Translated using Weblate (Dutch)
Currently translated at 99.6% (324 of 325 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-04-23 00:00:39 +00:00
Weblate
e2680b9fa6 Translated using Weblate (Hungarian)
Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (325 of 325 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-04-22 10:00:39 +00:00
Weblate
6eb626a151 Translated using Weblate (Hungarian)
Currently translated at 99.6% (324 of 325 strings)

Translated using Weblate (Hungarian)

Currently translated at 99.6% (324 of 325 strings)

Translated using Weblate (Hungarian)

Currently translated at 99.6% (324 of 325 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-04-22 05:21:36 +00:00
Weblate
9e6779a45a Translated using Weblate (Hungarian)
Currently translated at 96.9% (315 of 325 strings)

Translated using Weblate (Dutch)

Currently translated at 99.6% (324 of 325 strings)

Co-authored-by: Erwin van Londen <translate.sysadminsm.treachery437@passmail.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-04-22 05:12:40 +00:00
Weblate
3e1404490b Translated using Weblate (Czech)
Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (325 of 325 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (325 of 325 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-04-20 15:00:39 +00:00
Weblate
1f37123899 Translated using Weblate (Czech)
Currently translated at 97.2% (316 of 325 strings)

Translated using Weblate (German)

Currently translated at 99.3% (323 of 325 strings)

Translated using Weblate (German)

Currently translated at 99.3% (323 of 325 strings)

Translated using Weblate (German)

Currently translated at 99.3% (323 of 325 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: Matt <weblate@neo17k.de>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-04-20 10:32:46 +00:00
Weblate
d2bdfebe0a Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/
Translation: Homebox/Frontend
2025-04-20 07:58:08 +00:00
Tonya
cbaf483788 migrate pages to shadcn (#628)
* feat: migrate tools page and label generator to shadcn

* chore: lint issues

* feat: also do profile page

* feat: shadcn 404 page

* feat: login page shadcn

* fix: daisyui ironically breaks the z height for the login page

* feat: componentise the language selector and add it to the login page

* feat: use nuxtlink

* feat: card and table made more shadcn

* feat: shadcn statscard

* chore: lint

* feat: shadcn labelchip and locationcard

* feat: shadcn locations page

* refactor: remove unused new item page

* chore: lint

* feat: shadcn item card

* fix: wrapping of location and lint

* feat: ctrl enter in text area in form submits form

* feat: begin shadcn locations page and remove pageqrcode comp in favour of integrating it into labelmaker

* chore: lint + remove unused code

* fix: remove uneeded margin

* feat: shadcn labels page and fix some issues with location

* feat: shadcn scanner

* chore: lint

* feat: begin shadcning item pages

* feat: shadcn maintenance page

* feat: begin shadcn search page

* fix: quick switch blurry text and crashing page when switching + incorrect z height for create menu

* feat: finish shadcn search page

* chore: lint

* feat: shadcn edit item page

* fix: quickmenumodal bug

* feat: shadcn item details page

* feat: remove all non-color related daisyui classes

* fix: type error

* fix: quick menu modal again :(
2025-04-20 08:58:03 +01:00
Matthew Kilgore
400bc3f341 Fix frontend lint 2025-04-19 15:53:21 -04:00
Matthew Kilgore
912e5b231a Fix footer links 2025-04-19 13:35:19 -04:00
Matt Kilgore
177b7344f8 E2E Playwright Testing (#466)
* Add e2e testing for frontend

* Hopefully working CI/CD for playwright

* Fix run name

* Trying to fix the CI/CD stuff

* Try this again, although Vite apparently has playwright?

* Fix vitetest

* Add registration tests

* Safer kill of testing dependencies

* These might not last.

* feat: Add iPhone and Android device testing

* fix: Minor fixes, set registration to "fixme" as it fails frequently for some reason.

* fix: Make sure the OS dependencies get installed

* fix: For now remove mobile, they seem to be very hit or miss.

* Use sharding based testing

* Fix some minor mess ups

* Forgot PNPM for the merge
2025-04-19 13:09:14 -04:00
Weblate
d11627fa28 Translated using Weblate (Portuguese (Portugal))
Currently translated at 81.7% (260 of 318 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 81.7% (260 of 318 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: bl4ck1c3pt <gilpereira-@hotmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_PT/
Translation: Homebox/Frontend
2025-04-18 22:00:39 +00:00
Weblate
acf1660574 Translated using Weblate (English)
Currently translated at 100.0% (318 of 318 strings)

Translated using Weblate (English)

Currently translated at 100.0% (316 of 316 strings)

Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translation: Homebox/Frontend
2025-04-16 06:00:38 +00:00
Matt Kilgore
d644d302a3 Fix the footer links (#635) 2025-04-15 21:19:53 -04:00
Weblate
129cc72b8b Translated using Weblate (Portuguese (Portugal))
Currently translated at 81.3% (257 of 316 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 81.3% (257 of 316 strings)

Translated using Weblate (French)

Currently translated at 100.0% (316 of 316 strings)

Co-authored-by: Goncalo Almeida Casqueiro <goncalocasqueiro@armillaryhub.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: sephrat <florian.dupret@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_PT/
Translation: Homebox/Frontend
2025-04-15 16:00:39 +00:00
Dandyandy
1e0479c365 Fix/407 text wrap markdown issue (#616) 2025-04-15 10:51:06 -04:00
Weblate
41c9734ffb Translated using Weblate (Italian)
Currently translated at 100.0% (316 of 316 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (316 of 316 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (316 of 316 strings)

Co-authored-by: Erwin van Londen <translate.sysadminsm.treachery437@passmail.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-04-14 08:00:38 +00:00
Weblate
4b13897839 Translated using Weblate (Czech)
Currently translated at 100.0% (316 of 316 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (316 of 316 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-04-11 17:00:38 +00:00
Weblate
6984b33389 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/
Translation: Homebox/Frontend
2025-04-11 10:02:53 +00:00
Tonya
9ff4b32db0 Switch layouts to use shadcn (#507)
* feat: begin switching sonner, currently this breaks all alerts

* feat: switch to using new sonner and fix class names

* feat: add Shortcut component for improved keyboard shortcuts display in default layout

* feat: rewrite quick menu modal in shadcn

* feat: update QuickMenu modal placeholders and localize no results message in default layout

* feat: begin switching modals in layout to use shadcn dialog, needs bug fixing

* feat: implement DialogProvider for consistent dialog management across components

* fix: types

* feat: begin adding shadcn label selector (wip)

* feat: shadcnify textarea

* feat: begin adding location selector

* feat: add hotkey support for opening create modals in dialog provider components

* fix: update click event on NuxtLink and reorder sidebar menu item IDs for consistency

* feat: unify shortcut text across create modals and sort issue with text centring

* feat: prevent dialog from opening when a dialog alert is open

* fix: prevent potential out of bounds error

* feat: enhance button group UI in create modals for better layout and introduce new item photo label in the form

* fix: search on label selector

* chore: lint

* fix: oops

* feat: make selector usable

* feat: add actual data to label selector

* feat: label selector kinda works

* fix: add legacy selector for edit page

* fix: enable camera capture in image upload for CreateModal component

* fix: z levels for sidebar mobile

* fix: gap between inputs

* feat: update radix-vue, custom search function for location selector

* feat: add fuzzysort (can always remove it and go to lunr if we want to)

* feat: limit label name to 50 characters in create modal and selector, helps with issues with ui not working with larger labels, as it is only enforced on the frontend could be easily bypassed but thats a them problem

* feat: add colours to toast

* chore: lint

* feat: abstract the dialog for creation modals

* feat: add drawer component and responsive dialog for create modals

* feat: enhance photo preview in CreateModal

* fix: remember state of sidebar

* feat: add ui functionality for changing primary image

* feat: use button for file upload

* style: lint

* fix: dont clone asset id

* fix: using create and add label breaks selector

* chore: oops remove logging

* chore: lint

* fix: cut length of label dramatically to ensure maximal compatibility, not sure if too much

* fix: more limiting of label length

* feat: update reka-ui (prev radix-vue)

* chore: cleanup dialog provider and siebar provider a bit

* fix: improve accessibility

* fix: docs for shadcn error

* fix: hack to prevent issues with lots of toasts in quick succession

* feat: cleanup toast file and lint

* feat: improvements to dialog scroll and disable the ability to set default photo for now

* feat: add tooltips for photo buttons

* chore: substring to length check

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-11 11:02:49 +01:00
tonyaellie
964d3264cc docs: add missing env var change 2025-04-10 13:51:59 +00:00
Weblate
fca21a58f6 Translated using Weblate (French)
Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: sephrat <florian.dupret@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-04-09 20:00:38 +00:00
tonyaellie
2fe41d4783 fix: update asset and warranty field names to use translations 2025-04-09 10:23:37 +00:00
Tonya
4c0af18dcb feat: migration guide for hay-kot version (#620)
* feat: migration guide for hay-kot version

* Update docs/en/quick-start.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* docs: enhance migration guide with clearer steps and emphasize backup importance before migration process

* docs: add 'Migration Guide' link to menu and change from upgrade to migration guide in quick start

* docs: better text

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Matt Kilgore <tankerkiller125@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-09 10:13:23 +00:00
Weblate
a68aafdfd7 Translated using Weblate (Swedish)
Currently translated at 100.0% (309 of 309 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ecke101 <ecke101@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translation: Homebox/Frontend
2025-04-08 13:00:38 +00:00
Weblate
9db6f51a43 Translated using Weblate (Swedish)
Currently translated at 100.0% (309 of 309 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (309 of 309 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: ecke101 <ecke101@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translation: Homebox/Frontend
2025-04-08 08:03:52 +00:00
Weblate
fade1fbc21 Translated using Weblate (Spanish)
Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: Ricardo González <notorius28@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-04-06 20:00:38 +00:00
Weblate
cdabadb276 Translated using Weblate (Catalan)
Currently translated at 86.0% (266 of 309 strings)

Co-authored-by: Oriol Navascuez <onavascuez@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ca/
Translation: Homebox/Frontend
2025-04-05 14:59:47 +00:00
EdWorth120
cd510a07e7 Fix cannot delete photo in create item modal form (#613)
* Add a delete icon to every photo added in the create item modal form.

* Add a delete icon to every photo added in the create item modal form.

* Corrected margin of filename.

* Format the layout of the delete button using daisyUI indicator component CSS classes.

* Moved PhotoPreview interface to the local component file, it should not go in data-contracts.ts, this file is generated based on the contents of swagger.json, that is generated based on the contents of the backend, the type definition if it needs to be shared should go inside non-generated.ts
2025-04-05 08:38:53 -04:00
Matt Kilgore
b50add5732 Update CODE_OF_CONDUCT.md 2025-03-29 15:38:13 -04:00
mygrexit
ca612a138f fix: apply natural sorting for item names (#607) 2025-03-26 20:31:49 -04:00
Matt Kilgore
c275fa3e4a Fixes #605 2025-03-26 09:46:52 -04:00
Weblate
0ba6c08dda Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.6% (308 of 309 strings)

Co-authored-by: Cheng Gu <guchengf@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-03-25 09:35:33 +00:00
Weblate
35b3e94b2f Translated using Weblate (Hungarian)
Currently translated at 100.0% (309 of 309 strings)

Translated using Weblate (Russian)

Currently translated at 93.5% (289 of 309 strings)

Translated using Weblate (French)

Currently translated at 96.7% (299 of 309 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (309 of 309 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (309 of 309 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (309 of 309 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: Eugene Zrazhevsky <eugeny.zrazhevsky@gmail.com>
Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Co-authored-by: buzz <buzz.eclair@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ru/
Translation: Homebox/Frontend
2025-03-24 10:35:33 +00:00
Weblate
bf9ac0fb3b Translated using Weblate (Hungarian)
Currently translated at 100.0% (309 of 309 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-03-24 06:10:17 +00:00
Katos
c5ae258757 Exclude sold items from TotalPrice calculation
Exclude items that have a solddate from total price calculation
2025-03-23 20:48:39 +00:00
Katos
9a1bd6bfc4 Re-add photopreview, will fix this in a separate issue for Linting 2025-03-23 20:47:45 +00:00
Katos
1c802feabe Remove PhotoPreview import to fix Linting errors 2025-03-23 20:45:39 +00:00
Katos
6b0c28df83 Add method to type ItemSummary 2025-03-23 20:34:29 +00:00
Katos
7937518ef0 Fix issue with duplicated SoldTime struct 2025-03-23 20:27:50 +00:00
Katos
406eca7709 Exclude items that have a solddate from total price calculation 2025-03-23 20:17:40 +00:00
Matthew Kilgore
e716fe54e1 Merge remote-tracking branch 'origin/main' 2025-03-22 21:45:08 -04:00
Matthew Kilgore
64b4173d1d fix: borked doc param 2025-03-22 21:45:01 -04:00
Matt Kilgore
dcf16ba4c9 Update index.md 2025-03-22 14:09:50 -04:00
Matthew Kilgore
c00edce158 chore: Use our own site instead of jsDelivr 2025-03-22 14:04:08 -04:00
Matt Kilgore
71d9b6605b Update api.md 2025-03-22 13:47:56 -04:00
Matt Kilgore
8e9571c96a Update api.md 2025-03-22 13:31:09 -04:00
Matt Kilgore
41ff4c4664 Mk/fix api docs (#601)
* fix: API URLs for docs

* fix: merge issue

* fix: Lets try this again with some minor changes
2025-03-22 13:26:42 -04:00
Katos
7279703d7c Revert temp API test 2025-03-22 16:59:30 +00:00
Katos
6b938a88cf FIX: Dynamically patch the BaseURL on load (API) 2025-03-22 16:56:50 +00:00
Katos
8854a6835e API changes 2025-03-22 16:52:47 +00:00
Katos
51291e94b0 Skill issue central, sorry! 2025-03-22 16:51:00 +00:00
Katos
733d1c5f77 Stoplight being stupid with BaseURL 2025-03-22 16:49:16 +00:00
Katos
91fde1e3d7 Adjust API footer to AGPL license 2025-03-22 16:44:02 +00:00
Katos
46539547af API: Dynamically reload CSS on light/dark mode 2025-03-22 16:38:05 +00:00
Katos
858f242e52 Fix host URL 2025-03-22 16:36:40 +00:00
Katos
1c7b6fef9e Update BaseURL on API 2025-03-22 16:35:08 +00:00
Matt Kilgore
d5b062cd62 fix: API URLs for docs (#599)
* fix: API URLs for docs

* fix: merge issue
2025-03-22 12:04:52 -04:00
Katos
e216d46848 Update API 2025-03-22 15:42:36 +00:00
Katos
9ee6b7b72f Remove hash router 2025-03-22 15:38:40 +00:00
Katos
a7c3c7041a Update openapi-2.0.json 2025-03-22 15:37:59 +00:00
Katos
92a0fa1193 Update openapi-2.0.json 2025-03-22 15:34:18 +00:00
Katos
46d217232a Update api.md 2025-03-22 15:33:14 +00:00
Katos
3b35612574 Yeet a test to fix API redirect issues 2025-03-22 15:31:34 +00:00
Matt Kilgore
5e2e8b66d8 Mk/simplified analytics (#596)
* chore: move analytics to it's own seperate file and function.

* chore: fix linting
2025-03-22 11:24:57 -04:00
Weblate
482aeac289 Translated using Weblate (Czech)
Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-03-22 00:35:32 +00:00
Weblate
88bec687e3 Translated using Weblate (German)
Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: Matt <weblate@neo17k.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-03-20 19:31:56 +00:00
Sai Vishnu M
537dedbbea Improve Media Stream API error message for clarity (#593)
The previous error message was vague, stating only that the Media Stream API was unsupported. This update makes it explicit that HTTPS is required for support. The new message reads:  
> "Media Stream API is not supported without HTTPS" 
This improves clarity and helps users quickly understand the issue and how to resolve it.
2025-03-18 14:48:11 -04:00
Weblate
ab777e4a35 Translated using Weblate (Czech)
Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-03-18 18:35:32 +00:00
Weblate
9e2937a3d9 Translated using Weblate (German)
Currently translated at 100.0% (309 of 309 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-03-17 21:35:32 +00:00
Weblate
0344bbdabe Translated using Weblate (German)
Currently translated at 100.0% (308 of 308 strings)

Translated using Weblate (German)

Currently translated at 100.0% (308 of 308 strings)

Translated using Weblate (German)

Currently translated at 100.0% (308 of 308 strings)

Translated using Weblate (English)

Currently translated at 100.0% (308 of 308 strings)

Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Nic <nicmeier1@gmx.net>
Co-authored-by: justuser668 <der.chiller@t-online.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translation: Homebox/Frontend
2025-03-17 15:52:37 +00:00
Weblate
3725c6d161 Translated using Weblate (German)
Currently translated at 97.0% (299 of 308 strings)

Co-authored-by: Matt <weblate@neo17k.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-03-17 14:28:02 +00:00
Matt Kilgore
f2770584c7 chore: Always use LTS NodeJS for Docker builds (#589)
* chore: Always use LTS NodeJS for Docker builds

* chore: Update devcontainers too
2025-03-16 12:25:09 -04:00
Matt Kilgore
de4a3ef7a9 [VNEXT] feat: Opt-In Anlytics (#277)
* feat: Initial Analytics stuff

* chore: add documentation of new feature

* fix: minor issues

* chore: add some new doc pages around analytics.

* fix: iframe height?

* fix: minor some PR stuff

* chore: add version and virtualization type to analytics

* Update privacy.md

* [VNEXT] feat: Multi-DB type support (#291)

* feat: Multi-DB type URL formats and config

* fix: remove legacy sqlite path config and minor other things

* fix: dumb eslint issues

* fix: dumb eslint issues

* fix: application can be tested with sqlite

* fix: minor config formatting

* chore: some cleanup

* feat: postgres migration creation now works

The migration creation for postgres now works properly.
Removed MySQL support, having too many issues with it at this time.

* chore: revert some strings back to bytes as they should be

* feat: improve languages support

* feat: add locale time ago formatting and the local name for the language in language dropdown

* Update FUNDING.yml

* chore: remove some more mysql stuff

* fix: coderabbit security recommendations

* fix: validate postgres sslmode

* Update migrations.go

* fix: postgres migration creation now works

* fix: errors in raw sql queries

* fix: lint error, and simpler SQL query

* fix: migrations directory string

* fix: stats related test

* fix: sql query

* Update TextArea.vue

* Update TextField.vue

* chore: run integration testing on multiple postgresql versions

* chore: jobs should run for vnext branch PRs

* fix: missed $ for Postgres testing

* fix: environment variable for db ssl mode

* fix: lint issue from a merge

* chore: trying to fix postgresql testing

* chore: trying to fix postgresql testing

* fix: trying to fix postgresql testing

* fix: trying to fix postgresql testing

---------

Co-authored-by: tonya <tonya@tokia.dev>

* fix: publish docker vnext branch

* Add upgrade guide documentation

* chore: add new config options to documentation

* Update vnext (#314)

* feat: make 404 follow theme and add a return home page

* feat: sanitise translations when using v-html

* chore: Add native API docs to website

* chore: remove try it button from api docs

---------

Co-authored-by: tonyaellie <tonya@tokia.dev>

* Update Dockerfile

Update dockerfile to test the theory of data folder breaking in vnext

* fix: broken docker image

* fix: statistics

* feat: support mm, cm and inches for label generation

* [VNEXT] feat: Multi-DB type support (#291)

* feat: Multi-DB type URL formats and config

* fix: remove legacy sqlite path config and minor other things

* fix: dumb eslint issues

* fix: dumb eslint issues

* fix: application can be tested with sqlite

* fix: minor config formatting

* chore: some cleanup

* feat: postgres migration creation now works

The migration creation for postgres now works properly.
Removed MySQL support, having too many issues with it at this time.

* chore: revert some strings back to bytes as they should be

* feat: improve languages support

* feat: add locale time ago formatting and the local name for the language in language dropdown

* Update FUNDING.yml

* chore: remove some more mysql stuff

* fix: coderabbit security recommendations

* fix: validate postgres sslmode

* Update migrations.go

* fix: postgres migration creation now works

* fix: errors in raw sql queries

* fix: lint error, and simpler SQL query

* fix: migrations directory string

* fix: stats related test

* fix: sql query

* Update TextArea.vue

* Update TextField.vue

* chore: run integration testing on multiple postgresql versions

* chore: jobs should run for vnext branch PRs

* fix: missed $ for Postgres testing

* fix: environment variable for db ssl mode

* fix: lint issue from a merge

* chore: trying to fix postgresql testing

* chore: trying to fix postgresql testing

* fix: trying to fix postgresql testing

* fix: trying to fix postgresql testing

---------

Co-authored-by: tonya <tonya@tokia.dev>

* fix: publish docker vnext branch

* Add upgrade guide documentation

* chore: add new config options to documentation

* Update Dockerfile

Update dockerfile to test the theory of data folder breaking in vnext

* fix: broken docker image

* fix: statistics

* feat: support mm, cm and inches for label generation

* Update privacy.md

* chore: fix merge with main

* fix: Docs menu

* fix: Docs

* fix: Fix privacy policy layout

* fix: put stats under it's own unlikely used URL

* Forgot to add to configure.md

---------

Co-authored-by: tonya <tonya@tokia.dev>
Co-authored-by: Katos <7927609+katosdev@users.noreply.github.com>
2025-03-15 21:17:18 -04:00
Weblate
341f0e9af9 Translated using Weblate (Chinese (Simplified) (zh_MO))
Currently translated at 60.0% (185 of 308 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (308 of 308 strings)

Co-authored-by: Ziqian Huang <ziqian.huang@hotmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_MO/
Translation: Homebox/Frontend
2025-03-15 21:35:32 +00:00
Weblate
e5be690e94 Translated using Weblate (Danish)
Currently translated at 98.7% (304 of 308 strings)

Co-authored-by: Heine Olsen <olsen10051988@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/da/
Translation: Homebox/Frontend
2025-03-14 01:35:32 +00:00
Weblate
97eecac56f Translated using Weblate (Albanian)
Currently translated at 31.1% (96 of 308 strings)

Translated using Weblate (Albanian)

Currently translated at 31.1% (96 of 308 strings)

Co-authored-by: Bledar Jonuzaj <mikuvarin@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sq/
Translation: Homebox/Frontend
2025-03-13 19:35:32 +00:00
dependabot[bot]
f28bb8886c Bump the npm_and_yarn group across 1 directory with 2 updates (#585)
Bumps the npm_and_yarn group with 1 update in the /frontend directory: [@babel/helpers](https://github.com/babel/babel/tree/HEAD/packages/babel-helpers).


Updates `@babel/helpers` from 7.26.9 to 7.26.10
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-helpers)

Updates `@babel/runtime` from 7.26.9 to 7.26.10
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-runtime)

---
updated-dependencies:
- dependency-name: "@babel/helpers"
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: "@babel/runtime"
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-13 13:55:53 -04:00
Weblate
b98c550ac3 Translated using Weblate (Albanian)
Currently translated at 10.7% (33 of 308 strings)

Translated using Weblate (Albanian)

Currently translated at 10.7% (33 of 308 strings)

Co-authored-by: Bledar Jonuzaj <mikuvarin@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sq/
Translation: Homebox/Frontend
2025-03-13 15:01:12 +00:00
Weblate
1e89b06a2a Translated using Weblate (Albanian)
Currently translated at 2.5% (8 of 308 strings)

Translated using Weblate (Albanian)

Currently translated at 2.5% (8 of 308 strings)

Co-authored-by: Bledar Jonuzaj <mikuvarin@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sq/
Translation: Homebox/Frontend
2025-03-13 14:50:04 +00:00
Weblate
585875aaf8 Translated using Weblate (Albanian)
Currently translated at 1.9% (6 of 308 strings)

Translated using Weblate (Albanian)

Currently translated at 1.9% (6 of 308 strings)

Co-authored-by: Bledar Jonuzaj <mikuvarin@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sq/
Translation: Homebox/Frontend
2025-03-13 14:47:42 +00:00
Weblate
ada5cc8575 Translated using Weblate (Albanian)
Currently translated at 1.6% (5 of 308 strings)

Translated using Weblate (Albanian)

Currently translated at 1.6% (5 of 308 strings)

Co-authored-by: Bledar Jonuzaj <mikuvarin@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sq/
Translation: Homebox/Frontend
2025-03-13 14:47:11 +00:00
dependabot[bot]
4f150f3c52 Bump golang.org/x/net (#581)
Bumps the go_modules group with 1 update in the /backend directory: [golang.org/x/net](https://github.com/golang/net).


Updates `golang.org/x/net` from 0.35.0 to 0.36.0
- [Commits](https://github.com/golang/net/compare/v0.35.0...v0.36.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-13 09:34:24 -04:00
Weblate
bde7f711de Added translation using Weblate (Albanian)
Co-authored-by: Bledar Jonuzaj <mikuvarin@gmail.com>
2025-03-13 11:39:42 +00:00
EdWorth120
629b1139ba Fixes the document record being abandoned inside the database after an attachment is deleted. (#579) 2025-03-12 15:08:19 -04:00
Weblate
45c1c17154 Translated using Weblate (Japanese)
Currently translated at 92.8% (286 of 308 strings)

Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-03-11 13:35:32 +00:00
Weblate
61ded24e9b Translated using Weblate (Italian)
Currently translated at 100.0% (308 of 308 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (308 of 308 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-03-10 19:35:32 +00:00
Weblate
2da77b7b8c Translated using Weblate (Italian)
Currently translated at 99.0% (305 of 308 strings)

Translated using Weblate (Italian)

Currently translated at 99.0% (305 of 308 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-03-10 15:33:32 +00:00
Weblate
5b62911040 Translated using Weblate (Hungarian)
Currently translated at 100.0% (308 of 308 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (308 of 308 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-03-10 10:35:32 +00:00
Weblate
b9386a3db0 Translated using Weblate (Hungarian)
Currently translated at 98.7% (304 of 308 strings)

Translated using Weblate (Hungarian)

Currently translated at 98.7% (304 of 308 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-03-10 06:16:17 +00:00
Weblate
8e7bcaf389 Translated using Weblate (Hungarian)
Currently translated at 97.4% (300 of 308 strings)

Translated using Weblate (Hungarian)

Currently translated at 97.4% (300 of 308 strings)

Translated using Weblate (Hungarian)

Currently translated at 97.4% (300 of 308 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-03-10 06:15:45 +00:00
Weblate
7488209544 Translated using Weblate (Hungarian)
Currently translated at 96.1% (296 of 308 strings)

Translated using Weblate (Hungarian)

Currently translated at 96.1% (296 of 308 strings)

Translated using Weblate (Hungarian)

Currently translated at 96.1% (296 of 308 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-03-10 06:14:34 +00:00
Weblate
23771e1118 Translated using Weblate (Hungarian)
Currently translated at 94.8% (292 of 308 strings)

Translated using Weblate (Hungarian)

Currently translated at 94.8% (292 of 308 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-03-10 06:14:15 +00:00
Weblate
91cfadf834 Translated using Weblate (Hungarian)
Currently translated at 93.8% (289 of 308 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (308 of 308 strings)

Co-authored-by: Erwin van Londen <translate.sysadminsm.treachery437@passmail.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-03-10 06:13:50 +00:00
Weblate
88086a377b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.0% (302 of 308 strings)

Co-authored-by: Cheng Gu <guchengf@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-03-10 02:45:08 +00:00
Weblate
b082ab46b8 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.3% (303 of 308 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-03-10 02:20:20 +00:00
EdWorth120
3baf1a5c92 Fix the parent location being undefined when set while the locationStore is empty. (#571) 2025-03-09 10:30:56 -04:00
EdWorth120
6797fcb58f Try to choose a media device that have the word "back" in it, if it doesn't find one falls back to the first. (#573) 2025-03-09 10:28:30 -04:00
Matt Kilgore
9fe509215d feat: Add goreleaser cosign signing (#562) 2025-03-08 19:01:03 -05:00
Weblate
66654ab565 Translated using Weblate (Japanese)
Currently translated at 92.8% (286 of 308 strings)

Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-03-08 12:35:32 +00:00
dependabot[bot]
543c947d93 Bump vue-i18n in /frontend in the npm_and_yarn group across 1 directory (#567)
Bumps the npm_and_yarn group with 1 update in the /frontend directory: [vue-i18n](https://github.com/intlify/vue-i18n/tree/HEAD/packages/vue-i18n).


Updates `vue-i18n` from 9.14.2 to 9.14.3
- [Release notes](https://github.com/intlify/vue-i18n/releases)
- [Changelog](https://github.com/intlify/vue-i18n/blob/v9.14.3/CHANGELOG.md)
- [Commits](https://github.com/intlify/vue-i18n/commits/v9.14.3/packages/vue-i18n)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-07 16:14:54 -05:00
Weblate
0e190af9c9 Translated using Weblate (Czech)
Currently translated at 100.0% (308 of 308 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (308 of 308 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (308 of 308 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 98.0% (302 of 308 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: cclassbreak <hsiungfei@outlook.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-03-07 13:35:32 +00:00
Weblate
f2bde0be2f Translated using Weblate (Slovak)
Currently translated at 100.0% (308 of 308 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.0% (299 of 308 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.0% (299 of 308 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.0% (299 of 308 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.0% (299 of 308 strings)

Co-authored-by: Daniel Zanardi de Souza <zz.uploader@gmail.com>
Co-authored-by: Lucas Duete <lm.duete@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: euforik <euforik22@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translation: Homebox/Frontend
2025-03-06 00:35:32 +00:00
Katos
618f305f50 Update index.md
Amend link for tips and tricks
2025-03-05 20:08:53 +00:00
Weblate
8b9b1bdad0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 95.7% (295 of 308 strings)

Translated using Weblate (Swedish)

Currently translated at 92.5% (285 of 308 strings)

Translated using Weblate (Swedish)

Currently translated at 92.5% (285 of 308 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Rasmus Åberg <rasabergnv@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translation: Homebox/Frontend
2025-03-05 20:04:06 +00:00
Matt Kilgore
3a3280466e Merge VNEXT into Main (#464)
* [VNEXT] feat: Multi-DB type support (#291)

* feat: Multi-DB type URL formats and config

* fix: remove legacy sqlite path config and minor other things

* fix: dumb eslint issues

* fix: dumb eslint issues

* fix: application can be tested with sqlite

* fix: minor config formatting

* chore: some cleanup

* feat: postgres migration creation now works

The migration creation for postgres now works properly.
Removed MySQL support, having too many issues with it at this time.

* chore: revert some strings back to bytes as they should be

* feat: improve languages support

* feat: add locale time ago formatting and the local name for the language in language dropdown

* Update FUNDING.yml

* chore: remove some more mysql stuff

* fix: coderabbit security recommendations

* fix: validate postgres sslmode

* Update migrations.go

* fix: postgres migration creation now works

* fix: errors in raw sql queries

* fix: lint error, and simpler SQL query

* fix: migrations directory string

* fix: stats related test

* fix: sql query

* Update TextArea.vue

* Update TextField.vue

* chore: run integration testing on multiple postgresql versions

* chore: jobs should run for vnext branch PRs

* fix: missed $ for Postgres testing

* fix: environment variable for db ssl mode

* fix: lint issue from a merge

* chore: trying to fix postgresql testing

* chore: trying to fix postgresql testing

* fix: trying to fix postgresql testing

* fix: trying to fix postgresql testing

---------

Co-authored-by: tonya <tonya@tokia.dev>

* fix: publish docker vnext branch

* Add upgrade guide documentation

* chore: add new config options to documentation

* Update vnext (#314)

* feat: make 404 follow theme and add a return home page

* feat: sanitise translations when using v-html

* chore: Add native API docs to website

* chore: remove try it button from api docs

---------

Co-authored-by: tonyaellie <tonya@tokia.dev>

* Update Dockerfile

Update dockerfile to test the theory of data folder breaking in vnext

* fix: broken docker image

* fix: statistics

* feat: support mm, cm and inches for label generation

* [VNEXT] feat: Multi-DB type support (#291)

* feat: Multi-DB type URL formats and config

* fix: remove legacy sqlite path config and minor other things

* fix: dumb eslint issues

* fix: dumb eslint issues

* fix: application can be tested with sqlite

* fix: minor config formatting

* chore: some cleanup

* feat: postgres migration creation now works

The migration creation for postgres now works properly.
Removed MySQL support, having too many issues with it at this time.

* chore: revert some strings back to bytes as they should be

* feat: improve languages support

* feat: add locale time ago formatting and the local name for the language in language dropdown

* Update FUNDING.yml

* chore: remove some more mysql stuff

* fix: coderabbit security recommendations

* fix: validate postgres sslmode

* Update migrations.go

* fix: postgres migration creation now works

* fix: errors in raw sql queries

* fix: lint error, and simpler SQL query

* fix: migrations directory string

* fix: stats related test

* fix: sql query

* Update TextArea.vue

* Update TextField.vue

* chore: run integration testing on multiple postgresql versions

* chore: jobs should run for vnext branch PRs

* fix: missed $ for Postgres testing

* fix: environment variable for db ssl mode

* fix: lint issue from a merge

* chore: trying to fix postgresql testing

* chore: trying to fix postgresql testing

* fix: trying to fix postgresql testing

* fix: trying to fix postgresql testing

---------

Co-authored-by: tonya <tonya@tokia.dev>

* fix: publish docker vnext branch

* Add upgrade guide documentation

* chore: add new config options to documentation

* Update Dockerfile

Update dockerfile to test the theory of data folder breaking in vnext

* fix: broken docker image

* fix: statistics

* feat: support mm, cm and inches for label generation

* Update go dependencies

* Update documentation

* Slight update to docker actions

* Small doc update

* More doc changes

* Sort out migrations

* Temp fix to broken stats test

* Update dependencies

* Update documentation

* Fix broken merge

* Fix docker image sqlite path

* Fix minor taskfile issue

---------

Co-authored-by: tonya <tonya@tokia.dev>
Co-authored-by: Katos <7927609+katosdev@users.noreply.github.com>
2025-03-04 08:16:17 -05:00
Matthew Kilgore
33ecc49ad7 Deleted translation using Weblate (English (Pirate)) 2025-03-04 02:41:07 +00:00
Weblate
87c0392148 Added translation using Weblate (English (Pirate))
Translated using Weblate (English)

Currently translated at 100.0% (308 of 308 strings)

Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translation: Homebox/Frontend
2025-03-04 02:40:17 +00:00
Weblate
8b47217d7c Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/
Translation: Homebox/Frontend
2025-03-04 02:37:21 +00:00
Matt Kilgore
6b06215967 Update en.json 2025-03-03 21:37:17 -05:00
Weblate
2e281aec8d Translated using Weblate (English)
Currently translated at 100.0% (303 of 303 strings)

Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translation: Homebox/Frontend
2025-03-04 02:31:08 +00:00
Weblate
9aa147fdf1 Translated using Weblate (English)
Currently translated at 100.0% (303 of 303 strings)

Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translation: Homebox/Frontend
2025-03-04 02:27:42 +00:00
Weblate
aac0d04254 Translated using Weblate (English)
Currently translated at 100.0% (302 of 302 strings)

Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translation: Homebox/Frontend
2025-03-04 02:27:36 +00:00
Matt Kilgore
d927bc238f Update items.vue 2025-03-03 09:57:26 -05:00
Weblate
3900dc7442 Translated using Weblate (Tamil)
Currently translated at 2.3% (7 of 302 strings)

Co-authored-by: Venkatasubramanian B <bvenkysubbu@yahoo.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ta/
Translation: Homebox/Frontend
2025-03-03 09:35:32 +00:00
Weblate
ba6f8ed2bd Added translation using Weblate (Tamil)
Co-authored-by: Venkatasubramanian B <bvenkysubbu@yahoo.com>
2025-03-03 05:08:33 +00:00
Weblate
bb102fd9f6 Translated using Weblate (Japanese)
Currently translated at 95.0% (287 of 302 strings)

Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-28 11:35:32 +00:00
Weblate
0e46e3c827 Translated using Weblate (Indonesian)
Currently translated at 94.3% (285 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translation: Homebox/Frontend
2025-02-26 21:35:32 +00:00
Weblate
7bcf7f0845 Added translation using Weblate (Korean)
Co-authored-by: eejun49 <dldmlwns49@naver.com>
2025-02-24 07:03:20 +00:00
Weblate
53f1476185 Translated using Weblate (Japanese)
Currently translated at 95.0% (287 of 302 strings)

Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-23 12:35:32 +00:00
Weblate
b846157c65 Translated using Weblate (French)
Currently translated at 99.3% (300 of 302 strings)

Co-authored-by: Jean-Philippe Baril <translate.sysadminsmedia.com@alias.trebaxis.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-02-23 04:25:49 +00:00
Weblate
08854316f9 Translated using Weblate (French)
Currently translated at 99.3% (300 of 302 strings)

Translated using Weblate (French)

Currently translated at 99.3% (300 of 302 strings)

Co-authored-by: Jean-Philippe Baril <translate.sysadminsmedia.com@alias.trebaxis.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-02-23 03:32:10 +00:00
Weblate
b76b6dbd5a Translated using Weblate (French)
Currently translated at 99.0% (299 of 302 strings)

Translated using Weblate (French)

Currently translated at 99.0% (299 of 302 strings)

Translated using Weblate (French)

Currently translated at 99.0% (299 of 302 strings)

Co-authored-by: Jean-Philippe Baril <translate.sysadminsmedia.com@alias.trebaxis.net>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translation: Homebox/Frontend
2025-02-23 03:30:35 +00:00
EdWorth120
20e34e3428 Change the width of the items quantity badge to not be fixed. (#525) 2025-02-22 16:15:28 -05:00
thevortexcloud
fe31847269 Allow miltiple file uploads on creation (#528)
* Fix #317

* Fix(?) lint errors

* Actually fix all the lint errors

* Fix type check errors
2025-02-22 16:15:08 -05:00
Weblate
08d9de0b44 Translated using Weblate (Japanese)
Currently translated at 95.0% (287 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 95.0% (287 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 14:35:32 +00:00
Weblate
efb2f1f945 Translated using Weblate (Japanese)
Currently translated at 83.7% (253 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 83.7% (253 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:42:36 +00:00
Weblate
114410c530 Translated using Weblate (Japanese)
Currently translated at 83.1% (251 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 83.1% (251 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:41:09 +00:00
Weblate
0c5c5f6994 Translated using Weblate (Japanese)
Currently translated at 80.7% (244 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 80.7% (244 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:35:28 +00:00
Weblate
d5dadb27f1 Translated using Weblate (Japanese)
Currently translated at 74.5% (225 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 74.5% (225 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:20:59 +00:00
Weblate
88ad6e8505 Translated using Weblate (Japanese)
Currently translated at 74.1% (224 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 74.1% (224 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:20:40 +00:00
Weblate
5700a73bf4 Translated using Weblate (Japanese)
Currently translated at 72.1% (218 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 72.1% (218 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:08:22 +00:00
Weblate
d5bf6d5c62 Translated using Weblate (Japanese)
Currently translated at 71.8% (217 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 71.8% (217 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:07:14 +00:00
Weblate
c622c96568 Translated using Weblate (Japanese)
Currently translated at 70.8% (214 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:06:53 +00:00
Weblate
c935ca30ab Translated using Weblate (Japanese)
Currently translated at 70.8% (214 of 302 strings)

Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:06:50 +00:00
Weblate
0b6571ba36 Translated using Weblate (Japanese)
Currently translated at 70.1% (212 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 70.1% (212 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:04:16 +00:00
Weblate
94c8478863 Translated using Weblate (Japanese)
Currently translated at 69.8% (211 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 69.8% (211 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 69.8% (211 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:03:59 +00:00
Weblate
9f8243b71c Translated using Weblate (Japanese)
Currently translated at 68.8% (208 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 68.8% (208 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 09:02:04 +00:00
Weblate
d4890b08de Translated using Weblate (Japanese)
Currently translated at 67.5% (204 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 67.5% (204 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 08:59:15 +00:00
Weblate
db58ea5f66 Translated using Weblate (Japanese)
Currently translated at 67.2% (203 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 67.2% (203 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 08:58:12 +00:00
Weblate
4a773d56ba Translated using Weblate (Japanese)
Currently translated at 63.9% (193 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 63.9% (193 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 08:47:33 +00:00
Weblate
9fae285e76 Translated using Weblate (Japanese)
Currently translated at 60.5% (183 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 60.5% (183 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 08:22:12 +00:00
Weblate
3539b5229a Translated using Weblate (Japanese)
Currently translated at 59.2% (179 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 08:09:21 +00:00
Weblate
492af54aa5 Translated using Weblate (Japanese)
Currently translated at 58.9% (178 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 58.9% (178 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 08:08:21 +00:00
Weblate
56a2ccf687 Translated using Weblate (Japanese)
Currently translated at 50.9% (154 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 50.9% (154 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 07:49:18 +00:00
Weblate
65ebf3ce11 Translated using Weblate (Japanese)
Currently translated at 50.6% (153 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 50.6% (153 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 07:46:36 +00:00
Weblate
e5aa0954ba Translated using Weblate (Japanese)
Currently translated at 49.6% (150 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-21 07:45:07 +00:00
Weblate
0a9fad3e61 Translated using Weblate (Japanese)
Currently translated at 49.6% (150 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 49.6% (150 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 19:35:32 +00:00
Weblate
2e53b8a8b6 Translated using Weblate (Japanese)
Currently translated at 48.6% (147 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 48.6% (147 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 15:00:52 +00:00
Weblate
52802a9532 Translated using Weblate (Japanese)
Currently translated at 46.6% (141 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 46.6% (141 of 302 strings)

Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 14:24:40 +00:00
Weblate
a18466ef17 Translated using Weblate (Japanese)
Currently translated at 45.6% (138 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 45.6% (138 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 14:05:36 +00:00
Weblate
80256fc2b1 Translated using Weblate (Japanese)
Currently translated at 39.0% (118 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 39.0% (118 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 12:57:09 +00:00
Weblate
e1d3087403 Translated using Weblate (Japanese)
Currently translated at 34.4% (104 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 34.4% (104 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 12:44:46 +00:00
Weblate
8e4a223441 Translated using Weblate (Japanese)
Currently translated at 32.1% (97 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 32.1% (97 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 12:39:58 +00:00
Weblate
8b03d5bf61 Translated using Weblate (Japanese)
Currently translated at 31.4% (95 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 31.4% (95 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 12:37:38 +00:00
Weblate
53d3d53292 Translated using Weblate (Japanese)
Currently translated at 29.1% (88 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 29.1% (88 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 11:47:18 +00:00
Weblate
56c0c5e9ad Translated using Weblate (Japanese)
Currently translated at 27.8% (84 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 27.8% (84 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 11:44:18 +00:00
Weblate
ea06de9d2d Translated using Weblate (Japanese)
Currently translated at 24.5% (74 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 24.5% (74 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 11:01:42 +00:00
Weblate
aa66f93444 Translated using Weblate (Japanese)
Currently translated at 24.1% (73 of 302 strings)

Translated using Weblate (Japanese)

Currently translated at 24.1% (73 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 11:01:23 +00:00
Weblate
d6cf844946 Translated using Weblate (Japanese)
Currently translated at 18.8% (57 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 10:03:17 +00:00
Weblate
706545ae84 Translated using Weblate (Japanese)
Currently translated at 18.8% (57 of 302 strings)

Co-authored-by: ななしぃ <weblate@nanasi-rasi.net>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ja/
Translation: Homebox/Frontend
2025-02-20 10:02:54 +00:00
Weblate
4e31e17b13 Translated using Weblate (Czech)
Currently translated at 100.0% (302 of 302 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (302 of 302 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-02-19 21:51:43 +00:00
Weblate
b7959bb2d5 Translated using Weblate (Czech)
Currently translated at 90.3% (273 of 302 strings)

Translated using Weblate (Czech)

Currently translated at 90.3% (273 of 302 strings)

Translated using Weblate (Czech)

Currently translated at 90.3% (273 of 302 strings)

Co-authored-by: Adam Havránek <adamhavra@seznam.cz>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translation: Homebox/Frontend
2025-02-19 21:21:30 +00:00
Weblate
6c7910661e Translated using Weblate (Danish)
Currently translated at 100.0% (302 of 302 strings)

Co-authored-by: Heine Olsen <olsen10051988@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/da/
Translation: Homebox/Frontend
2025-02-18 18:35:32 +00:00
Weblate
ba8005929b Translated using Weblate (Spanish)
Currently translated at 100.0% (302 of 302 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (302 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-02-18 02:35:32 +00:00
Weblate
c6ed191d3d Translated using Weblate (Spanish)
Currently translated at 97.0% (293 of 302 strings)

Translated using Weblate (Spanish)

Currently translated at 97.0% (293 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translation: Homebox/Frontend
2025-02-17 21:47:11 +00:00
Matthew Kilgore
ece75e2984 chore: Remove aside from configure page. It doesn't make sense there. 2025-02-16 22:42:16 -05:00
Matthew Kilgore
817058bc70 fix: broken page rendering 2025-02-16 22:30:47 -05:00
kylehakala
8e46553a0d Add additional documentation for Notifiers (#530)
* Add additional documentation for Notifiers

When I first set up the notifiers, I felt like the documentation was pretty light on how to do this. 

I'd like to submit a few more PRs to outline a couple basic examples on this page (or a separate page specific for notifications) in addition to elaborating more on how this feature works. It's super flexible, and I love that!

Nevertheless, I think it would be more accessible to outline a few examples on what this ends up entailing.

* User general/latest shoutrrr URL without hardcoded version
2025-02-16 16:58:10 -05:00
Weblate
c4edb81fdd Translated using Weblate (Swedish)
Currently translated at 93.3% (282 of 302 strings)

Co-authored-by: jesper rezler lang <jesper.rezler.lang@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translation: Homebox/Frontend
2025-02-14 12:35:32 +00:00
dependabot[bot]
56ec06516d Bump koa in /frontend in the npm_and_yarn group across 1 directory (#524)
Bumps the npm_and_yarn group with 1 update in the /frontend directory: [koa](https://github.com/koajs/koa).


Updates `koa` from 2.15.3 to 2.15.4
- [Release notes](https://github.com/koajs/koa/releases)
- [Changelog](https://github.com/koajs/koa/blob/2.15.4/History.md)
- [Commits](https://github.com/koajs/koa/compare/2.15.3...2.15.4)

---
updated-dependencies:
- dependency-name: koa
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-13 11:02:45 -05:00
Webysther Sperandio
d62d55a42f Fix screen large items (#472)
* Update Container.vue to allow max 7 for xl

* Update items.vue to allow 5 cols to large screen

* Change to use pageSize to 30

Least common multiple is 30 for cols if 2, 3 or 5.

---------

Co-authored-by: Matt Kilgore <tankerkiller125@users.noreply.github.com>
2025-02-12 08:42:38 -05:00
Weblate
81d3ddc362 Translated using Weblate (Italian)
Currently translated at 100.0% (302 of 302 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (302 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-02-12 04:48:46 +00:00
Weblate
17e355d180 Translated using Weblate (Romanian)
Currently translated at 94.3% (285 of 302 strings)

Translated using Weblate (Italian)

Currently translated at 97.6% (295 of 302 strings)

Translated using Weblate (Italian)

Currently translated at 97.6% (295 of 302 strings)

Translated using Weblate (Italian)

Currently translated at 97.6% (295 of 302 strings)

Co-authored-by: Aurelian Zanoschi <aurelian17@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: alexdelli <alexdelli@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ro/
Translation: Homebox/Frontend
2025-02-12 00:48:00 +00:00
Weblate
5ca174fbc6 Translated using Weblate (German)
Currently translated at 100.0% (302 of 302 strings)

Co-authored-by: Sebastian <homeboxtranslate@sschefold.de>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-02-11 12:22:40 +00:00
Weblate
337a55fae9 Translated using Weblate (German)
Currently translated at 100.0% (302 of 302 strings)

Translated using Weblate (German)

Currently translated at 100.0% (302 of 302 strings)

Translated using Weblate (German)

Currently translated at 100.0% (302 of 302 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Sebastian <homeboxtranslate@sschefold.de>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-02-11 10:22:50 +00:00
Weblate
f0803f54af Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.3% (291 of 302 strings)

Co-authored-by: EdWorth120 <coragem.o.cao.covarde.81@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translation: Homebox/Frontend
2025-02-11 04:48:46 +00:00
Weblate
0a71a8ecaf Translated using Weblate (Polish)
Currently translated at 100.0% (302 of 302 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (302 of 302 strings)

Co-authored-by: PavulonGit <pavulongit@users.noreply.translate.sysadminsmedia.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pl/
Translation: Homebox/Frontend
2025-02-10 22:48:47 +00:00
Weblate
58fcc85a9c Translated using Weblate (Dutch)
Currently translated at 100.0% (302 of 302 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (302 of 302 strings)

Co-authored-by: 101br03k <warmerdamm03@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-02-10 11:48:46 +00:00
Weblate
a5c1799445 Translated using Weblate (Dutch)
Currently translated at 97.3% (294 of 302 strings)

Translated using Weblate (Dutch)

Currently translated at 97.3% (294 of 302 strings)

Translated using Weblate (Dutch)

Currently translated at 97.3% (294 of 302 strings)

Co-authored-by: 101br03k <warmerdamm03@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-02-10 07:11:25 +00:00
Weblate
ee221c8ca1 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 97.0% (293 of 302 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 97.0% (293 of 302 strings)

Co-authored-by: Cheng Gu <guchengf@gmail.com>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-02-10 06:48:46 +00:00
fidoriel
9a57ada534 Additional information on label, dynamic label layouting (#522) 2025-02-09 20:39:23 -05:00
fidoriel
7ddfa72936 Fix labelmaker wrong defaults in docs (#520) 2025-02-09 15:59:10 -05:00
fidoriel
f9bffad1d7 Fix labelmaker font size mixed up (#521) 2025-02-09 15:58:55 -05:00
tonyaellie
fe50ff982e feat: add head and middleware to maintenance page 2025-02-09 16:28:47 +00:00
dependabot[bot]
f11f12fac2 Bump the npm_and_yarn group across 2 directories with 4 updates (#517)
Bumps the npm_and_yarn group with 3 updates in the / directory: [nanoid](https://github.com/ai/nanoid), [rollup](https://github.com/rollup/rollup) and [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).
Bumps the npm_and_yarn group with 2 updates in the /frontend directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `nanoid` from 3.3.7 to 3.3.8
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.8)

Updates `rollup` from 4.21.2 to 4.34.6
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.21.2...v4.34.6)

Updates `vite` from 5.4.3 to 5.4.14
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.14/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.14/packages/vite)

Updates `vite` from 5.4.11 to 5.4.14
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.14/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.14/packages/vite)

Updates `vitest` from 1.6.0 to 1.6.1
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v1.6.1/packages/vitest)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: rollup
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: vite
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: vite
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: vitest
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-08 22:25:58 -05:00
Jake Walker
fba6d7817a add label generation api (#498)
* add label generation api

* show location name on labels

* add label scan page

* dispose of code reader when navigating away from scan page

* save label to png

* implement code suggestions

* fix label padding and margin

* update swagger docs

* add print from browser dialog

Co-authored-by: fidoriel <49869342+fidoriel@users.noreply.github.com>

* increase label description font weight

* update documentation label file suffix

* fix scanner components import

* fix linting issues

---------

Co-authored-by: fidoriel <49869342+fidoriel@users.noreply.github.com>
2025-02-08 21:26:16 -05:00
zawnk
401fd7fc71 Fix file upload size env in installation.md (#514) 2025-02-08 13:43:54 -05:00
Weblate
c84504b1e1 Translated using Weblate (Dutch)
Currently translated at 100.0% (290 of 290 strings)

Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-02-08 15:48:46 +00:00
Weblate
9886cb5495 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (290 of 290 strings)

Co-authored-by: Gustavo Souza <gustavobat.gb@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translation: Homebox/Frontend
2025-02-06 19:48:46 +00:00
Weblate
768b4123b8 Translated using Weblate (Russian)
Currently translated at 99.6% (289 of 290 strings)

Translated using Weblate (Russian)

Currently translated at 99.6% (289 of 290 strings)

Co-authored-by: Ivan Davydov <lotigara@lotigara.ru>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ru/
Translation: Homebox/Frontend
2025-02-06 14:48:46 +00:00
Weblate
3db6719fcf Translated using Weblate (Indonesian)
Currently translated at 97.9% (284 of 290 strings)

Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translation: Homebox/Frontend
2025-02-05 06:48:46 +00:00
Weblate
e48919181b Translated using Weblate (Indonesian)
Currently translated at 97.9% (284 of 290 strings)

Translated using Weblate (Indonesian)

Currently translated at 97.9% (284 of 290 strings)

Translated using Weblate (Russian)

Currently translated at 98.6% (286 of 290 strings)

Translated using Weblate (French)

Currently translated at 100.0% (290 of 290 strings)

Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: askolock <askolock@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ru/
Translation: Homebox/Frontend
2025-02-04 17:48:46 +00:00
Weblate
e0b39ce3fd Translated using Weblate (Indonesian)
Currently translated at 93.7% (272 of 290 strings)

Translated using Weblate (Indonesian)

Currently translated at 93.7% (272 of 290 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 98.9% (287 of 290 strings)

Translated using Weblate (Russian)

Currently translated at 98.6% (286 of 290 strings)

Co-authored-by: Cheng Gu <guchengf@gmail.com>
Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: askolock <askolock@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ru/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-02-04 12:55:41 +00:00
Weblate
e9ffc7954b Translated using Weblate (Indonesian)
Currently translated at 90.6% (263 of 290 strings)

Translated using Weblate (Indonesian)

Currently translated at 90.6% (263 of 290 strings)

Translated using Weblate (Russian)

Currently translated at 96.8% (281 of 290 strings)

Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: askolock <askolock@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/ru/
Translation: Homebox/Frontend
2025-02-04 12:45:58 +00:00
Weblate
29f52ab47d Translated using Weblate (Indonesian)
Currently translated at 86.8% (252 of 290 strings)

Translated using Weblate (Indonesian)

Currently translated at 86.8% (252 of 290 strings)

Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translation: Homebox/Frontend
2025-02-04 12:42:31 +00:00
Weblate
bc8c31cabc Translated using Weblate (Indonesian)
Currently translated at 85.8% (249 of 290 strings)

Translated using Weblate (Indonesian)

Currently translated at 85.8% (249 of 290 strings)

Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translation: Homebox/Frontend
2025-02-04 12:41:38 +00:00
Weblate
126dcd1402 Translated using Weblate (Indonesian)
Currently translated at 39.3% (114 of 290 strings)

Translated using Weblate (Indonesian)

Currently translated at 39.3% (114 of 290 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (290 of 290 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (290 of 290 strings)

Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: PavulonGit <pavulongit@users.noreply.translate.sysadminsmedia.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pl/
Translation: Homebox/Frontend
2025-02-04 10:24:18 +00:00
Weblate
d4c8573916 Translated using Weblate (Indonesian)
Currently translated at 37.5% (109 of 290 strings)

Translated using Weblate (Indonesian)

Currently translated at 37.5% (109 of 290 strings)

Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translation: Homebox/Frontend
2025-02-04 10:17:27 +00:00
Weblate
90c07f13d9 Translated using Weblate (Indonesian)
Currently translated at 35.5% (103 of 290 strings)

Translated using Weblate (Indonesian)

Currently translated at 35.5% (103 of 290 strings)

Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/id/
Translation: Homebox/Frontend
2025-02-04 10:10:32 +00:00
Weblate
f93de9cd1d Added translation using Weblate (Indonesian)
Co-authored-by: Muhammad Ikhsan <pararang@gmail.com>
2025-02-04 09:37:52 +00:00
Weblate
7c37c4dbeb Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (290 of 290 strings)

Translated using Weblate (German)

Currently translated at 100.0% (290 of 290 strings)

Co-authored-by: EdWorth120 <coragem.o.cao.covarde.81@gmail.com>
Co-authored-by: supaeasy <ismo+github@wolffson.ch>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translation: Homebox/Frontend
2025-02-03 22:48:46 +00:00
Weblate
9446cb4f91 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (290 of 290 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (290 of 290 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (290 of 290 strings)

Co-authored-by: Christer Solstrand Johannessen <weblate@csj.no>
Co-authored-by: Fernando Martín <fer.martyni@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nb_NO/
Translation: Homebox/Frontend
2025-02-03 15:48:46 +00:00
Weblate
080d173778 Translated using Weblate (Slovenian)
Currently translated at 100.0% (290 of 290 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (290 of 290 strings)

Co-authored-by: 101br03k <warmerdamm03@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-02-03 10:48:46 +00:00
Weblate
428d4bb2fa Translated using Weblate (Slovenian)
Currently translated at 100.0% (290 of 290 strings)

Translated using Weblate (Slovenian)

Currently translated at 100.0% (290 of 290 strings)

Translated using Weblate (English)

Currently translated at 100.0% (290 of 290 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: stegl <primsteg@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translation: Homebox/Frontend
2025-02-03 05:52:07 +00:00
Weblate
787a7c86c0 Translated using Weblate (German)
Currently translated at 100.0% (290 of 290 strings)

Translated using Weblate (German)

Currently translated at 100.0% (290 of 290 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: supaeasy <ismo+github@wolffson.ch>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translation: Homebox/Frontend
2025-02-03 00:48:46 +00:00
EdWorth120
e9f8a235d4 Fix the problem of the fixed height in the background of the location badge in the item cards (#479)
* Fix the problem of the fixed height in the background of the location badge above the photo in the item cards.

* Corrected linter complaint.

---------

Co-authored-by: Matt Kilgore <tankerkiller125@users.noreply.github.com>
Co-authored-by: Katos <7927609+katosdev@users.noreply.github.com>
2025-02-02 12:03:57 -05:00
tonyaellie
d71da5f1ee fix: login page tailwind 2025-02-02 00:11:43 +00:00
Tonya
e708bd9839 Begin switching from daisyui to shadcnui (#492)
* feat: add shadcn

* feat: add themes

* feat: make sidebar use shadcn

* feat: sort bg

* feat: lint fixes

* feat: make daisyui toggleable, add tooltips to sidebar, add work in progress docs page

* fix: theme switching for shadcn

* Fix minor profile.vue issue

* feat: update docs, enlarge SidebarMenuButton and refine profile layout

* feat: add testing page

* feat: update css and remove comments from template

* fix: create dropdown not opening due to tooltip interference also lint

* fix: correct CSS selector for homebox in main.css to ensure proper theming functionality

* feat: make theme switching actually kinda work for shadcn

* fix: sidebar colours

* fix: remove unused router import, made sidebar indicate active page and sort tailwind config linting

* style: update styles

* chore: remove unused duplicate code

* style: refine theme management, CSS variables, get styles closer to original

* feat: implement suggested changes

* feat: better button size

---------

Co-authored-by: Matt Kilgore <tankerkiller125@users.noreply.github.com>
2025-02-01 10:32:10 +00:00
Matt Kilgore
574079437a Update label-generator.vue 2025-01-28 14:52:41 -05:00
Matt Kilgore
a262ff9628 Attempt to fix label generation issue 2025-01-28 14:45:20 -05:00
zebrapurring
b22a49a0fd feat: add search filter for items with no photo (#383)
* feat: add search filter for items without photos

* chore: configure Golang formatter for VSCode

* fix: displaying long filter labels for some locales

* feat: add search filter for items with photos

* test: fix linter errors

* chore: remove redundant height attribute

* fix: make with/without photo filters mutually exclusive

---------

Co-authored-by: zebrapurring <>
2025-01-27 23:00:24 +00:00
Matthew Kilgore
743be2fb2c Ignore cache push errors 2025-01-26 13:44:26 -05:00
Matthew Kilgore
21f9dadbb0 Fix only push for actual branches, not PRs 2025-01-26 13:35:02 -05:00
Matthew Kilgore
8ddf291c5d Run all the linters 2025-01-26 13:31:33 -05:00
Matthew Kilgore
18adac6620 Only push on actual project branches, PRs do not get pushed 2025-01-26 13:24:19 -05:00
Corknut
fca7d24268 Creation modal quality of life changes (#467)
Co-authored-by: Matt Kilgore <tankerkiller125@users.noreply.github.com>
Co-authored-by: Tonya <tonya@tokia.dev>
2025-01-26 12:43:45 +00:00
Weblate
96d88c5728 Translated using Weblate (English)
Currently translated at 100.0% (288 of 288 strings)

Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translation: Homebox/Frontend
2025-01-25 21:48:46 +00:00
Katos
d5b9d52f6e Roll back to token 2025-01-25 21:21:00 +00:00
Katos
4931535d0b Test action with a PAT 2025-01-25 21:14:42 +00:00
Katos
7e9a97789e Update docker-publish.yaml 2025-01-25 21:03:55 +00:00
Katos
28fa843317 Update docker-publish-rootless.yaml 2025-01-25 21:03:40 +00:00
Katos
5db1dec3e9 Enable debug temporarily 2025-01-25 20:54:38 +00:00
Matt Kilgore
c9f3e6c77b Trying to fix builds (#480)
* Try to fix builds for PRs

* Some things I forgot about

* Fix missing quote

* Reverse the merge qualifier

* Don't inspect the non-existing dockerhub repo

* Try a slightly different merge

* Try a slightly different merge

* Try this again? WTF Github Actions

* Get rid of inspections, it doesn't really do anything

* Fix a bash if statement (bash is horrible)

* Don't even login on merge for Dockerhub if pull request

* Try breaking up the push into seperate parts

* Fix copy paste error

* You shall bend to my will!
2025-01-25 11:18:24 -05:00
tonyaellie
8231e13127 fix: type error 2025-01-24 22:48:18 +00:00
tonyaellie
28a9291769 fix: use .value 2025-01-23 22:30:50 +00:00
Katos
86466229cb Update README.md
Force a currency sync
2025-01-23 07:36:46 +00:00
FjellOverflow
a6b25f7a1c Fix flash of wrong theme on initial UI load (#485)
Co-authored-by: Tonya <tonya@tokia.dev>
2025-01-23 01:29:19 +00:00
EdWorth120
f317bb6d88 Change the tag of loading="lazy" attribute placement for it to work properly on item images. (#486) 2025-01-23 01:13:09 +00:00
Matt Kilgore
a1dabaa5b6 Update devcontainer.json
Some checks failed
Update Currencies / update-currencies (push) Has been cancelled
Docker publish / build (linux/amd64) (push) Has been cancelled
Docker publish / build (linux/arm/v7) (push) Has been cancelled
Docker publish / build (linux/arm64) (push) Has been cancelled
Docker publish rootless / build (linux/amd64) (push) Has been cancelled
Docker publish rootless / build (linux/arm/v7) (push) Has been cancelled
Docker publish rootless / build (linux/arm64) (push) Has been cancelled
Docker Cleanup / Delete Untagged Images (push) Has been cancelled
Docker Cleanup / Delete Cache Old Images (push) Has been cancelled
Docker publish / merge (push) Has been cancelled
Docker publish rootless / merge (push) Has been cancelled
2025-01-18 15:03:40 -05:00
Matt Kilgore
918618b720 Update devcontainer.json 2025-01-18 15:03:32 -05:00
Matt Kilgore
e79300c646 Update Dockerfile 2025-01-18 15:03:16 -05:00
Matt Kilgore
dd0164eb20 Update Dockerfile 2025-01-18 14:50:17 -05:00
Matt Kilgore
1cdf4ff505 Update Dockerfile 2025-01-18 14:48:19 -05:00
Matthew Kilgore
e533fd7770 Fix broken version links
Some checks failed
Docker publish rootless / build (linux/amd64) (push) Has been cancelled
Docker publish rootless / build (linux/arm/v7) (push) Has been cancelled
Docker publish rootless / build (linux/arm64) (push) Has been cancelled
Docker publish / build (linux/amd64) (push) Has been cancelled
Docker publish / build (linux/arm/v7) (push) Has been cancelled
Docker publish / build (linux/arm64) (push) Has been cancelled
Update Currencies / update-currencies (push) Has been cancelled
Docker publish rootless / merge (push) Has been cancelled
Docker publish / merge (push) Has been cancelled
2025-01-16 20:29:25 -05:00
Weblate
155fd5d17f Translated using Weblate (Chinese (Simplified) (zh_MO))
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Docker publish / build (linux/amd64) (push) Waiting to run
Docker publish / build (linux/arm/v7) (push) Waiting to run
Docker publish / build (linux/arm64) (push) Waiting to run
Docker publish / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
Currently translated at 33.3% (96 of 288 strings)

Translated using Weblate (Chinese (Simplified) (zh_MO))

Currently translated at 33.3% (96 of 288 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: wangwb <im.wangwb@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_MO/
Translation: Homebox/Frontend
2025-01-16 03:31:05 +00:00
Webysther Sperandio
1354242f38 Add link to release page (#471)
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Docker publish / build (linux/amd64) (push) Waiting to run
Docker publish / build (linux/arm/v7) (push) Waiting to run
Docker publish / build (linux/arm64) (push) Waiting to run
Docker publish / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
* Add link to release page

* Add API docs
2025-01-15 16:14:20 -05:00
Weblate
603a89d723 Translated using Weblate (French)
Some checks failed
Docker publish rootless / build (linux/amd64) (push) Has been cancelled
Docker publish rootless / build (linux/arm/v7) (push) Has been cancelled
Docker publish rootless / build (linux/arm64) (push) Has been cancelled
Docker publish / build (linux/amd64) (push) Has been cancelled
Docker publish / build (linux/arm/v7) (push) Has been cancelled
Docker publish / build (linux/arm64) (push) Has been cancelled
Update Currencies / update-currencies (push) Has been cancelled
Docker publish rootless / merge (push) Has been cancelled
Docker publish / merge (push) Has been cancelled
Currently translated at 100.0% (288 of 288 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (288 of 288 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translation: Homebox/Frontend
2025-01-14 01:48:46 +00:00
Weblate
a5e7c51e0f Translated using Weblate (Polish)
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Docker publish / build (linux/amd64) (push) Waiting to run
Docker publish / build (linux/arm/v7) (push) Waiting to run
Docker publish / build (linux/arm64) (push) Waiting to run
Docker publish / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
Currently translated at 99.6% (287 of 288 strings)

Translated using Weblate (Turkish)

Currently translated at 99.6% (287 of 288 strings)

Co-authored-by: Hakan Bildir <divxtr@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/tr/
Translation: Homebox/Frontend
2025-01-13 15:48:46 +00:00
Matt Kilgore
b147c53a5d Update docker-publish-rootless.yaml 2025-01-13 09:59:15 -05:00
Matt Kilgore
88eb6ec2fa Update docker-publish.yaml 2025-01-13 09:59:04 -05:00
Weblate
ac361eca13 Translated using Weblate (Hungarian)
Currently translated at 100.0% (288 of 288 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (288 of 288 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (288 of 288 strings)

Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translation: Homebox/Frontend
2025-01-13 10:48:46 +00:00
Weblate
92dbbe4892 Translated using Weblate (Hungarian)
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Docker publish / build (linux/amd64) (push) Waiting to run
Docker publish / build (linux/arm/v7) (push) Waiting to run
Docker publish / build (linux/arm64) (push) Waiting to run
Docker publish / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
Currently translated at 99.6% (287 of 288 strings)

Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translation: Homebox/Frontend
2025-01-13 06:13:49 +00:00
Weblate
ddc52f4f0c Translated using Weblate (Chinese (Simplified))
Currently translated at 98.9% (285 of 288 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 98.9% (285 of 288 strings)

Co-authored-by: Cheng Gu <guchengf@gmail.com>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translation: Homebox/Frontend
2025-01-13 05:39:14 +00:00
Weblate
8bd97e24d0 Translated using Weblate (Thai)
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Docker publish / build (linux/amd64) (push) Waiting to run
Docker publish / build (linux/arm/v7) (push) Waiting to run
Docker publish / build (linux/arm64) (push) Waiting to run
Docker publish / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
Currently translated at 12.2% (35 of 286 strings)

Added translation using Weblate (Thai)

Translated using Weblate (Chinese (Simplified))

Currently translated at 98.9% (283 of 286 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 98.9% (283 of 286 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 98.9% (283 of 286 strings)

Translated using Weblate (Slovenian)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (French)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Polish)

Currently translated at 99.6% (285 of 286 strings)

Translated using Weblate (French)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (German)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (German)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 36.7% (105 of 286 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 36.7% (105 of 286 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Hungarian)

Currently translated at 96.8% (277 of 286 strings)

Translated using Weblate (Hungarian)

Currently translated at 96.8% (277 of 286 strings)

Translated using Weblate (German)

Currently translated at 98.2% (281 of 286 strings)

Translated using Weblate (Danish)

Currently translated at 97.9% (280 of 286 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (286 of 286 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.5% (279 of 286 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.5% (279 of 286 strings)

Translated using Weblate (Slovenian)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (Slovenian)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (Slovenian)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (French)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (French)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (English)

Currently translated at 100.0% (281 of 281 strings)

Co-authored-by: 1270o1 <ma@da-sh.de>
Co-authored-by: Adam Kleizer <adamkleizer@gmail.com>
Co-authored-by: Cheng Gu <guchengf@gmail.com>
Co-authored-by: Daniel Zanardi de Souza <zz.uploader@gmail.com>
Co-authored-by: Equinoxs <equinoxsoftime@gmail.com>
Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: Kostiantyn Kozlov <tempor.demonius@gmail.com>
Co-authored-by: Lukan Vanderlinde <weblate@lukan.rocks>
Co-authored-by: Matthew Kilgore <matthew@kilgore.dev>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: Nic <nicmeier1@gmx.net>
Co-authored-by: SKNTim <timmy444074@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: buzz <buzz.eclair@gmail.com>
Co-authored-by: csacsatb <csacsatb@gmail.com>
Co-authored-by: euforik <euforik22@gmail.com>
Co-authored-by: falchdk <jesper@falch.org>
Co-authored-by: stegl <primsteg@gmail.com>
Co-authored-by: xtsusaku <thanawat.putmala@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/da/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/en/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/hu/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sk/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/th/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/uk/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hans/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/zh_Hant/
Translation: Homebox/Frontend
2025-01-11 17:59:37 +00:00
Corknut
55b907fac3 Added keyboard accessible shortcut menu for create modals (#457)
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Docker publish / build (linux/amd64) (push) Waiting to run
Docker publish / build (linux/arm/v7) (push) Waiting to run
Docker publish / build (linux/arm64) (push) Waiting to run
Docker publish / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
* Added quick action menu

* Ran ui:fix

* Updated quick action ui, added navigation options, translation keys

* Changed text color

* Added missing translation keys
2025-01-11 17:59:33 +00:00
Cheng Gu
3ca10897bb Fix problem of broken navigation text in Chinese and set the correct value of html lang (#456)
Some checks failed
Docker publish rootless / build (linux/amd64) (push) Has been cancelled
Docker publish rootless / build (linux/arm/v7) (push) Has been cancelled
Docker publish rootless / build (linux/arm64) (push) Has been cancelled
Docker publish / build (linux/amd64) (push) Has been cancelled
Docker publish / build (linux/arm/v7) (push) Has been cancelled
Docker publish / build (linux/arm64) (push) Has been cancelled
Update Currencies / update-currencies (push) Has been cancelled
Docker publish rootless / merge (push) Has been cancelled
Docker publish / merge (push) Has been cancelled
* feat: set correct html lang value with i18n locale

* feat: do not wrap side menu text when locale is chinese

---------

Co-authored-by: Katos <7927609+katosdev@users.noreply.github.com>
2025-01-09 11:18:30 -05:00
Katos
344489819c Trigger action to run
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
Testing Docker actions following cycle of PAT
2025-01-09 12:23:55 +00:00
Katos
44bdca8c21 Update Dockerfile.rootless
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
Specify UID:GID of nonroot user to fix issue with rootless database
2025-01-08 18:58:40 +00:00
Matt Kilgore
25700c12da Update cutoff
Some checks failed
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
Docker publish / build (linux/amd64) (push) Has been cancelled
Docker publish / build (linux/arm/v7) (push) Has been cancelled
Docker publish / build (linux/arm64) (push) Has been cancelled
Docker publish / merge (push) Has been cancelled
2025-01-07 19:56:38 -05:00
Matt Kilgore
a252f63ae8 Update to 2025-01-07 19:55:05 -05:00
Matt Kilgore
3919ed2e91 Update docker-publish-rootless.yaml
Some checks failed
Docker publish rootless / build (linux/amd64) (push) Has been cancelled
Docker publish rootless / build (linux/arm/v7) (push) Has been cancelled
Docker publish rootless / build (linux/arm64) (push) Has been cancelled
Docker publish / build (linux/amd64) (push) Has been cancelled
Docker publish / build (linux/arm/v7) (push) Has been cancelled
Docker publish / build (linux/arm64) (push) Has been cancelled
Update Currencies / update-currencies (push) Has been cancelled
Docker publish rootless / merge (push) Has been cancelled
Docker publish / merge (push) Has been cancelled
2025-01-06 05:46:02 -05:00
Matt Kilgore
4847d8d72b add docker sbom, provenance and annotations 2025-01-06 05:43:09 -05:00
Matt Kilgore
08081d7abf Update clear-stale-docker-images.yml
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Docker publish / build (linux/amd64) (push) Waiting to run
Docker publish / build (linux/arm/v7) (push) Waiting to run
Docker publish / build (linux/arm64) (push) Waiting to run
Docker publish / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
2025-01-05 21:27:58 -05:00
Matt Kilgore
da9d0681b8 Update clear-stale-docker-images.yml 2025-01-05 21:26:07 -05:00
Matt Kilgore
f635bb1084 Update clear-stale-docker-images.yml 2025-01-05 21:16:44 -05:00
Matt Kilgore
ccb8961ed2 Update clear-stale-docker-images.yml 2025-01-05 21:14:18 -05:00
Matt Kilgore
de993f37a4 Update clear-stale-docker-images.yml 2025-01-05 21:12:18 -05:00
Matt Kilgore
c839e82b93 Need to make the directory from the builder
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Docker publish / build (linux/amd64) (push) Waiting to run
Docker publish / build (linux/arm/v7) (push) Waiting to run
Docker publish / build (linux/arm64) (push) Waiting to run
Docker publish / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
2025-01-05 12:50:52 -05:00
Matt Kilgore
ac47073988 Lets try this 2025-01-05 12:48:00 -05:00
Katos
6ad0c33340 Attempt #182391239123 2025-01-05 17:25:11 +00:00
Katos
14bb2de584 CHOWN data file 2025-01-05 17:15:01 +00:00
Katos
1d62552046 Update Dockerfile.rootless 2025-01-05 17:01:42 +00:00
Katos
d84c45d332 Fix ownership of directories 2025-01-05 16:46:04 +00:00
Katos
1f197f748a CHOWN the required directories 2025-01-05 16:40:17 +00:00
Katos
0484bbb0c3 Update Dockerfile.rootless 2025-01-05 16:32:08 +00:00
Matt Kilgore
5009879f9f Try this instead to fix rootless 2025-01-05 11:06:02 -05:00
Matt Kilgore
4b9bf95f20 Fix missing pnpm 2025-01-05 11:00:57 -05:00
Katos
d1dff61bef They see my errors... they hatin' 2025-01-05 15:53:44 +00:00
Katos
966ae9062e Adjust from Distroless to Alpine 2025-01-05 15:51:29 +00:00
Katos
0e3c1db334 Update Dockerfile.rootless 2025-01-05 15:43:44 +00:00
Katos
2e4a967559 Update Dockerfile.rootless 2025-01-05 15:42:05 +00:00
Katos
d8c98d1bdb Update Dockerfile.rootless 2025-01-05 15:34:24 +00:00
Katos
f56067ac5c Update Dockerfile.rootless 2025-01-05 15:31:16 +00:00
Katos
5878870809 Losing the will to live, one commit at a time 2025-01-05 15:27:03 +00:00
Katos
40ba888e05 Migrate context to variable. 2025-01-05 15:24:25 +00:00
Katos
342caf2e6b Update docker-publish-rootless.yaml 2025-01-05 15:21:08 +00:00
Katos
f30ccec451 Update Dockerfile.rootless to use Curl instead of wget 2025-01-05 15:15:38 +00:00
Katos
8d3de1a1e5 Update Dockerfile.rootless to fix wget 2025-01-05 15:13:23 +00:00
Katos
f5e404e6cd Update to rectify rootless build issues. 2025-01-05 15:07:34 +00:00
Matt Kilgore
62dc9f83c2 Fix missing version information in docker files 2025-01-05 10:05:58 -05:00
Katos
3922b13696 Force dockerfile to rootless on rootless build. 2025-01-05 15:00:08 +00:00
Matt Kilgore
96f3543891 fix: trying to solve the arm build process issue. (#365)
Some checks are pending
Docker publish rootless / build (linux/amd64) (push) Waiting to run
Docker publish rootless / build (linux/arm/v7) (push) Waiting to run
Docker publish rootless / build (linux/arm64) (push) Waiting to run
Docker publish rootless / merge (push) Blocked by required conditions
Docker publish / build (linux/amd64) (push) Waiting to run
Docker publish / build (linux/arm/v7) (push) Waiting to run
Docker publish / build (linux/arm64) (push) Waiting to run
Docker publish / merge (push) Blocked by required conditions
Update Currencies / update-currencies (push) Waiting to run
Co-authored-by: Katos <7927609+katosdev@users.noreply.github.com>
2025-01-04 20:43:27 -05:00
Matt Kilgore
850e61cade Update NPM dependencies 2025-01-04 16:24:22 -05:00
Matt Kilgore
d320401555 Update Golang dependencies 2025-01-04 16:22:53 -05:00
Tonya
9cf244c933 Add a warning when the version does not match the latest release (#442)
Some checks failed
Docker publish rootless / build-rootless (push) Waiting to run
Docker publish / build (push) Waiting to run
Update Currencies / update-currencies (push) Waiting to run
Docker publish ARM / build (push) Has been cancelled
Docker publish rootless ARM / build-rootless (push) Has been cancelled
Dockerhub publish / build (push) Has been cancelled
2025-01-04 14:22:25 -05:00
Matt Kilgore
a4e94ddf7a feat: Add measurement types to label generator, part of #436 2025-01-04 11:10:06 -05:00
EdWorth120
b6c4815dd1 When a location is requested by ID, sort its children location by name, it helps to organize the user interface. (#421)
Co-authored-by: Matt Kilgore <tankerkiller125@users.noreply.github.com>
2025-01-04 10:28:43 -05:00
Harrison Conlin
1a4e98ad2a add _time_format=sqlite parameter to SQLite URLs (#430) 2025-01-04 10:28:15 -05:00
Matt Kilgore
15e0cfb73f feat: Implement offline cache for sw, and autoupdating (#431) 2025-01-04 10:28:01 -05:00
Matt Kilgore
2810ff9172 Update package.json 2025-01-04 10:02:18 -05:00
Matt Kilgore
303cfa7268 Update clear-stale-docker-images.yml
Some checks are pending
Docker publish ARM / build (push) Waiting to run
Docker publish rootless ARM / build-rootless (push) Waiting to run
Docker publish rootless / build-rootless (push) Waiting to run
Docker publish / build (push) Waiting to run
Dockerhub publish / build (push) Waiting to run
Update Currencies / update-currencies (push) Waiting to run
2025-01-03 19:58:06 -05:00
Matt Kilgore
7ffda6119f Update clear-stale-docker-images.yml 2025-01-03 19:50:10 -05:00
Matt Kilgore
a73aee5ea2 Update clear-stale-docker-images.yml 2025-01-03 19:46:31 -05:00
Matt Kilgore
5bdaac74cd Create clear-stale-docker-images.yml 2025-01-03 19:44:49 -05:00
Tonya
2b4ad9356d Added easy label creation to multiselect (#425)
* feat: added easy label creation to multiselect, also fixed webhooks in dev mode

* fix: add missing translation
2025-01-03 14:29:48 -05:00
EdWorth120
1638e35da3 fix: #413 text not wrapping in location names when in location page (#422)
Some checks failed
Docker publish ARM / build (push) Has been cancelled
Docker publish rootless ARM / build-rootless (push) Has been cancelled
Docker publish rootless / build-rootless (push) Has been cancelled
Docker publish / build (push) Has been cancelled
Dockerhub publish / build (push) Has been cancelled
Update Currencies / update-currencies (push) Has been cancelled
2025-01-01 19:58:14 -05:00
Katos
9be3e4e830 Fix environment variable documentation
Some checks are pending
Docker publish ARM / build (push) Waiting to run
Docker publish rootless ARM / build-rootless (push) Waiting to run
Docker publish rootless / build-rootless (push) Waiting to run
Docker publish / build (push) Waiting to run
Dockerhub publish / build (push) Waiting to run
Update Currencies / update-currencies (push) Waiting to run
2025-01-01 16:06:32 +00:00
Katos
14916d2cc9 Merge pull request #420 from sysadminsmedia/katos/docs-fix
Update Docs to rectify invalid environment variable for max file upload
2025-01-01 15:57:24 +00:00
Katos
e63316b5be Update Docs to rectify invalid environment variable for max file upload 2025-01-01 15:48:04 +00:00
Weblate
09e2daef3e Translated using Weblate (Spanish)
Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (German)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (German)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (French)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (German)

Currently translated at 99.6% (280 of 281 strings)

Translated using Weblate (German)

Currently translated at 99.6% (280 of 281 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (281 of 281 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (German)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Czech)

Currently translated at 79.7% (221 of 277 strings)

Added translation using Weblate (Czech)

Translated using Weblate (Polish)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Polish)

Currently translated at 95.6% (265 of 277 strings)

Translated using Weblate (Polish)

Currently translated at 95.6% (265 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 74.0% (205 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 74.0% (205 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 74.0% (205 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 43.6% (121 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 43.6% (121 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 43.6% (121 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 38.6% (107 of 277 strings)

Translated using Weblate (Danish)

Currently translated at 38.6% (107 of 277 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (French)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (French)

Currently translated at 100.0% (277 of 277 strings)

Translated using Weblate (French)

Currently translated at 78.7% (218 of 277 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (277 of 277 strings)

Co-authored-by: 101br03k <warmerdamm03@gmail.com>
Co-authored-by: Andreas Olsson <basen82@icloud.com>
Co-authored-by: ChinskiKaczynski <nupharizar@gmail.com>
Co-authored-by: Christoph Auer <Christoph.Auer@pilsheim.de>
Co-authored-by: Edmundo Neto <edmundo.vn@gmail.com>
Co-authored-by: Eniafit <eniafit87@gmail.com>
Co-authored-by: Fabian <Fabian.paul.gurtner@gmail.com>
Co-authored-by: Hannes Salen <hannes.salen@gmail.com>
Co-authored-by: Heine Olsen <olsen10051988@gmail.com>
Co-authored-by: Mickaël Descamps <mickael.descamps@mineyou.fr>
Co-authored-by: MyMemory <noreply-mt-mymemory@weblate.org>
Co-authored-by: PavulonGit <pavloo@vp.pl>
Co-authored-by: PavulonGit <pavulongit@users.noreply.translate.sysadminsmedia.com>
Co-authored-by: Slydite4 <39199098+Slydite4@users.noreply.github.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: thhurt <th.hurtado+weblate@gmail.com>
Co-authored-by: vyPal <kubik.palacky@gmail.com>
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/cs/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/da/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/de/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/es/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/fr/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/it/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/nl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pl/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/pt_BR/
Translate-URL: https://translate.sysadminsmedia.com/projects/homebox/frontend/sv/
Translation: Homebox/Frontend
2024-12-31 19:48:46 +00:00
Tonya
1ebdc88b0d Improve handling of copy button on http (#414)
Some checks failed
Docker publish ARM / build (push) Has been cancelled
Docker publish rootless ARM / build-rootless (push) Has been cancelled
Docker publish rootless / build-rootless (push) Has been cancelled
Docker publish / build (push) Has been cancelled
Dockerhub publish / build (push) Has been cancelled
Update Currencies / update-currencies (push) Has been cancelled
2024-12-29 12:23:59 -05:00
Katos
ba98655231 REVERT: Fix logo not appearing in safari
Some checks failed
Docker publish ARM / build (push) Has been cancelled
Docker publish rootless ARM / build-rootless (push) Has been cancelled
Docker publish rootless / build-rootless (push) Has been cancelled
Docker publish / build (push) Has been cancelled
Dockerhub publish / build (push) Has been cancelled
Update Currencies / update-currencies (push) Has been cancelled
Due to issues with placement of the homebox logo, remove Logo size for further investigation and discussion.
2024-12-27 23:03:42 +00:00
Katos
7d955e4a5d Remove Logo size
Due to misplaced logo components, reverting change to add sizing whilst further investigation is conducted.
2024-12-27 22:57:31 +00:00
Katos
2f7d7cfc00 Update Dockerfile
Trigger the Dockerhub action
2024-12-27 16:15:33 +00:00
Katos
243dd1d306 Update .gitignore
triggering the new dockerhub build action
2024-12-27 16:13:58 +00:00
Katos
a825bab986 Update dockerhub-publish.yaml 2024-12-27 16:12:56 +00:00
Katos
3242e9b24b Rename dockerhub-publish to dockerhub-publish.yaml 2024-12-27 16:06:12 +00:00
Katos
481f2e9698 Create dockerhub-publish 2024-12-27 16:05:56 +00:00
Katos
873ee90674 Fix logo size
Some checks are pending
Docker publish ARM / build (push) Waiting to run
Docker publish rootless ARM / build-rootless (push) Waiting to run
Docker publish rootless / build-rootless (push) Waiting to run
Docker publish / build (push) Waiting to run
Update Currencies / update-currencies (push) Waiting to run
Due to placement issues on the login page, size has to be significantly reduced. I continue to hate Safari....
2024-12-26 22:08:41 +00:00
Katos
35dcfd2c0f FIX: Homebox SVG logo missing in Safari due to size not specified
FIX #360 : Homebox SVG logo missing in Safari due to size not specified
2024-12-26 21:46:59 +00:00
Katos
97e0816654 Fix Safari being dumb 2024-12-26 21:41:10 +00:00
Tonya
2ae1115a3e refactor: remove strings lib (#405) 2024-12-26 16:37:07 -05:00
Katos
ba3f4ac371 Move Height and Width attribute to (hopefully) fix Safari issues. 2024-12-26 21:32:54 +00:00
Katos
9a4f8e0dde Merge pull request #402 from sysadminsmedia/katos/fix-logo-size
FIX: Set SVG logo size to fix logo not showing on Safari
2024-12-26 18:55:10 +00:00
Katos
26a7fcb697 Update Logo and Fix Frontend tests 2024-12-26 18:49:48 +00:00
Katos
62a450f376 Fix integration tests 2024-12-26 18:49:48 +00:00
Katos
32e0d80611 Update Logo.vue 2024-12-26 18:49:48 +00:00
Matt Kilgore
75b9c2f45b fix: missing migration 2024-12-26 18:36:28 +00:00
Katos
1aff45159e Merge pull request #403 from sysadminsmedia/revert-401-katos/fix-items-labels
Revert "Fix: Show labels on item page"
2024-12-26 17:40:33 +00:00
Katos
0f3948d435 Revert "Fix: Show labels on item page" 2024-12-26 17:38:01 +00:00
Katos
e0de8433f5 Merge pull request #401 from sysadminsmedia/katos/fix-items-labels
Fix: Show labels on item page
2024-12-26 17:30:37 +00:00
Katos
29d82fcbfe Update index.vue 2024-12-26 16:57:39 +00:00
Matt Kilgore
2df7d25284 Run task ui:fix for lint 2024-12-26 16:51:29 +00:00
Katos
6a54b66fec Update datelib.test.ts
Please fix the tests 😁
2024-12-26 16:42:38 +00:00
Matt Kilgore
91851b4333 Fix datelib test 2024-12-26 11:31:44 -05:00
Matt Kilgore
68cad395b8 Fix date test (I think) 2024-12-26 11:19:43 -05:00
Katos
a935c7d0dd Update index.vue 2024-12-26 16:16:34 +00:00
Katos
55d11f0b05 Update index.vue
Update Item page to correct the JSON return for labels and add a fall back if no labels are collected.
2024-12-26 16:09:00 +00:00
Katos
5e853513b9 Merge pull request #400 from sysadminsmedia/katos/fix-logo-safari
Some checks are pending
Docker publish ARM / build (push) Waiting to run
Docker publish rootless ARM / build-rootless (push) Waiting to run
Docker publish rootless / build-rootless (push) Waiting to run
Docker publish / build (push) Waiting to run
Update Currencies / update-currencies (push) Waiting to run
Update Logo.vue
2024-12-26 14:36:28 +00:00
Katos
6fb52bf19e Update Logo.vue
Add height and width attributes to the logo to fix #360
2024-12-26 14:18:51 +00:00
zebrapurring
441c2e7a59 feat: add button to copy the item URL (#389)
Some checks failed
Docker publish ARM / build (push) Has been cancelled
Docker publish rootless ARM / build-rootless (push) Has been cancelled
Docker publish rootless / build-rootless (push) Has been cancelled
Docker publish / build (push) Has been cancelled
Update Currencies / update-currencies (push) Has been cancelled
Co-authored-by: zebrapurring <>
2024-12-23 22:18:44 -05:00
zebrapurring
a3ebeb8f6f feat: display item labels in the details page (#387)
Some checks failed
Docker publish ARM / build (push) Has been cancelled
Docker publish rootless ARM / build-rootless (push) Has been cancelled
Docker publish rootless / build-rootless (push) Has been cancelled
Docker publish / build (push) Has been cancelled
Update Currencies / update-currencies (push) Has been cancelled
Co-authored-by: zebrapurring <>
2024-12-20 19:36:14 -05:00
Katos
6142c31c8c Merge pull request #275 from slid1amo2n3e4/parent-location-sync
Implement syncing with parent item location.
2024-12-13 21:02:39 +00:00
slid1amo2n3e4
beed55f322 Merge branch 'main' into parent-location-sync 2024-12-13 15:01:02 +01:00
dependabot[bot]
a7d61889ca chore(deps): bump golang.org/x/crypto (#382)
Bumps the go_modules group with 1 update in the /backend directory: [golang.org/x/crypto](https://github.com/golang/crypto).


Updates `golang.org/x/crypto` from 0.28.0 to 0.31.0
- [Commits](https://github.com/golang/crypto/compare/v0.28.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-12 20:49:23 -05:00
zebrapurring
83c57ed9e6 fix: sorting for completed and scheduled maintenance entries (#384)
* fix: sorting for completed and scheduled maintenance entries

* Completed entries are sorted by descending completion date
* Scheduled entries are sorted by ascending scheduling date
* Selecting both entries shall sort them by scheduling and then completion date in descending order

* refactor: rewrite if-else as switch-case

---------

Co-authored-by: zebrapurring <>
2024-12-12 20:47:40 -05:00
Mike Kusold
90adeb0063 Update Swagger Docs from #370 (#376) 2024-12-10 16:53:18 -05:00
slid1amo2n3e4
63eb287485 Make the tests pass, hopefully. 2024-12-10 18:48:49 +01:00
Mike Kusold
5f63c5f738 Improve swagger generation (#370)
* Improve swagger generation

These issues are causing ogen-api to fail after I used the swagger
converter.

* Specify multipart/form-data routes

Operations with parameters of "type: file" must include "multipart/form-data" in their "consumes" property

* Fix example usage

* fixup! Specify multipart/form-data routes

* Fix final validation errors
2024-12-08 18:11:21 -05:00
Nikolai K
2d2e3fe891 Improve filter for maintenances (#367)
Maintenances with completed date in the future should be in the scheduled tab
2024-12-02 14:23:37 -05:00
Sai Vishnu M
8dca14850b add timestamp to the export filename (#366) 2024-12-02 09:00:25 -05:00
Katos
c9fc3ce020 Alphabetical Sorting of currencies
Update currencies.json with alphabetical sorting
2024-11-30 21:25:11 +00:00
github-actions[bot]
bb58d7da9d Update currencies.json 2024-11-30 21:24:11 +00:00
Katos
8cb29c28ba Update currencies.json
Force a re-sync from API to allow for alphabetical sorting
2024-11-30 21:23:55 +00:00
Katos
9a27b4d762 Update README.md 2024-11-30 21:20:21 +00:00
Katos
bfb70a26ab Merge pull request #361 from sysadminsmedia/katos/fix-currencies-action
Fix Currencies Automated action
2024-11-30 21:13:48 +00:00
Katos
83012d491d Update update-currencies.yml 2024-11-30 21:09:14 +00:00
Katos
67668578e8 Update update_currencies.py 2024-11-30 21:07:56 +00:00
Matt Kilgore
daf07d4f35 Merge branch 'main' into parent-location-sync 2024-11-02 23:22:53 -04:00
Matt Kilgore
ae76538178 Merge branch 'main' into parent-location-sync 2024-10-30 15:49:18 -04:00
Matt Kilgore
ab80805073 Merge branch 'main' into parent-location-sync 2024-10-28 15:51:31 -04:00
slid1amo2n3e4
f6d1f9c90d Fix 'should not use underscores in Go names' lint error 2024-10-08 22:31:05 +02:00
slid1amo2n3e4
17e7e24070 Implement syncing child's locations to that of parent. 2024-10-08 15:48:12 -04:00
slid1amo2n3e4
7d462a4dd3 Fix formatting. 2024-10-08 15:48:12 -04:00
516 changed files with 39529 additions and 15244 deletions

View File

@@ -1,5 +1,3 @@
# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
ARG VARIANT=16-bullseye
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT}
FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:22-bullseye
RUN sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin
RUN sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin

View File

@@ -3,13 +3,7 @@
{
"name": "Node.js & TypeScript",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick a Node version: 18, 16, 14.
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
"args": {
"VARIANT": "18-bullseye"
}
"dockerfile": "Dockerfile"
},
// Configure tool-specific properties.
@@ -35,6 +29,6 @@
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node",
"features": {
"ghcr.io/devcontainers/features/go:1": "1.21"
"ghcr.io/devcontainers/features/go:1": "1.24"
}
}

40
.github/AGENTS.md vendored Normal file
View File

@@ -0,0 +1,40 @@
This is a Go based repository with a VueJS client for the frontend built with Vite and Nuxt, with ShadCN.
To make life easier, the use of a Taskfile is included for the majority of development commands.
Please follow these guidelines when contributing:
## Required Before Each Commit
- Generate Swagger Files: `task swag --force`
- Generate JS API Client: `task typescript-types --force`
- Lint Golang: `task go:lint`
- Lint frontend: `task ui:fix`
## Repository Structure
### Backend
- `backend/`: Contains the backend folders
- `backend/app`: Contains main app code including API endpoints
- `backend/internal/core`: Contains basic services such as currencies
- `backend/data`: Contains all information related to data, including `ent` schemas, repos, migrations, etc.
- `backend/data/migrations`: Contains migration data, the `sqlite3` sub-folder contains sqlite migrations, `postgres` sub-folder the postgres migrations, BOTH are REQUIRED.
- `backend/data/ent/schema`: Contains the actual `ent` data models.
- `backend/data/repo`: Contains the data repositories
- `backend/pkgs`: Contains general helper functions and services
### Frontend
- `frontend/`: Contains initial frontend files
- `frontend/components`: Contains the ShadCN components
- `frontend/locales`: Contains the i18n JSON for languages
- `frontend/pages`: Contains VueJS pages
- `frontend/test`: Contains Playwright setup
- `frontend/test/e2e`: Contains actual Playwright test files
### Docs
- `docs/`: Contains VitePress based documentation
## Key Guidelines
1. Follow best practices for the various programming languages
2. Maintain existing code structure and organization when possible
3. Use dependency injection when reasonable
4. Write tests for new functionality and after fixing bugs to validate they're fixed
5. Document changes to the `docs/` folder when appropriate

View File

@@ -1,9 +1,4 @@
---
name: "Feature Request"
description: "Submit a feature request for the current release"
labels: ["⬆️ enhancement"]
projects: ["sysadminsmedia/2"]
type: "Enhancement"
body:
- type: textarea
id: problem-statement
@@ -31,9 +26,5 @@ body:
label: Contributions
description: Please confirm the following
options:
- label: I have searched through existing issues and feature requests to see if my idea has already been proposed.
- label: I have searched through existing ideas in the discussions to check if this is a duplicate
required: true
- label: If this feature is accepted, I would be willing to help implement and maintain this feature.
required: false
- label: If this feature is accepted, I'm willing to sponsor the development of this feature.
required: false

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: GitHub Community Support
url: https://github.com/sysadminsmedia/homebox/discussions/categories/support
about: Get support for issues here
- name: Feature Requests
url: https://github.com/sysadminsmedia/homebox/discussions/categories/ideas
about: Have an idea for Homebox? Share it in our discussions forum. If we decide to take it on we will create an issue for it.
- name: Translate
url: https://translate.sysadminsmedia.com
about: Help us translate Homebox! All contributions and all languages welcome!

View File

@@ -1,65 +1,106 @@
import requests
#!/usr/bin/env python3
import json
import os
import logging
import sys
from pathlib import Path
import requests
from requests.adapters import HTTPAdapter, Retry
API_URL = 'https://restcountries.com/v3.1/all?fields=name,common,currencies'
SAVE_PATH = Path('backend/internal/core/currencies/currencies.json')
TIMEOUT = 10 # seconds
def setup_logging():
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s %(levelname)s: %(message)s'
)
def fetch_currencies():
session = requests.Session()
retries = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=frozenset(['GET'])
)
session.mount('https://', HTTPAdapter(max_retries=retries))
try:
response = requests.get('https://restcountries.com/v3.1/all')
response.raise_for_status()
except requests.exceptions.Timeout:
print("Request to the API timed out.")
return []
resp = session.get(API_URL, timeout=TIMEOUT)
resp.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"An error occurred while making the request: {e}")
return []
logging.error("API request failed: %s", e)
return None # signal fatal
try:
countries = response.json()
except json.JSONDecodeError:
print("Failed to decode JSON from the response.")
return []
countries = resp.json()
except ValueError as e:
logging.error("Failed to parse JSON response: %s", e)
return None # signal fatal
currencies_list = []
results = []
for country in countries:
country_name = country.get('name', {}).get('common')
country_currencies = country.get('currencies', {})
for currency_code, currency_info in country_currencies.items():
symbol = currency_info.get('symbol', '')
currencies_list.append({
'code': currency_code,
'local': country_name,
'symbol': symbol,
'name': currency_info.get('name')
country_name = country.get('name', {}).get('common') or "Unknown"
for code, info in country.get('currencies', {}).items():
results.append({
'code': code,
'local': country_name,
'symbol': info.get('symbol', ''),
'name': info.get('name', '')
})
return currencies_list
# sort by country name for consistency
return sorted(results, key=lambda x: x['local'].lower())
def save_currencies(currencies, file_path):
try:
os.makedirs(os.path.dirname(file_path), exist_ok=True)
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(currencies, f, ensure_ascii=False, indent=4)
except IOError as e:
print(f"An error occurred while writing to the file: {e}")
def load_existing_currencies(file_path):
def load_existing(path: Path):
if not path.exists():
return []
try:
with open(file_path, 'r', encoding='utf-8') as f:
with path.open('r', encoding='utf-8') as f:
return json.load(f)
except (IOError, json.JSONDecodeError):
return [] # Return an empty list if file doesn't exist or is invalid
except (IOError, ValueError) as e:
logging.warning("Could not load existing file (%s): %s", path, e)
return []
def save_currencies(data, path: Path):
path.parent.mkdir(parents=True, exist_ok=True)
with path.open('w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
logging.info("Wrote %d entries to %s", len(data), path)
def main():
save_path = 'backend/internal/core/currencies/currencies.json'
existing_currencies = load_existing_currencies(save_path)
new_currencies = fetch_currencies()
setup_logging()
logging.info("🔄 Starting currency update")
existing = load_existing(SAVE_PATH)
new = fetch_currencies()
# Fatal API / parse error → exit non-zero so the workflow will fail
if new is None:
logging.error("Aborting: failed to fetch or parse API data.")
sys.exit(1)
# Empty array → log & exit zero (no file change)
if not new:
logging.warning("API returned empty list; skipping write.")
sys.exit(0)
# Identical to existing → nothing to do
if new == existing:
logging.info("Up-to-date; skipping write.")
sys.exit(0)
# Otherwise actually overwrite
save_currencies(new, SAVE_PATH)
logging.info("✅ Currency file updated.")
if new_currencies == existing_currencies:
print("Currencies up-to-date with API, skipping commit.")
else:
save_currencies(new_currencies, save_path)
print("Currencies updated and saved.")
if __name__ == "__main__":
main()
main()

View File

@@ -5,14 +5,6 @@ on:
tags: [ 'v*.*.*' ]
jobs:
# backend-tests:
# name: "Backend Server Tests"
# uses: sysadminsmedia/homebox/.github/workflows/partial-backend.yaml@main
# frontend-tests:
# name: "Frontend and End-to-End Tests"
# uses: sysadminsmedia/homebox/.github/workflows/partial-frontend.yaml@main
goreleaser:
name: goreleaser
runs-on: ubuntu-latest
@@ -24,24 +16,32 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.24"
cache-dependency-path: backend/go.mod
- uses: pnpm/action-setup@v2
with:
version: 7.30.1
version: 9.15.3
- name: Build Frontend and Copy to Backend
working-directory: frontend
run: |
pnpm install --shamefully-hoist
pnpm install
pnpm run build
cp -r ./.output/public ../backend/app/api/static/
- name: Install CoSign
working-directory: backend
run: |
go install github.com/sigstore/cosign/cmd/cosign@latest
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
workdir: "backend"
distribution: goreleaser
version: latest
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -0,0 +1,41 @@
name: Docker Cleanup
on:
schedule:
- cron: '00 0 * * *'
workflow_dispatch:
jobs:
delete-old-images-main:
name: Delete Old Images for Main Repo
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
dry-run: true
delete-ghost-images: true
delete-partial-images: true
delete-orphaned-images: true
delete-untagged: true
validate: true
token: '${{ github.token }}'
package: homebox
use-regex: true
exclude-tags: latest,latest-rootless,main,main-rootless,nightly,nightly-rootless,*.*.*,0.*,0,*.*.*-rootless,0.*-rootless,0-rootless
older-than: 180 days
delete-old-images-devcache:
name: Delete Old Devcache Images
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- uses: dataaxiom/ghcr-cleanup-action@v1
with:
dry-run: false
delete-untagged: true
token: '${{ github.token }}'
package: devcache
older-than: 90 days

View File

@@ -0,0 +1,52 @@
name: "Copilot Setup Steps"
# Automatically run the setup steps when they are changed to allow for easy validation, and
# allow manual testing through the repository's "Actions" tab
on:
workflow_dispatch:
push:
paths:
- .github/workflows/copilot-setup-steps.yml
pull_request:
paths:
- .github/workflows/copilot-setup-steps.yml
jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
copilot-setup-steps:
runs-on: ubuntu-latest
# Set the permissions to the lowest permissions possible needed for your steps.
# Copilot will be given its own token for its operations.
permissions:
# If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
contents: read
# You can define any steps you want, and they will run before the agent starts.
# If you do not check out your code, Copilot will do this for you.
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
- uses: pnpm/action-setup@v3.0.0
with:
version: 9.12.2
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.24"
cache-dependency-path: backend/go.mod
- name: Install Task
uses: arduino/setup-task@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Perform setup
run: task setup

View File

@@ -1,105 +0,0 @@
name: Docker publish ARM
on:
schedule:
- cron: '00 0 * * *'
push:
branches: [ "main" ]
paths:
- 'backend/**'
- 'frontend/**'
- 'Dockerfile'
- 'Dockerfile.rootless'
- '.dockerignore'
- '.github/workflows'
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
pull_request:
branches: [ "main" ]
paths:
- 'backend/**'
- 'frontend/**'
- 'Dockerfile'
- 'Dockerfile.rootless'
- '.dockerignore'
- '.github/workflows'
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
# Step 1: Checkout repository
- name: Checkout repository
uses: actions/checkout@v4
# Step 2: Set up Buildx without specifying driver
# Let it use default settings to avoid the 'no remote endpoint' issue
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.0.0
with:
install: true # Ensure Buildx is installed and set up properly
use: true # Use Buildx instance directly for this job
# Step 3: Login against Docker registry except on PR
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Step 4: Extract metadata for Docker images
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=schedule,pattern=nightly
flavor: |
suffix=-arm,onlatest=true
# Step 5: Build and push the Docker image
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5.0.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/arm64,linux/arm/v7
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
# Step 6: Attest built image to prove build provenance
- name: Attest
uses: actions/attest-build-provenance@v1
id: attest
if: ${{ github.event_name != 'pull_request' }}
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: true

View File

@@ -1,104 +0,0 @@
name: Docker publish rootless ARM
on:
schedule:
- cron: '00 0 * * *'
push:
branches: [ "main" ]
paths:
- 'backend/**'
- 'frontend/**'
- 'Dockerfile'
- 'Dockerfile.rootless'
- '.dockerignore'
- '.github/workflows'
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
pull_request:
branches: [ "main" ]
paths:
- 'backend/**'
- 'frontend/**'
- 'Dockerfile'
- 'Dockerfile.rootless'
- '.dockerignore'
- '.github/workflows'
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build-rootless:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
# Step 1: Checkout repository
- name: Checkout repository
uses: actions/checkout@v4
# Step 2: Set up Buildx without specifying driver
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.0.0
with:
install: true # Ensure Buildx is installed and set up properly
use: true # Use Buildx instance directly for this job
# Step 3: Login to Docker registry except on PR
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Step 4: Extract metadata for Docker images
- name: Extract Docker metadata
id: metadata
uses: docker/metadata-action@v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=schedule,pattern=nightly
flavor: |
suffix=-rootless-arm,onlatest=true
# Step 5: Build and push the Docker image
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5.0.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
platforms: linux/arm64,linux/arm/v7
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
# Step 6: Attest built image to prove build provenance
- name: Attest
uses: actions/attest-build-provenance@v1
id: attest
if: ${{ github.event_name != 'pull_request' }}
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: true

View File

@@ -9,10 +9,10 @@ on:
- 'backend/**'
- 'frontend/**'
- 'Dockerfile'
- 'Dockerfile.rootless'
- '.dockerignore'
- '.github/workflows'
# Publish semver tags as releases.
- '.github/workflows/docker-publish-rootless.yaml'
ignore:
- 'docs/**'
tags: [ 'v*.*.*' ]
pull_request:
branches: [ "main" ]
@@ -20,57 +20,170 @@ on:
- 'backend/**'
- 'frontend/**'
- 'Dockerfile'
- 'Dockerfile.rootless'
- '.dockerignore'
- '.github/workflows'
- '.github/workflows/docker-publish-rootless.yaml'
ignore:
- 'docs/**'
permissions:
contents: read # Access to repository contents
packages: write # Write access for pushing to GHCR
id-token: write # Required for OIDC authentication (if used)
attestations: write # Required for signing and attestation (if needed)
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
DOCKERHUB_REPO: sysadminsmedia/homebox
GHCR_REPO: ghcr.io/${{ github.repository }}
jobs:
build-rootless:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
attestations: write
id-token: write
attestations: write
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
- linux/arm/v7
steps:
- name: Enable Debug Logs
run: echo "##[debug]Enabling debug logging"
env:
ACTIONS_RUNNER_DEBUG: true
ACTIONS_STEP_DEBUG: true
- name: Checkout repository
uses: actions/checkout@v4
# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.0.0 # v3.0.0
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
branch=${{ github.event.pull_request.number || github.ref_name }}
echo "BRANCH=${branch//\//-}" >> $GITHUB_ENV
echo "DOCKERNAMES=${{ env.DOCKERHUB_REPO }},${{ env.GHCR_REPO }}" >> $GITHUB_ENV
if [[ "${{ github.event_name }}" != "schedule" ]] || [[ "${{ github.ref }}" != refs/tags/* ]]; then
echo "DOCKERNAMES=${{ env.GHCR_REPO }}" >> $GITHUB_ENV
fi
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3.0.0 # v3.0.0
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
registry: ${{ env.REGISTRY }}
images: |
name=${{ env.DOCKERHUB_REPO }},enable=${{ github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/') }}
name=${{ env.GHCR_REPO }}
- name: Login to Docker Hub
uses: docker/login-action@v3
if: (github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/'))
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: metadata
uses: docker/metadata-action@v5.0.0 # v5.0.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
image: ghcr.io/amitie10g/binfmt:latest
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
image=ghcr.io/amitie10g/buildkit:master
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: . # Explicitly specify the build context
file: ./Dockerfile.rootless # Explicitly specify the Dockerfile
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,"name=${{ env.DOCKERNAMES }}",push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
cache-from: type=registry,ref=ghcr.io/sysadminsmedia/devcache:${{ env.PLATFORM_PAIR }}-${{ env.BRANCH }}-rootless
cache-to: type=registry,ref=ghcr.io/sysadminsmedia/devcache:${{ env.PLATFORM_PAIR }}-${{ env.BRANCH }}-rootless,mode=max,ignore-error=true
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
provenance: true
sbom: true
annotations: ${{ steps.meta.outputs.annotations }}
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
attestations: write
needs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Login to Docker Hub
uses: docker/login-action@v3
if: (github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/'))
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
image=ghcr.io/amitie10g/buildkit:master
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
name=${{ env.DOCKERHUB_REPO }},enable=${{ github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/') }}
name=${{ env.GHCR_REPO }}
tags: |
type=ref,event=branch
type=ref,event=pr
@@ -80,29 +193,18 @@ jobs:
type=schedule,pattern=nightly
flavor: |
suffix=-rootless,onlatest=true
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5.0.0 # v5.0.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
platforms: linux/amd64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
- name: Attest
uses: actions/attest-build-provenance@v1
id: attest
if: ${{ github.event_name != 'pull_request' }}
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: true
- name: Create manifest list and push GHCR
id: push-ghcr
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.GHCR_REPO }}@sha256:%s ' *)
- name: Create manifest list and push Dockerhub
id: push-dockerhub
working-directory: /tmp/digests
if: (github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/'))
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.DOCKERHUB_REPO }}@sha256:%s ' *)

View File

@@ -9,10 +9,10 @@ on:
- 'backend/**'
- 'frontend/**'
- 'Dockerfile'
- 'Dockerfile.rootless'
- '.dockerignore'
- '.github/workflows'
# Publish semver tags as releases.
- '.github/workflows/docker-publish.yaml'
ignore:
- 'docs/**'
tags: [ 'v*.*.*' ]
pull_request:
branches: [ "main" ]
@@ -20,56 +20,163 @@ on:
- 'backend/**'
- 'frontend/**'
- 'Dockerfile'
- 'Dockerfile.rootless'
- '.dockerignore'
- '.github/workflows'
- '.github/workflows/docker-publish.yaml'
ignore:
- 'docs/**'
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
DOCKERHUB_REPO: sysadminsmedia/homebox
GHCR_REPO: ghcr.io/${{ github.repository }}
permissions:
contents: read # Access to repository contents
packages: write # Write access for pushing to GHCR
id-token: write # Required for OIDC authentication (if used)
attestations: write # Required for signing and attestation (if needed)
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
attestations: write
id-token: write
contents: read # Allows access to repository contents (read-only)
packages: write # Allows pushing to GHCR
id-token: write # Allows identity token write access for authentication
attestations: write # Needed for signing and attestation (if required)
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
- linux/arm/v7
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.0.0 # v3.0.0
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
branch=${{ github.event.pull_request.number || github.ref_name }}
echo "BRANCH=${branch//\//-}" >> $GITHUB_ENV
echo "DOCKERNAMES=${{ env.DOCKERHUB_REPO }},${{ env.GHCR_REPO }}" >> $GITHUB_ENV
if [[ "${{ github.event_name }}" != "schedule" ]] || [[ "${{ github.ref }}" != refs/tags/* ]]; then
echo "DOCKERNAMES=${{ env.GHCR_REPO }}" >> $GITHUB_ENV
fi
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3.0.0 # v3.0.0
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
registry: ${{ env.REGISTRY }}
images: |
name=${{ env.DOCKERHUB_REPO }},enable=${{ github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/') }}
name=${{ env.GHCR_REPO }}
- name: Login to Docker Hub
uses: docker/login-action@v3
if: (github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/'))
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5.0.0 # v5.0.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
image: ghcr.io/amitie10g/binfmt:latest
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
image=ghcr.io/amitie10g/buildkit:master
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
platforms: ${{ matrix.platform }}
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,"name=${{ env.DOCKERNAMES }}",push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
cache-from: type=registry,ref=ghcr.io/sysadminsmedia/devcache:${{ env.PLATFORM_PAIR }}-${{ env.BRANCH }}
cache-to: type=registry,ref=ghcr.io/sysadminsmedia/devcache:${{ env.PLATFORM_PAIR}}-${{ env.BRANCH }},mode=max,ignore-error=true
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
provenance: true
sbom: true
annotations: ${{ steps.meta.outputs.annotations }}
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read # Allows access to repository contents (read-only)
packages: write # Allows pushing to GHCR
id-token: write # Allows identity token write access for authentication
attestations: write # Needed for signing and attestation (if required)
needs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Login to Docker Hub
uses: docker/login-action@v3
if: (github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/'))
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
image=ghcr.io/amitie10g/buildkit:master
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
name=${{ env.DOCKERHUB_REPO }},enable=${{ github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/') }}
name=${{ env.GHCR_REPO }}
tags: |
type=ref,event=branch
type=ref,event=pr
@@ -78,28 +185,17 @@ jobs:
type=semver,pattern={{major}}
type=schedule,pattern=nightly
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5.0.0 # v5.0.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ github.ref_name }}
COMMIT=${{ github.sha }}
- name: Attest
uses: actions/attest-build-provenance@v1
id: attest
if: ${{ github.event_name != 'pull_request' }}
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: true
- name: Create manifest list and push GHCR
id: push-ghcr
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.GHCR_REPO }}@sha256:%s ' *)
- name: Create manifest list and push Dockerhub
id: push-dockerhub
working-directory: /tmp/digests
if: (github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/'))
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.DOCKERHUB_REPO }}@sha256:%s ' *)

95
.github/workflows/e2e-partial.yaml vendored Normal file
View File

@@ -0,0 +1,95 @@
name: E2E (Playwright)
on:
workflow_call:
jobs:
playwright-tests:
timeout-minutes: 60
strategy:
matrix:
shardIndex: [1,2,3,4]
shardTotal: [4]
name: E2E Playwright Testing ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Task
uses: arduino/setup-task@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.23"
cache-dependency-path: backend/go.mod
- uses: actions/setup-node@v4
with:
node-version: lts/*
- uses: pnpm/action-setup@v3.0.0
with:
version: 9.12.2
- name: Install dependencies
run: pnpm install
working-directory: frontend
- name: Install Go Dependencies
run: go mod download
working-directory: backend
- name: Run E2E Tests
run: task test:e2e -- --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
- uses: actions/upload-artifact@v4
name: Upload partial Playwright report
if: ${{ !cancelled() }}
with:
name: blob-report-${{ matrix.shardIndex }}
path: frontend/blob-report/
retention-days: 2
merge-reports:
# Merge reports after playwright-tests, even if some shards have failed
if: ${{ !cancelled() }}
needs: [playwright-tests]
name: Merge Playwright Reports
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- uses: pnpm/action-setup@v3.0.0
with:
version: 9.12.2
- name: Install dependencies
run: pnpm install
working-directory: frontend
- name: Download blob reports from GitHub Actions Artifacts
uses: actions/download-artifact@v4
with:
path: frontend/all-blob-reports
pattern: blob-report-*
merge-multiple: true
- name: Merge into HTML Report
run: pnpm exec playwright merge-reports --reporter html,github ./all-blob-reports
working-directory: frontend
- name: Upload HTML report
uses: actions/upload-artifact@v4
with:
name: html-report--attempt-${{ github.run_attempt }}
path: frontend/playwright-report
retention-days: 30

View File

@@ -12,7 +12,8 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.24"
cache-dependency-path: backend/go.mod
- name: Install Task
uses: arduino/setup-task@v1
@@ -20,7 +21,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v7
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: latest

View File

@@ -1,4 +1,4 @@
name: Frontend / E2E
name: Frontend
on:
workflow_call:
@@ -18,7 +18,7 @@ jobs:
version: 9.12.2
- name: Install dependencies
run: pnpm install --shamefully-hoist
run: pnpm install
working-directory: frontend
- name: Run Lint
@@ -32,6 +32,20 @@ jobs:
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17
env:
POSTGRES_USER: homebox
POSTGRES_PASSWORD: homebox
POSTGRES_DB: homebox
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -46,7 +60,8 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
go-version: "1.23"
cache-dependency-path: backend/go.mod
- uses: actions/setup-node@v4
with:
@@ -62,3 +77,54 @@ jobs:
- name: Run Integration Tests
run: task test:ci
integration-tests-pgsql:
strategy:
matrix:
database_version: [17,16,15]
name: Integration Tests PGSQL ${{ matrix.database_version }}
runs-on: ubuntu-latest
services:
postgres:
image: postgres:${{ matrix.database_version }}
env:
POSTGRES_USER: homebox
POSTGRES_PASSWORD: homebox
POSTGRES_DB: homebox
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Task
uses: arduino/setup-task@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.23"
cache-dependency-path: backend/go.mod
- uses: actions/setup-node@v4
with:
node-version: lts/*
- uses: pnpm/action-setup@v3.0.0
with:
version: 9.12.2
- name: Install dependencies
run: pnpm install
working-directory: frontend
- name: Run Integration Tests
run: task test:ci:postgresql

View File

@@ -4,10 +4,12 @@ on:
pull_request:
branches:
- main
- vnext
paths:
- 'backend/**'
- 'frontend/**'
- '.github/workflows/**'
jobs:
backend-tests:
@@ -15,5 +17,9 @@ jobs:
uses: ./.github/workflows/partial-backend.yaml
frontend-tests:
name: "Frontend and End-to-End Tests"
uses: ./.github/workflows/partial-frontend.yaml
name: "Frontend Tests"
uses: ./.github/workflows/partial-frontend.yaml
e2e-tests:
name: "End-to-End Playwright Tests"
uses: ./.github/workflows/e2e-partial.yaml

View File

@@ -2,8 +2,8 @@ name: Update Currencies
on:
push:
branches:
- main
branches: [ main ]
workflow_dispatch:
jobs:
update-currencies:
@@ -11,90 +11,45 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: '3.8'
cache: 'pip'
cache-dependency-path: .github/workflows/update-currencies/requirements.txt
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests
- name: Run currency fetch script
- name: Run currency update script
run: python .github/scripts/update_currencies.py
- name: Check for changes
id: check_changes
- name: Check for file changes
id: changes
run: |
if [[ $(git status --porcelain) ]]; then
echo "Changes detected."
echo "changes=true" >> $GITHUB_ENV
if git diff --quiet; then
echo "changed=false" >> $GITHUB_ENV
else
echo "No changes detected."
echo "changes=false" >> $GITHUB_ENV
echo "changed=true" >> $GITHUB_ENV
fi
- name: Delete existing update-currencies branch
run: |
if git show-ref --verify --quiet refs/heads/update-currencies; then
git branch -D update-currencies
echo "Deleted existing update-currencies branch."
else
echo "No existing update-currencies branch to delete."
fi
- name: Create Pull Request
if: env.changed == 'true'
uses: peter-evans/create-pull-request@v7.0.8
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: update-currencies
base: main
title: "Update currencies.json"
commit-message: "chore: update currencies.json"
path: backend/internal/core/currencies/currencies.json
- name: Create new update-currencies branch
if: env.changes == 'true'
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
# Create a new branch
git checkout -b update-currencies
git add backend/internal/core/currencies/currencies.json
git commit -m "Update currencies.json"
# Fetch the latest changes from the remote
git fetch origin
# Attempt to rebase with the latest changes
if git show-ref --verify --quiet refs/remotes/origin/update-currencies; then
if ! git rebase origin/update-currencies; then
echo "Rebase conflicts occurred. Please resolve them manually."
echo "To resolve conflicts, check out the 'update-currencies' branch locally."
exit 1
fi
else
echo "No existing remote branch 'update-currencies'. Skipping rebase."
fi
# Push the new branch to the remote
if ! git push --set-upstream origin update-currencies; then
echo "Push failed, trying to fetch and rebase again."
git fetch origin
if git show-ref --verify --quiet refs/remotes/origin/update-currencies; then
if ! git rebase origin/update-currencies; then
echo "Second rebase failed. Please resolve manually."
exit 1
fi
else
echo "No existing remote branch 'update-currencies'. Skipping rebase."
fi
if ! git push --set-upstream origin update-currencies; then
echo "Second push failed. Please resolve manually."
exit 1
fi
fi
# Create a pull request
curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-X POST \
-d '{"title": "Update currencies", "head": "update-currencies", "base": "main"}' \
https://api.github.com/repos/${{ github.repository }}/pulls
- name: Notify no changes
if: env.changes == 'false'
run: echo "Currencies up-to-date with API, skipping commit."
- name: No updates needed
if: env.changed == 'false'
run: echo "✅ currencies.json is already up-to-date"

View File

@@ -0,0 +1 @@
requests

11
.gitignore vendored
View File

@@ -2,6 +2,9 @@
backend/.data/*
config.yml
homebox.db
homebox.db-journal
homebox.db-shm
homebox.db-wal
.idea
.DS_Store
test-mailer.json
@@ -33,7 +36,7 @@ go.work
backend/.env
build/*
# Output Directory for Nuxt/Frontend during build step
# Output Directory for Nuxt/Frontend during build steps
backend/app/api/public/*
!backend/app/api/public/.gitkeep
@@ -58,3 +61,9 @@ backend/api
docs/.vitepress/cache/
/.data/
# Playwright
frontend/test-results/
frontend/playwright-report/
frontend/blob-report/
frontend/playwright/.cache/

8
.vscode/launch.json vendored
View File

@@ -16,14 +16,12 @@
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceRoot}/backend/app/api/",
"program": "${workspaceFolder}/backend/app/api/",
"args": [],
"env": {
"HBOX_DEMO": "true",
"HBOX_LOG_LEVEL": "debug",
"HBOX_DEBUG_ENABLED": "true",
"HBOX_STORAGE_DATA": "${workspaceRoot}/backend/.data",
"HBOX_STORAGE_SQLITE_URL": "${workspaceRoot}/backend/.data/homebox.db?_fk=1"
"HBOX_DEBUG_ENABLED": "true"
},
"console": "integratedTerminal",
},
@@ -46,4 +44,4 @@
"console": "integratedTerminal",
}
]
}
}

View File

@@ -30,5 +30,8 @@
"editor.quickSuggestions": {
"strings": true
},
"tailwindCSS.experimental.configFile": "./frontend/tailwind.config.js"
"tailwindCSS.experimental.configFile": "./frontend/tailwind.config.js",
"[go]": {
"editor.defaultFormatter": "golang.go"
},
}

View File

@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[support@sysadminemedia.com](mailto:support@sysadminemedia.com).
[support@sysadminsmedia.com](mailto:support@sysadminsmedia.com).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View File

@@ -33,8 +33,6 @@ If you're using `taskfile` you can run `task --list-all` for a list of all comma
If you're using the taskfile, you can use the `task setup` command to run the required setup commands. Otherwise, you can review the commands required in the `Taskfile.yml` file.
Note that when installing dependencies with pnpm you must use the `--shamefully-hoist` flag. If you don't use this flag, you will get an error when running the frontend server.
### API Development Notes
start command `task go:run`
@@ -46,7 +44,7 @@ start command `task go:run`
start command `task ui:dev`
1. The frontend is a Vue 3 app with Nuxt.js that uses Tailwind and DaisyUI for styling.
1. The frontend is a Vue 3 app with Nuxt.js that uses Tailwind and Shadcn-vue for styling.
2. We're using Vitest for our automated testing. You can run these with `task ui:watch`.
3. Tests require the API server to be running, and in some cases the first run will fail due to a race condition. If this happens, just run the tests again and they should pass.

View File

@@ -1,5 +1,5 @@
# Node dependencies stage
FROM --platform=$TARGETPLATFORM node:18-alpine AS frontend-dependencies
FROM public.ecr.aws/docker/library/node:lts-alpine AS frontend-dependencies
WORKDIR /app
# Install pnpm globally (caching layer)
@@ -7,10 +7,10 @@ RUN npm install -g pnpm
# Copy package.json and lockfile to leverage caching
COPY frontend/package.json frontend/pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --shamefully-hoist
RUN pnpm install --frozen-lockfile
# Build Nuxt (frontend) stage
FROM --platform=$TARGETPLATFORM node:18-alpine AS frontend-builder
FROM public.ecr.aws/docker/library/node:lts-alpine AS frontend-builder
WORKDIR /app
# Install pnpm globally again (it can reuse the cache if not changed)
@@ -22,7 +22,7 @@ COPY --from=frontend-dependencies /app/node_modules ./node_modules
RUN pnpm build
# Go dependencies stage
FROM --platform=$TARGETPLATFORM golang:alpine AS builder-dependencies
FROM public.ecr.aws/docker/library/golang:alpine AS builder-dependencies
WORKDIR /go/src/app
# Copy go.mod and go.sum for better caching
@@ -30,7 +30,9 @@ COPY ./backend/go.mod ./backend/go.sum ./
RUN go mod download
# Build API stage
FROM --platform=$TARGETPLATFORM golang:alpine AS builder
FROM public.ecr.aws/docker/library/golang:alpine AS builder
ARG TARGETOS
ARG TARGETARCH
ARG BUILD_TIME
ARG COMMIT
ARG VERSION
@@ -38,7 +40,8 @@ ARG VERSION
# Install necessary build tools
RUN apk update && \
apk upgrade && \
apk add --no-cache git build-base gcc g++
apk add --no-cache git build-base gcc g++ && \
if [ "$TARGETARCH" != "arm" ] || [ "$TARGETARCH" != "riscv64" ]; then apk --no-cache add libwebp libavif libheif libjxl; fi
WORKDIR /go/src/app
@@ -52,19 +55,26 @@ COPY --from=frontend-builder /app/.output/public ./app/api/static/public
# Use cache for Go build artifacts
RUN --mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=linux go build \
-ldflags "-s -w -X main.commit=$COMMIT -X main.buildTime=$BUILD_TIME -X main.version=$VERSION" \
-o /go/bin/api \
-v ./app/api/*.go
if [ "$TARGETARCH" = "arm" ] || [ "$TARGETARCH" = "riscv64" ]; \
then echo "nodynamic" $TARGETOS $TARGETARCH; CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build \
-ldflags "-s -w -X main.commit=$COMMIT -X main.buildTime=$BUILD_TIME -X main.version=$VERSION" \
-tags nodynamic -o /go/bin/api -v ./app/api/*.go; \
else \
echo $TARGETOS $TARGETARCH; CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build \
-ldflags "-s -w -X main.commit=$COMMIT -X main.buildTime=$BUILD_TIME -X main.version=$VERSION" \
-o /go/bin/api -v ./app/api/*.go; \
fi
# Production stage
FROM --platform=$TARGETPLATFORM alpine:latest
FROM public.ecr.aws/docker/library/alpine:latest
ENV HBOX_MODE=production
ENV HBOX_STORAGE_DATA=/data/
ENV HBOX_STORAGE_SQLITE_URL=/data/homebox.db?_pragma=busy_timeout=2000&_pragma=journal_mode=WAL&_fk=1
ENV HBOX_STORAGE_CONN_STRING=file:///?no_tmp_dir=true
ENV HBOX_STORAGE_PREFIX_PATH=data
ENV HBOX_DATABASE_SQLITE_PATH=/data/homebox.db?_pragma=busy_timeout=2000&_pragma=journal_mode=WAL&_fk=1&_time_format=sqlite
# Install necessary runtime dependencies
RUN apk --no-cache add ca-certificates wget
RUN apk --no-cache add ca-certificates wget && \
if [ "$TARGETARCH" != "arm" ] || [ "$TARGETARCH" != "riscv64" ]; then apk --no-cache add libwebp libavif libheif libjxl; fi
# Create application directory and copy over built Go binary
RUN mkdir /app
@@ -75,7 +85,7 @@ RUN chmod +x /app/api
LABEL Name=homebox Version=0.0.1
LABEL org.opencontainers.image.source="https://github.com/sysadminsmedia/homebox"
# Expose necessary ports
# Expose necessary ports for Homebox
EXPOSE 7745
WORKDIR /app

View File

@@ -1,73 +1,108 @@
# Node dependencies
FROM node:18-alpine AS frontend-dependencies
# Node dependencies stage
FROM public.ecr.aws/docker/library/node:lts-alpine AS frontend-dependencies
WORKDIR /app
RUN npm install -g pnpm
COPY frontend/package.json frontend/pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --shamefully-hoist
# Build Nuxt
FROM node:18-alpine AS frontend-builder
# Install pnpm globally (caching layer)
RUN npm install -g pnpm
# Copy package.json and lockfile to leverage caching
COPY frontend/package.json frontend/pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# Build Nuxt (frontend) stage
FROM public.ecr.aws/docker/library/node:lts-alpine AS frontend-builder
WORKDIR /app
COPY frontend ./
# Install pnpm globally again (it can reuse the cache if not changed)
RUN npm install -g pnpm
# Copy over source files and node_modules from dependencies stage
COPY frontend .
COPY --from=frontend-dependencies /app/node_modules ./node_modules
RUN pnpm build
# Build Go dependencies
FROM golang:alpine AS builder-dependencies
# Go dependencies stage
FROM public.ecr.aws/docker/library/golang:alpine AS builder-dependencies
WORKDIR /go/src/app
# Copy go.mod and go.sum for better caching
COPY ./backend/go.mod ./backend/go.sum ./
RUN go mod download
# Build API
FROM golang:alpine AS builder
# Build API stage
FROM public.ecr.aws/docker/library/golang:alpine AS builder
ARG TARGETOS
ARG TARGETARCH
ARG BUILD_TIME
ARG COMMIT
ARG VERSION
RUN apk update && apk upgrade && apk add --no-cache git build-base gcc g++
# Install necessary build tools
RUN apk update && \
apk upgrade && \
apk add --no-cache git build-base gcc g++ && \
if [ "$TARGETARCH" != "arm" ] || [ "$TARGETARCH" != "riscv64" ]; then apk --no-cache add libwebp libavif libheif libjxl; fi
WORKDIR /go/src/app
# Copy Go modules (from dependencies stage) and source code
COPY --from=builder-dependencies /go/pkg/mod /go/pkg/mod
COPY ./backend .
# Clear old public files and copy new ones from frontend build
RUN rm -rf ./app/api/public
COPY --from=frontend-builder /app/.output/public ./app/api/static/public
COPY --from=builder-dependencies /go/pkg/mod /go/pkg/mod
# Use cache for Go build
# Use cache for Go build artifacts
RUN --mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=linux go build \
-ldflags "-s -w -X main.commit=$COMMIT -X main.buildTime=$BUILD_TIME -X main.version=$VERSION" \
-o /go/bin/api ./app/api/*.go
if [ "$TARGETARCH" = "arm" ] || [ "$TARGETARCH" = "riscv64" ]; \
then echo "nodynamic" $TARGETOS $TARGETARCH; CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build \
-ldflags "-s -w -X main.commit=$COMMIT -X main.buildTime=$BUILD_TIME -X main.version=$VERSION" \
-tags nodynamic -o /go/bin/api -v ./app/api/*.go; \
else \
echo $TARGETOS $TARGETARCH; CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build \
-ldflags "-s -w -X main.commit=$COMMIT -X main.buildTime=$BUILD_TIME -X main.version=$VERSION" \
-o /go/bin/api -v ./app/api/*.go; \
fi
# Production stage with distroless
FROM gcr.io/distroless/static:latest
RUN mkdir /data
# Production stage
FROM public.ecr.aws/docker/library/alpine:latest
ENV HBOX_MODE=production
ENV HBOX_STORAGE_DATA=/data/
ENV HBOX_STORAGE_SQLITE_URL=/data/homebox.db?_fk=1
ENV HBOX_STORAGE_CONN_STRING=file:///?no_tmp_dir=true
ENV HBOX_STORAGE_PREFIX_PATH=data
ENV HBOX_DATABASE_SQLITE_PATH=/data/homebox.db?_pragma=busy_timeout=2000&_pragma=journal_mode=WAL&_fk=1&_time_format=sqlite
# Copy the binary and data directory, change ownership
# Install necessary runtime dependencies
RUN apk --no-cache add ca-certificates wget && \
if [ "$TARGETARCH" != "arm" ] || [ "$TARGETARCH" != "riscv64" ]; then apk --no-cache add libwebp libavif libheif libjxl; fi
# Create a nonroot user with UID/GID 65532
RUN addgroup -g 65532 nonroot && adduser -u 65532 -G nonroot -S nonroot
# Create application directory and copy over built Go binary
RUN mkdir /app
COPY --from=builder --chown=nonroot /go/bin/api /app
COPY --from=builder --chown=nonroot /data /data
RUN chmod +x /app/api
# Add wget to the image
# Note: If using distroless, this may not be applicable
# as distroless images do not include package managers.
# This line may be omitted if you're relying on another way to handle healthchecks.
COPY --from=alpine:latest /bin/wget /usr/bin/wget
# Labels and configuration for the final image
LABEL Name=homebox Version=0.0.1
LABEL org.opencontainers.image.source="https://github.com/sysadminsmedia/homebox"
# Expose necessary ports for Homebox
EXPOSE 7745
WORKDIR /app
HEALTHCHECK --interval=30s \
--timeout=5s \
--start-period=5s \
--retries=3 \
CMD ["/usr/bin/wget", "--no-verbose", "--tries=1", "-O", "-", "http://localhost:7745/api/v1/status"]
# Healthcheck configuration
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
CMD [ "wget", "--no-verbose", "--tries=1", "-O", "-", "http://localhost:7745/api/v1/status" ]
VOLUME ["/data"]
# Persist volume for data
VOLUME [ "/data" ]
# Drop root and run as a low-privileged user
# Entrypoint and CMD
USER nonroot
ENTRYPOINT ["/app"]
CMD ["/data/config.yml"]
ENTRYPOINT [ "/app/api" ]
CMD [ "/data/config.yml" ]

View File

@@ -13,7 +13,7 @@
## What is HomeBox
Homebox is the inventory and organization system built for the Home User! With a focus on simplicity and ease of use, Homebox is the perfect solution for your home inventory, organization, and management needs. While developing this project, I've tried to keep the following principles in mind:
HomeBox is the inventory and organization system built for the Home User! With a focus on simplicity and ease of use, Homebox is the perfect solution for your home inventory, organization, and management needs. While developing this project, I've tried to keep the following principles in mind:
- _Simple_ - Homebox is designed to be simple and easy to use. No complicated setup or configuration required. Use either a single docker container, or deploy yourself by compiling the binary for your platform of choice.
- _Blazingly Fast_ - Homebox is written in Go, which makes it extremely fast and requires minimal resources to deploy. In general, idle memory usage is less than 50MB for the whole container.
@@ -21,6 +21,10 @@ Homebox is the inventory and organization system built for the Home User! With a
# Screenshots
Check out screenshots of the project [here](https://imgur.com/a/5gLWt2j).
You can also try the demo instances of Homebox:
- [Demo](https://demo.homebox.software)
- [Nightly](https://nightly.homebox.software)
- [VNext](https://vnext.homebox.software/)
## Quick Start

View File

@@ -2,7 +2,8 @@ version: "3"
env:
HBOX_LOG_LEVEL: debug
HBOX_STORAGE_SQLITE_URL: .data/homebox.db?_pragma=busy_timeout=1000&_pragma=journal_mode=WAL&_fk=1
HBOX_DATABASE_DRIVER: sqlite3
HBOX_DATABASE_SQLITE_PATH: .data/homebox.db?_pragma=busy_timeout=1000&_pragma=journal_mode=WAL&_fk=1&_time_format=sqlite
HBOX_OPTIONS_ALLOW_REGISTRATION: true
UNSAFE_DISABLE_PASSWORD_PROJECTION: "yes_i_am_sure"
tasks:
@@ -10,8 +11,9 @@ tasks:
desc: Install development dependencies
cmds:
- go install github.com/swaggo/swag/cmd/swag@latest
- go install github.com/pressly/goose/v3/cmd/goose@v3.8.0
- cd backend && go mod tidy
- cd frontend && pnpm install --shamefully-hoist
- cd frontend && pnpm install
swag:
desc: Generate swagger docs
@@ -23,17 +25,18 @@ tasks:
cmds:
- swag fmt --dir={{ .API }}
- swag init --dir={{ .API }},{{ .INTERNAL }}/core/services,{{ .INTERNAL }}/data/repo --parseDependency
- cp -r ./docs/swagger.json ../../../../docs/en/api/openapi-2.0.json
- cp -r ./docs/swagger.yaml ../../../../docs/en/api/openapi-2.0.yaml
sources:
- "./backend/app/api/**/*"
- "./backend/internal/data/**"
- "./backend/internal/core/services/**/*"
- "./backend/app/tools/typegen/main.go"
typescript-types:
desc: Generates typescript types from swagger definition
cmds:
- |
npx swagger-typescript-api \
pnpm dlx swagger-typescript-api generate \
--no-client \
--modular \
--path ./backend/app/api/static/docs/swagger.json \
@@ -49,7 +52,8 @@ tasks:
cmds:
- task: swag
- task: typescript-types
- cp ./backend/app/api/static/docs/swagger.json docs/docs/api/openapi-2.0.json
- cp ./backend/app/api/static/docs/swagger.json docs/en/api/openapi-2.0.json
- cp ./backend/app/api/static/docs/swagger.yaml docs/en/api/openapi-2.0.yaml
go:run:
env:
@@ -62,11 +66,38 @@ tasks:
- go run ./app/api/ {{ .CLI_ARGS }}
silent: false
go:run:postgresql:
env:
HBOX_DEMO: true
HBOX_DATABASE_DRIVER: postgres
HBOX_DATABASE_USERNAME: homebox
HBOX_DATABASE_PASSWORD: homebox
HBOX_DATABASE_DATABASE: homebox
HBOX_DATABASE_HOST: localhost
HBOX_DATABASE_PORT: 5432
HBOX_DATABASE_SSL_MODE: disable
desc: Starts the backend api server with postgresql (depends on generate task)
dir: backend
deps:
- generate
cmds:
- go run ./app/api/ {{ .CLI_ARGS }}
silent: false
go:ci:
env:
HBOX_DEMO: true
desc: Runs all go test and lint related tasks
dir: backend
cmds:
- go run ./app/api/ {{ .CLI_ARGS }} &
silent: true
go:test:
desc: Runs all go tests using gotestsum - supports passing gotestsum args
dir: backend
cmds:
- gotestsum {{ .CLI_ARGS }} ./...
- go test {{ .CLI_ARGS }} ./...
go:coverage:
desc: Runs all go tests with -race flag and generates a coverage report
@@ -109,13 +140,6 @@ tasks:
sources:
- "./backend/internal/data/ent/schema/**/*"
db:migration:
desc: Runs the database diff engine to generate a SQL migration files
deps:
- db:generate
cmds:
- cd backend && go run app/tools/migrations/main.go {{ .CLI_ARGS }}
ui:watch:
desc: Starts the vitest test runner in watch mode
dir: frontend
@@ -126,7 +150,14 @@ tasks:
desc: Run frontend development server
dir: frontend
cmds:
- pnpm dev
- pnpm dev --no-fork
ui:ci:
desc: Run frontend build in CI mode
dir: frontend
cmds:
- pnpm dev &
silent: true
ui:fix:
desc: Runs prettier and eslint on the frontend
@@ -145,10 +176,38 @@ tasks:
cmds:
- cd backend && go build ./app/api
- backend/api &
- sleep 5
- sleep 15
- cd frontend && pnpm run test:ci
silent: true
test:ci:postgresql:
env:
HBOX_DATABASE_DRIVER: postgres
HBOX_DATABASE_USERNAME: homebox
HBOX_DATABASE_PASSWORD: homebox
HBOX_DATABASE_DATABASE: homebox
HBOX_DATABASE_HOST: 127.0.0.1
HBOX_DATABASE_PORT: 5432
HBOX_DATABASE_SSL_MODE: disable
desc: Runs end-to-end test on a live server with postgresql (only for use in CI)
cmds:
- cd backend && go build ./app/api
- backend/api &
- sleep 15
- cd frontend && pnpm run test:ci
silent: true
test:e2e:
desc: Runs end-to-end test on a live server
dir: frontend
cmds:
- task: go:ci
- task: ui:ci
- pnpm exec playwright install-deps
- pnpm exec playwright install
- sleep 30
- TEST_SHUTDOWN_API_SERVER=true pnpm exec playwright test -c ./test/playwright.config.ts {{ .CLI_ARGS }}
pr:
desc: Runs all tasks required for a PR
cmds:

View File

@@ -1,74 +1,81 @@
run:
timeout: 10m
linters-settings:
goconst:
min-len: 5
min-occurrences: 5
exhaustive:
default-signifies-exhaustive: true
revive:
ignore-generated-header: false
severity: warning
confidence: 3
depguard:
rules:
main:
deny:
- pkg: io/util
desc: |
Deprecated: As of Go 1.16, the same functionality is now provided by
package io or package os, and those implementations should be
preferred in new code. See the specific function documentation for
details.
gocritic:
enabled-checks:
- ruleguard
testifylint:
enable-all: true
tagalign:
order:
- json
- schema
- yaml
- yml
- toml
- validate
version: "2"
linters:
disable-all: true
default: none
enable:
- asciicheck
- bodyclose
- copyloopvar
- depguard
- dogsled
- errcheck
- errorlint
- exhaustive
- copyloopvar
- gochecknoinits
- goconst
- gocritic
- gocyclo
- gofmt
- goprintffuncname
- gosimple
- govet
- ineffassign
- misspell
- nakedret
- revive
- sqlclosecheck
- staticcheck
- stylecheck
- tagalign
- testifylint
- typecheck
- typecheck
- unconvert
- unused
- whitespace
- zerologlint
- sqlclosecheck
settings:
depguard:
rules:
main:
deny:
- pkg: io/util
desc: |
Deprecated: As of Go 1.16, the same functionality is now provided by
package io or package os, and those implementations should be
preferred in new code. See the specific function documentation for
details.
exhaustive:
default-signifies-exhaustive: true
goconst:
min-len: 5
min-occurrences: 5
gocritic:
enabled-checks:
- ruleguard
revive:
confidence: 3
severity: warning
tagalign:
order:
- json
- schema
- yaml
- yml
- toml
- validate
testifylint:
enable-all: true
exclusions:
generated: lax
paths:
- internal/data/ent.*
- third_party$
- builtin$
- examples$
issues:
exclude-use-default: false
exclude-dirs:
- internal/data/ent.*
fix: true
formatters:
enable:
- gofmt
exclusions:
generated: lax
paths:
- internal/data/ent.*
- third_party$
- builtin$
- examples$

View File

@@ -1,3 +1,5 @@
version: 2
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com
before:
@@ -12,19 +14,43 @@ builds:
- linux
- windows
- darwin
- freebsd
goarch:
- amd64
- "386"
- arm
- arm64
- riscv64
ignore:
- goos: windows
goarch: arm
- goos: windows
goarch: "386"
- goos: freebsd
goarch: arm
- goos: freebsd
goarch: "386"
tags:
- >-
{{- if eq .Arch "riscv64" }}nodynamic
{{- else if eq .Arch "arm" }}nodynamic
{{- else if eq .Arch "386" }}nodynamic
{{- else if eq .Os "freebsd" }}nodynamic
{{ end }}
signs:
- cmd: cosign
stdin: "{{ .Env.COSIGN_PWD }}"
args:
- "sign-blob"
- "--key=cosign.key"
- "--output-signature=${signature}"
- "${artifact}"
- "--yes" # needed on cosign 2.0.0+
artifacts: all
archives:
- format: tar.gz
- formats: [ 'tar.gz' ]
# this name template makes the OS and Arch compatible with the results of uname.
name_template: >-
{{ .ProjectName }}_
@@ -36,11 +62,15 @@ archives:
# use zip for windows archives
format_overrides:
- goos: windows
format: zip
formats: [ 'zip' ]
release:
extra_files:
- glob: dist/*.sig
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
version_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:

View File

@@ -23,8 +23,9 @@ func NewTask(name string, interval time.Duration, fn func(context.Context)) *Bac
}
func (tsk *BackgroundTask) Start(ctx context.Context) error {
timer := time.NewTimer(tsk.Interval)
tsk.Fn(ctx)
timer := time.NewTimer(tsk.Interval)
for {
select {
case <-ctx.Done():

View File

@@ -13,6 +13,7 @@ import (
"github.com/sysadminsmedia/homebox/backend/internal/core/services"
"github.com/sysadminsmedia/homebox/backend/internal/core/services/reporting/eventbus"
"github.com/sysadminsmedia/homebox/backend/internal/data/repo"
"github.com/sysadminsmedia/homebox/backend/internal/sys/config"
"github.com/olahol/melody"
)
@@ -72,6 +73,7 @@ type V1Controller struct {
allowRegistration bool
bus *eventbus.EventBus
url string
config *config.Config
}
type (
@@ -84,22 +86,25 @@ type (
}
APISummary struct {
Healthy bool `json:"health"`
Versions []string `json:"versions"`
Title string `json:"title"`
Message string `json:"message"`
Build Build `json:"build"`
Demo bool `json:"demo"`
AllowRegistration bool `json:"allowRegistration"`
Healthy bool `json:"health"`
Versions []string `json:"versions"`
Title string `json:"title"`
Message string `json:"message"`
Build Build `json:"build"`
Latest services.Latest `json:"latest"`
Demo bool `json:"demo"`
AllowRegistration bool `json:"allowRegistration"`
LabelPrinting bool `json:"labelPrinting"`
}
)
func NewControllerV1(svc *services.AllServices, repos *repo.AllRepos, bus *eventbus.EventBus, options ...func(*V1Controller)) *V1Controller {
func NewControllerV1(svc *services.AllServices, repos *repo.AllRepos, bus *eventbus.EventBus, config *config.Config, options ...func(*V1Controller)) *V1Controller {
ctrl := &V1Controller{
repo: repos,
svc: svc,
allowRegistration: true,
bus: bus,
config: config,
}
for _, opt := range options {
@@ -111,11 +116,11 @@ func NewControllerV1(svc *services.AllServices, repos *repo.AllRepos, bus *event
// HandleBase godoc
//
// @Summary Application Info
// @Tags Base
// @Produce json
// @Success 200 {object} APISummary
// @Router /v1/status [GET]
// @Summary Application Info
// @Tags Base
// @Produce json
// @Success 200 {object} APISummary
// @Router /v1/status [GET]
func (ctrl *V1Controller) HandleBase(ready ReadyFunc, build Build) errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
return server.JSON(w, http.StatusOK, APISummary{
@@ -123,19 +128,21 @@ func (ctrl *V1Controller) HandleBase(ready ReadyFunc, build Build) errchain.Hand
Title: "Homebox",
Message: "Track, Manage, and Organize your Things",
Build: build,
Latest: ctrl.svc.BackgroundService.GetLatestVersion(),
Demo: ctrl.isDemo,
AllowRegistration: ctrl.allowRegistration,
LabelPrinting: ctrl.config.LabelMaker.PrintCommand != nil,
})
}
}
// HandleCurrency godoc
//
// @Summary Currency
// @Tags Base
// @Produce json
// @Success 200 {object} currencies.Currency
// @Router /v1/currency [GET]
// @Summary Currency
// @Tags Base
// @Produce json
// @Success 200 {object} currencies.Currency
// @Router /v1/currency [GET]
func (ctrl *V1Controller) HandleCurrency() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
// Set Cache for 10 Minutes

View File

@@ -0,0 +1,30 @@
package v1
import (
"net/url"
"github.com/rs/zerolog/log"
)
func GetHBURL(refererHeader, fallback string) (hbURL string) {
hbURL = refererHeader
if hbURL == "" {
hbURL = fallback
}
return stripPathFromURL(hbURL)
}
// stripPathFromURL removes the path from a URL.
// ex. https://example.com/tools -> https://example.com
func stripPathFromURL(rawURL string) string {
parsedURL, err := url.Parse(rawURL)
if err != nil {
log.Err(err).Msg("failed to parse URL")
return ""
}
strippedURL := url.URL{Scheme: parsedURL.Scheme, Host: parsedURL.Host}
return strippedURL.String()
}

View File

@@ -32,52 +32,65 @@ func actionHandlerFactory(ref string, fn func(context.Context, uuid.UUID) (int,
// HandleEnsureAssetID godoc
//
// @Summary Ensure Asset IDs
// @Description Ensures all items in the database have an asset ID
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/ensure-asset-ids [Post]
// @Security Bearer
// @Summary Ensure Asset IDs
// @Description Ensures all items in the database have an asset ID
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/ensure-asset-ids [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleEnsureAssetID() errchain.HandlerFunc {
return actionHandlerFactory("ensure asset IDs", ctrl.svc.Items.EnsureAssetID)
}
// HandleEnsureImportRefs godoc
//
// @Summary Ensures Import Refs
// @Description Ensures all items in the database have an import ref
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/ensure-import-refs [Post]
// @Security Bearer
// @Summary Ensures Import Refs
// @Description Ensures all items in the database have an import ref
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/ensure-import-refs [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleEnsureImportRefs() errchain.HandlerFunc {
return actionHandlerFactory("ensure import refs", ctrl.svc.Items.EnsureImportRef)
}
// HandleItemDateZeroOut godoc
//
// @Summary Zero Out Time Fields
// @Description Resets all item date fields to the beginning of the day
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/zero-item-time-fields [Post]
// @Security Bearer
// @Summary Zero Out Time Fields
// @Description Resets all item date fields to the beginning of the day
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/zero-item-time-fields [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleItemDateZeroOut() errchain.HandlerFunc {
return actionHandlerFactory("zero out date time", ctrl.repo.Items.ZeroOutTimeFields)
}
// HandleSetPrimaryPhotos godoc
//
// @Summary Set Primary Photos
// @Description Sets the first photo of each item as the primary photo
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/set-primary-photos [Post]
// @Security Bearer
// @Summary Set Primary Photos
// @Description Sets the first photo of each item as the primary photo
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/set-primary-photos [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleSetPrimaryPhotos() errchain.HandlerFunc {
return actionHandlerFactory("ensure asset IDs", ctrl.repo.Items.SetPrimaryPhotos)
}
// HandleCreateMissingThumbnails godoc
//
// @Summary Create Missing Thumbnails
// @Description Creates thumbnails for items that are missing them
// @Tags Actions
// @Produce json
// @Success 200 {object} ActionAmountResult
// @Router /v1/actions/create-missing-thumbnails [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleCreateMissingThumbnails() errchain.HandlerFunc {
return actionHandlerFactory("create missing thumbnails", ctrl.repo.Attachments.CreateMissingThumbnails)
}

View File

@@ -17,13 +17,13 @@ import (
// HandleAssetGet godocs
//
// @Summary Get Item by Asset ID
// @Tags Items
// @Produce json
// @Param id path string true "Asset ID"
// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{}
// @Router /v1/assets/{id} [GET]
// @Security Bearer
// @Summary Get Item by Asset ID
// @Tags Items
// @Produce json
// @Param id path string true "Asset ID"
// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{}
// @Router /v1/assets/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleAssetGet() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ctx := services.NewContext(r.Context())

View File

@@ -28,8 +28,8 @@ type (
}
LoginForm struct {
Username string `json:"username"`
Password string `json:"password"`
Username string `json:"username" example:"admin@admin.com"`
Password string `json:"password" example:"admin"`
StayLoggedIn bool `json:"stayLoggedIn"`
}
)
@@ -79,17 +79,15 @@ type AuthProvider interface {
// HandleAuthLogin godoc
//
// @Summary User Login
// @Tags Authentication
// @Accept x-www-form-urlencoded
// @Accept application/json
// @Param username formData string false "string" example(admin@admin.com)
// @Param password formData string false "string" example(admin)
// @Param payload body LoginForm true "Login Data"
// @Param provider query string false "auth provider"
// @Produce json
// @Success 200 {object} TokenResponse
// @Router /v1/users/login [POST]
// @Summary User Login
// @Tags Authentication
// @Accept x-www-form-urlencoded
// @Accept application/json
// @Param payload body LoginForm true "Login Data"
// @Param provider query string false "auth provider"
// @Produce json
// @Success 200 {object} TokenResponse
// @Router /v1/users/login [POST]
func (ctrl *V1Controller) HandleAuthLogin(ps ...AuthProvider) errchain.HandlerFunc {
if len(ps) == 0 {
panic("no auth providers provided")
@@ -131,11 +129,11 @@ func (ctrl *V1Controller) HandleAuthLogin(ps ...AuthProvider) errchain.HandlerFu
// HandleAuthLogout godoc
//
// @Summary User Logout
// @Tags Authentication
// @Success 204
// @Router /v1/users/logout [POST]
// @Security Bearer
// @Summary User Logout
// @Tags Authentication
// @Success 204
// @Router /v1/users/logout [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleAuthLogout() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
token := services.UseTokenCtx(r.Context())
@@ -155,13 +153,13 @@ func (ctrl *V1Controller) HandleAuthLogout() errchain.HandlerFunc {
// HandleAuthRefresh godoc
//
// @Summary User Token Refresh
// @Description handleAuthRefresh returns a handler that will issue a new token from an existing token.
// @Description This does not validate that the user still exists within the database.
// @Tags Authentication
// @Success 200
// @Router /v1/users/refresh [GET]
// @Security Bearer
// @Summary User Token Refresh
// @Description handleAuthRefresh returns a handler that will issue a new token from an existing token.
// @Description This does not validate that the user still exists within the database.
// @Tags Authentication
// @Success 200
// @Router /v1/users/refresh [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleAuthRefresh() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
requestToken := services.UseTokenCtx(r.Context())

View File

@@ -26,12 +26,12 @@ type (
// HandleGroupGet godoc
//
// @Summary Get Group
// @Tags Group
// @Produce json
// @Success 200 {object} repo.Group
// @Router /v1/groups [Get]
// @Security Bearer
// @Summary Get Group
// @Tags Group
// @Produce json
// @Success 200 {object} repo.Group
// @Router /v1/groups [Get]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupGet() errchain.HandlerFunc {
fn := func(r *http.Request) (repo.Group, error) {
auth := services.NewContext(r.Context())
@@ -43,13 +43,13 @@ func (ctrl *V1Controller) HandleGroupGet() errchain.HandlerFunc {
// HandleGroupUpdate godoc
//
// @Summary Update Group
// @Tags Group
// @Produce json
// @Param payload body repo.GroupUpdate true "User Data"
// @Success 200 {object} repo.Group
// @Router /v1/groups [Put]
// @Security Bearer
// @Summary Update Group
// @Tags Group
// @Produce json
// @Param payload body repo.GroupUpdate true "User Data"
// @Success 200 {object} repo.Group
// @Router /v1/groups [Put]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupUpdate() errchain.HandlerFunc {
fn := func(r *http.Request, body repo.GroupUpdate) (repo.Group, error) {
auth := services.NewContext(r.Context())
@@ -69,13 +69,13 @@ func (ctrl *V1Controller) HandleGroupUpdate() errchain.HandlerFunc {
// HandleGroupInvitationsCreate godoc
//
// @Summary Create Group Invitation
// @Tags Group
// @Produce json
// @Param payload body GroupInvitationCreate true "User Data"
// @Success 200 {object} GroupInvitation
// @Router /v1/groups/invitations [Post]
// @Security Bearer
// @Summary Create Group Invitation
// @Tags Group
// @Produce json
// @Param payload body GroupInvitationCreate true "User Data"
// @Success 200 {object} GroupInvitation
// @Router /v1/groups/invitations [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupInvitationsCreate() errchain.HandlerFunc {
fn := func(r *http.Request, body GroupInvitationCreate) (GroupInvitation, error) {
if body.ExpiresAt.IsZero() {

View File

@@ -4,10 +4,11 @@ import (
"database/sql"
"encoding/csv"
"errors"
"fmt"
"math/big"
"net/http"
"net/url"
"strings"
"time"
"github.com/google/uuid"
"github.com/hay-kot/httpkit/errchain"
@@ -21,18 +22,18 @@ import (
// HandleItemsGetAll godoc
//
// @Summary Query All Items
// @Tags Items
// @Produce json
// @Param q query string false "search string"
// @Param page query int false "page number"
// @Param pageSize query int false "items per page"
// @Param labels query []string false "label Ids" collectionFormat(multi)
// @Param locations query []string false "location Ids" collectionFormat(multi)
// @Param parentIds query []string false "parent Ids" collectionFormat(multi)
// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{}
// @Router /v1/items [GET]
// @Security Bearer
// @Summary Query All Items
// @Tags Items
// @Produce json
// @Param q query string false "search string"
// @Param page query int false "page number"
// @Param pageSize query int false "items per page"
// @Param labels query []string false "label Ids" collectionFormat(multi)
// @Param locations query []string false "location Ids" collectionFormat(multi)
// @Param parentIds query []string false "parent Ids" collectionFormat(multi)
// @Success 200 {object} repo.PaginationResult[repo.ItemSummary]{}
// @Router /v1/items [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleItemsGetAll() errchain.HandlerFunc {
extractQuery := func(r *http.Request) repo.ItemQuery {
params := r.URL.Query()
@@ -54,16 +55,18 @@ func (ctrl *V1Controller) HandleItemsGetAll() errchain.HandlerFunc {
}
v := repo.ItemQuery{
Page: queryIntOrNegativeOne(params.Get("page")),
PageSize: queryIntOrNegativeOne(params.Get("pageSize")),
Search: params.Get("q"),
LocationIDs: queryUUIDList(params, "locations"),
LabelIDs: queryUUIDList(params, "labels"),
NegateLabels: queryBool(params.Get("negateLabels")),
ParentItemIDs: queryUUIDList(params, "parentIds"),
IncludeArchived: queryBool(params.Get("includeArchived")),
Fields: filterFieldItems(params["fields"]),
OrderBy: params.Get("orderBy"),
Page: queryIntOrNegativeOne(params.Get("page")),
PageSize: queryIntOrNegativeOne(params.Get("pageSize")),
Search: params.Get("q"),
LocationIDs: queryUUIDList(params, "locations"),
LabelIDs: queryUUIDList(params, "labels"),
NegateLabels: queryBool(params.Get("negateLabels")),
OnlyWithoutPhoto: queryBool(params.Get("onlyWithoutPhoto")),
OnlyWithPhoto: queryBool(params.Get("onlyWithPhoto")),
ParentItemIDs: queryUUIDList(params, "parentIds"),
IncludeArchived: queryBool(params.Get("includeArchived")),
Fields: filterFieldItems(params["fields"]),
OrderBy: params.Get("orderBy"),
}
if strings.HasPrefix(v.Search, "#") {
@@ -85,6 +88,9 @@ func (ctrl *V1Controller) HandleItemsGetAll() errchain.HandlerFunc {
items, err := ctrl.repo.Items.QueryByGroup(ctx, ctx.GID, extractQuery(r))
totalPrice := new(big.Int)
for _, item := range items.Items {
if !item.SoldTime.IsZero() { // Skip items with a non-null SoldDate
continue
}
totalPrice.Add(totalPrice, big.NewInt(int64(item.PurchasePrice*100)))
}
@@ -106,13 +112,13 @@ func (ctrl *V1Controller) HandleItemsGetAll() errchain.HandlerFunc {
// HandleItemFullPath godoc
//
// @Summary Get the full path of an item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 200 {object} []repo.ItemPath
// @Router /v1/items/{id}/path [GET]
// @Security Bearer
// @Summary Get the full path of an item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 200 {object} []repo.ItemPath
// @Router /v1/items/{id}/path [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleItemFullPath() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID) ([]repo.ItemPath, error) {
auth := services.NewContext(r.Context())
@@ -148,13 +154,13 @@ func (ctrl *V1Controller) HandleItemFullPath() errchain.HandlerFunc {
// HandleItemsCreate godoc
//
// @Summary Create Item
// @Tags Items
// @Produce json
// @Param payload body repo.ItemCreate true "Item Data"
// @Success 201 {object} repo.ItemSummary
// @Router /v1/items [POST]
// @Security Bearer
// @Summary Create Item
// @Tags Items
// @Produce json
// @Param payload body repo.ItemCreate true "Item Data"
// @Success 201 {object} repo.ItemSummary
// @Router /v1/items [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleItemsCreate() errchain.HandlerFunc {
fn := func(r *http.Request, body repo.ItemCreate) (repo.ItemOut, error) {
return ctrl.svc.Items.Create(services.NewContext(r.Context()), body)
@@ -165,13 +171,13 @@ func (ctrl *V1Controller) HandleItemsCreate() errchain.HandlerFunc {
// HandleItemGet godocs
//
// @Summary Get Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [GET]
// @Security Bearer
// @Summary Get Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleItemGet() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID) (repo.ItemOut, error) {
auth := services.NewContext(r.Context())
@@ -184,13 +190,13 @@ func (ctrl *V1Controller) HandleItemGet() errchain.HandlerFunc {
// HandleItemDelete godocs
//
// @Summary Delete Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 204
// @Router /v1/items/{id} [DELETE]
// @Security Bearer
// @Summary Delete Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Success 204
// @Router /v1/items/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleItemDelete() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID) (any, error) {
auth := services.NewContext(r.Context())
@@ -203,14 +209,14 @@ func (ctrl *V1Controller) HandleItemDelete() errchain.HandlerFunc {
// HandleItemUpdate godocs
//
// @Summary Update Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Param payload body repo.ItemUpdate true "Item Data"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [PUT]
// @Security Bearer
// @Summary Update Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Param payload body repo.ItemUpdate true "Item Data"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleItemUpdate() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID, body repo.ItemUpdate) (repo.ItemOut, error) {
auth := services.NewContext(r.Context())
@@ -224,14 +230,14 @@ func (ctrl *V1Controller) HandleItemUpdate() errchain.HandlerFunc {
// HandleItemPatch godocs
//
// @Summary Update Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Param payload body repo.ItemPatch true "Item Data"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [Patch]
// @Security Bearer
// @Summary Update Item
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Param payload body repo.ItemPatch true "Item Data"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id} [Patch]
// @Security Bearer
func (ctrl *V1Controller) HandleItemPatch() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID, body repo.ItemPatch) (repo.ItemOut, error) {
auth := services.NewContext(r.Context())
@@ -250,13 +256,13 @@ func (ctrl *V1Controller) HandleItemPatch() errchain.HandlerFunc {
// HandleGetAllCustomFieldNames godocs
//
// @Summary Get All Custom Field Names
// @Tags Items
// @Produce json
// @Success 200
// @Router /v1/items/fields [GET]
// @Success 200 {object} []string
// @Security Bearer
// @Summary Get All Custom Field Names
// @Tags Items
// @Produce json
// @Success 200
// @Router /v1/items/fields [GET]
// @Success 200 {object} []string
// @Security Bearer
func (ctrl *V1Controller) HandleGetAllCustomFieldNames() errchain.HandlerFunc {
fn := func(r *http.Request) ([]string, error) {
auth := services.NewContext(r.Context())
@@ -268,13 +274,13 @@ func (ctrl *V1Controller) HandleGetAllCustomFieldNames() errchain.HandlerFunc {
// HandleGetAllCustomFieldValues godocs
//
// @Summary Get All Custom Field Values
// @Tags Items
// @Produce json
// @Success 200
// @Router /v1/items/fields/values [GET]
// @Success 200 {object} []string
// @Security Bearer
// @Summary Get All Custom Field Values
// @Tags Items
// @Produce json
// @Success 200
// @Router /v1/items/fields/values [GET]
// @Success 200 {object} []string
// @Security Bearer
func (ctrl *V1Controller) HandleGetAllCustomFieldValues() errchain.HandlerFunc {
type query struct {
Field string `schema:"field" validate:"required"`
@@ -290,13 +296,14 @@ func (ctrl *V1Controller) HandleGetAllCustomFieldValues() errchain.HandlerFunc {
// HandleItemsImport godocs
//
// @Summary Import Items
// @Tags Items
// @Produce json
// @Success 204
// @Param csv formData file true "Image to upload"
// @Router /v1/items/import [Post]
// @Security Bearer
// @Summary Import Items
// @Tags Items
// @Accept multipart/form-data
// @Produce json
// @Success 204
// @Param csv formData file true "Image to upload"
// @Router /v1/items/import [Post]
// @Security Bearer
func (ctrl *V1Controller) HandleItemsImport() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
err := r.ParseMultipartForm(ctrl.maxUploadSize << 20)
@@ -325,49 +332,29 @@ func (ctrl *V1Controller) HandleItemsImport() errchain.HandlerFunc {
// HandleItemsExport godocs
//
// @Summary Export Items
// @Tags Items
// @Success 200 {string} string "text/csv"
// @Router /v1/items/export [GET]
// @Security Bearer
// @Summary Export Items
// @Tags Items
// @Success 200 {string} string "text/csv"
// @Router /v1/items/export [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleItemsExport() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ctx := services.NewContext(r.Context())
csvData, err := ctrl.svc.Items.ExportCSV(r.Context(), ctx.GID, getHBURL(r.Header.Get("Referer"), ctrl.url))
csvData, err := ctrl.svc.Items.ExportCSV(r.Context(), ctx.GID, GetHBURL(r.Header.Get("Referer"), ctrl.url))
if err != nil {
log.Err(err).Msg("failed to export items")
return validate.NewRequestError(err, http.StatusInternalServerError)
}
timestamp := time.Now().Format("2006-01-02_15-04-05") // YYYY-MM-DD_HH-MM-SS format
filename := fmt.Sprintf("homebox-items_%s.csv", timestamp) // add timestamp to filename
w.Header().Set("Content-Type", "text/csv")
w.Header().Set("Content-Disposition", "attachment;filename=homebox-items.csv")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment;filename=%s", filename))
writer := csv.NewWriter(w)
writer.Comma = ','
return writer.WriteAll(csvData)
}
}
func getHBURL(refererHeader, fallback string) (hbURL string) {
hbURL = refererHeader
if hbURL == "" {
hbURL = fallback
}
return stripPathFromURL(hbURL)
}
// stripPathFromURL removes the path from a URL.
// ex. https://example.com/tools -> https://example.com
func stripPathFromURL(rawURL string) string {
parsedURL, err := url.Parse(rawURL)
if err != nil {
log.Err(err).Msg("failed to parse URL")
return ""
}
strippedURL := url.URL{Scheme: parsedURL.Scheme, Host: parsedURL.Host}
return strippedURL.String()
}

View File

@@ -3,7 +3,9 @@ package v1
import (
"errors"
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"
"github.com/hay-kot/httpkit/errchain"
@@ -13,6 +15,13 @@ import (
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/repo"
"github.com/sysadminsmedia/homebox/backend/internal/sys/validate"
"gocloud.dev/blob"
_ "gocloud.dev/blob/azureblob"
_ "gocloud.dev/blob/fileblob"
_ "gocloud.dev/blob/gcsblob"
_ "gocloud.dev/blob/memblob"
_ "gocloud.dev/blob/s3blob"
)
type (
@@ -23,17 +32,19 @@ type (
// HandleItemAttachmentCreate godocs
//
// @Summary Create Item Attachment
// @Tags Items Attachments
// @Produce json
// @Param id path string true "Item ID"
// @Param file formData file true "File attachment"
// @Param type formData string true "Type of file"
// @Param name formData string true "name of the file including extension"
// @Success 200 {object} repo.ItemOut
// @Failure 422 {object} validate.ErrorResponse
// @Router /v1/items/{id}/attachments [POST]
// @Security Bearer
// @Summary Create Item Attachment
// @Tags Items Attachments
// @Accept multipart/form-data
// @Produce json
// @Param id path string true "Item ID"
// @Param file formData file true "File attachment"
// @Param type formData string false "Type of file"
// @Param primary formData bool false "Is this the primary attachment"
// @Param name formData string true "name of the file including extension"
// @Success 200 {object} repo.ItemOut
// @Failure 422 {object} validate.ErrorResponse
// @Router /v1/items/{id}/attachments [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleItemAttachmentCreate() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
err := r.ParseMultipartForm(ctrl.maxUploadSize << 20)
@@ -72,13 +83,19 @@ func (ctrl *V1Controller) HandleItemAttachmentCreate() errchain.HandlerFunc {
ext := filepath.Ext(attachmentName)
switch strings.ToLower(ext) {
case ".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp", ".tiff":
case ".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp", ".tiff", ".avif", ".ico", ".heic", ".jxl":
attachmentType = attachment.TypePhoto.String()
default:
attachmentType = attachment.TypeAttachment.String()
}
}
primary, err := strconv.ParseBool(r.FormValue("primary"))
if err != nil {
log.Debug().Msg("failed to parse primary from form")
primary = false
}
id, err := ctrl.routeID(r)
if err != nil {
return err
@@ -91,6 +108,7 @@ func (ctrl *V1Controller) HandleItemAttachmentCreate() errchain.HandlerFunc {
id,
attachmentName,
attachment.Type(attachmentType),
primary,
file,
)
if err != nil {
@@ -104,41 +122,41 @@ func (ctrl *V1Controller) HandleItemAttachmentCreate() errchain.HandlerFunc {
// HandleItemAttachmentGet godocs
//
// @Summary Get Item Attachment
// @Tags Items Attachments
// @Produce application/octet-stream
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Success 200 {object} ItemAttachmentToken
// @Router /v1/items/{id}/attachments/{attachment_id} [GET]
// @Security Bearer
// @Summary Get Item Attachment
// @Tags Items Attachments
// @Produce application/octet-stream
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Success 200 {object} ItemAttachmentToken
// @Router /v1/items/{id}/attachments/{attachment_id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleItemAttachmentGet() errchain.HandlerFunc {
return ctrl.handleItemAttachmentsHandler
}
// HandleItemAttachmentDelete godocs
//
// @Summary Delete Item Attachment
// @Tags Items Attachments
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Success 204
// @Router /v1/items/{id}/attachments/{attachment_id} [DELETE]
// @Security Bearer
// @Summary Delete Item Attachment
// @Tags Items Attachments
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Success 204
// @Router /v1/items/{id}/attachments/{attachment_id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleItemAttachmentDelete() errchain.HandlerFunc {
return ctrl.handleItemAttachmentsHandler
}
// HandleItemAttachmentUpdate godocs
//
// @Summary Update Item Attachment
// @Tags Items Attachments
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Param payload body repo.ItemAttachmentUpdate true "Attachment Update"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id}/attachments/{attachment_id} [PUT]
// @Security Bearer
// @Summary Update Item Attachment
// @Tags Items Attachments
// @Param id path string true "Item ID"
// @Param attachment_id path string true "Attachment ID"
// @Param payload body repo.ItemAttachmentUpdate true "Attachment Update"
// @Success 200 {object} repo.ItemOut
// @Router /v1/items/{id}/attachments/{attachment_id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleItemAttachmentUpdate() errchain.HandlerFunc {
return ctrl.handleItemAttachmentsHandler
}
@@ -157,13 +175,39 @@ func (ctrl *V1Controller) handleItemAttachmentsHandler(w http.ResponseWriter, r
ctx := services.NewContext(r.Context())
switch r.Method {
case http.MethodGet:
doc, err := ctrl.svc.Items.AttachmentPath(r.Context(), attachmentID)
doc, err := ctrl.svc.Items.AttachmentPath(r.Context(), ctx.GID, attachmentID)
if err != nil {
log.Err(err).Msg("failed to get attachment path")
return validate.NewRequestError(err, http.StatusInternalServerError)
}
http.ServeFile(w, r, doc.Path)
bucket, err := blob.OpenBucket(ctx, ctrl.repo.Attachments.GetConnString())
if err != nil {
log.Err(err).Msg("failed to open bucket")
return validate.NewRequestError(err, http.StatusInternalServerError)
}
file, err := bucket.NewReader(ctx, doc.Path, nil)
if err != nil {
log.Err(err).Msg("failed to open file")
return validate.NewRequestError(err, http.StatusInternalServerError)
}
defer func(file *blob.Reader) {
err := file.Close()
if err != nil {
log.Err(err).Msg("failed to close file")
}
}(file)
defer func(bucket *blob.Bucket) {
err := bucket.Close()
if err != nil {
log.Err(err).Msg("failed to close bucket")
}
}(bucket)
// Set the Content-Disposition header for RFC6266 compliance
disposition := "attachment; filename*=UTF-8''" + url.QueryEscape(doc.Title)
w.Header().Set("Content-Disposition", disposition)
http.ServeContent(w, r, doc.Title, doc.CreatedAt, file)
return nil
// Delete Attachment Handler
@@ -186,9 +230,9 @@ func (ctrl *V1Controller) handleItemAttachmentsHandler(w http.ResponseWriter, r
}
attachment.ID = attachmentID
val, err := ctrl.svc.Items.AttachmentUpdate(ctx, ID, &attachment)
val, err := ctrl.svc.Items.AttachmentUpdate(ctx, ctx.GID, ID, &attachment)
if err != nil {
log.Err(err).Msg("failed to delete attachment")
log.Err(err).Msg("failed to update attachment")
return validate.NewRequestError(err, http.StatusInternalServerError)
}

View File

@@ -0,0 +1,136 @@
package v1
import (
"fmt"
"net/http"
"strconv"
"strings"
"github.com/go-chi/chi/v5"
"github.com/hay-kot/httpkit/errchain"
"github.com/sysadminsmedia/homebox/backend/internal/core/services"
"github.com/sysadminsmedia/homebox/backend/internal/data/repo"
"github.com/sysadminsmedia/homebox/backend/internal/sys/validate"
"github.com/sysadminsmedia/homebox/backend/internal/web/adapters"
"github.com/sysadminsmedia/homebox/backend/pkgs/labelmaker"
)
func generateOrPrint(ctrl *V1Controller, w http.ResponseWriter, r *http.Request, title string, description string, url string) error {
params := labelmaker.NewGenerateParams(int(ctrl.config.LabelMaker.Width), int(ctrl.config.LabelMaker.Height), int(ctrl.config.LabelMaker.Margin), int(ctrl.config.LabelMaker.Padding), ctrl.config.LabelMaker.FontSize, title, description, url, ctrl.config.LabelMaker.DynamicLength, ctrl.config.LabelMaker.AdditionalInformation)
print := queryBool(r.URL.Query().Get("print"))
if print {
err := labelmaker.PrintLabel(ctrl.config, &params)
if err != nil {
return err
}
_, err = w.Write([]byte("Printed!"))
return err
} else {
return labelmaker.GenerateLabel(w, &params)
}
}
// HandleGetLocationLabel godoc
//
// @Summary Get Location label
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Param print query bool false "Print this label, defaults to false"
// @Success 200 {string} string "image/png"
// @Router /v1/labelmaker/location/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGetLocationLabel() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ID, err := adapters.RouteUUID(r, "id")
if err != nil {
return err
}
auth := services.NewContext(r.Context())
location, err := ctrl.repo.Locations.GetOneByGroup(auth, auth.GID, ID)
if err != nil {
return err
}
hbURL := GetHBURL(r.Header.Get("Referer"), ctrl.url)
return generateOrPrint(ctrl, w, r, location.Name, "Homebox Location", fmt.Sprintf("%s/location/%s", hbURL, location.ID))
}
}
// HandleGetItemLabel godoc
//
// @Summary Get Item label
// @Tags Items
// @Produce json
// @Param id path string true "Item ID"
// @Param print query bool false "Print this label, defaults to false"
// @Success 200 {string} string "image/png"
// @Router /v1/labelmaker/item/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGetItemLabel() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
ID, err := adapters.RouteUUID(r, "id")
if err != nil {
return err
}
auth := services.NewContext(r.Context())
item, err := ctrl.repo.Items.GetOneByGroup(auth, auth.GID, ID)
if err != nil {
return err
}
description := ""
if item.Location != nil {
description += fmt.Sprintf("\nLocation: %s", item.Location.Name)
}
hbURL := GetHBURL(r.Header.Get("Referer"), ctrl.url)
return generateOrPrint(ctrl, w, r, item.Name, description, fmt.Sprintf("%s/item/%s", hbURL, item.ID))
}
}
// HandleGetAssetLabel godoc
//
// @Summary Get Asset label
// @Tags Items
// @Produce json
// @Param id path string true "Asset ID"
// @Param print query bool false "Print this label, defaults to false"
// @Success 200 {string} string "image/png"
// @Router /v1/labelmaker/assets/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGetAssetLabel() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
assetIDParam := chi.URLParam(r, "id")
assetIDParam = strings.ReplaceAll(assetIDParam, "-", "")
assetID, err := strconv.ParseInt(assetIDParam, 10, 64)
if err != nil {
return err
}
auth := services.NewContext(r.Context())
item, err := ctrl.repo.Items.QueryByAssetID(auth, auth.GID, repo.AssetID(assetID), 0, 1)
if err != nil {
return err
}
if len(item.Items) == 0 {
return validate.NewRequestError(fmt.Errorf("failed to find asset id"), http.StatusNotFound)
}
description := item.Items[0].Name
if item.Items[0].Location != nil {
description += fmt.Sprintf("\nLocation: %s", item.Items[0].Location.Name)
}
hbURL := GetHBURL(r.Header.Get("Referer"), ctrl.url)
return generateOrPrint(ctrl, w, r, item.Items[0].AssetID.String(), description, fmt.Sprintf("%s/a/%s", hbURL, item.Items[0].AssetID.String()))
}
}

View File

@@ -12,12 +12,12 @@ import (
// HandleLabelsGetAll godoc
//
// @Summary Get All Labels
// @Tags Labels
// @Produce json
// @Success 200 {object} []repo.LabelOut
// @Router /v1/labels [GET]
// @Security Bearer
// @Summary Get All Labels
// @Tags Labels
// @Produce json
// @Success 200 {object} []repo.LabelOut
// @Router /v1/labels [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelsGetAll() errchain.HandlerFunc {
fn := func(r *http.Request) ([]repo.LabelSummary, error) {
auth := services.NewContext(r.Context())
@@ -29,13 +29,13 @@ func (ctrl *V1Controller) HandleLabelsGetAll() errchain.HandlerFunc {
// HandleLabelsCreate godoc
//
// @Summary Create Label
// @Tags Labels
// @Produce json
// @Param payload body repo.LabelCreate true "Label Data"
// @Success 200 {object} repo.LabelSummary
// @Router /v1/labels [POST]
// @Security Bearer
// @Summary Create Label
// @Tags Labels
// @Produce json
// @Param payload body repo.LabelCreate true "Label Data"
// @Success 200 {object} repo.LabelSummary
// @Router /v1/labels [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelsCreate() errchain.HandlerFunc {
fn := func(r *http.Request, data repo.LabelCreate) (repo.LabelOut, error) {
auth := services.NewContext(r.Context())
@@ -47,13 +47,13 @@ func (ctrl *V1Controller) HandleLabelsCreate() errchain.HandlerFunc {
// HandleLabelDelete godocs
//
// @Summary Delete Label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 204
// @Router /v1/labels/{id} [DELETE]
// @Security Bearer
// @Summary Delete Label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 204
// @Router /v1/labels/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelDelete() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID) (any, error) {
auth := services.NewContext(r.Context())
@@ -66,13 +66,13 @@ func (ctrl *V1Controller) HandleLabelDelete() errchain.HandlerFunc {
// HandleLabelGet godocs
//
// @Summary Get Label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 200 {object} repo.LabelOut
// @Router /v1/labels/{id} [GET]
// @Security Bearer
// @Summary Get Label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 200 {object} repo.LabelOut
// @Router /v1/labels/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelGet() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID) (repo.LabelOut, error) {
auth := services.NewContext(r.Context())
@@ -84,13 +84,13 @@ func (ctrl *V1Controller) HandleLabelGet() errchain.HandlerFunc {
// HandleLabelUpdate godocs
//
// @Summary Update Label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 200 {object} repo.LabelOut
// @Router /v1/labels/{id} [PUT]
// @Security Bearer
// @Summary Update Label
// @Tags Labels
// @Produce json
// @Param id path string true "Label ID"
// @Success 200 {object} repo.LabelOut
// @Router /v1/labels/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleLabelUpdate() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID, data repo.LabelUpdate) (repo.LabelOut, error) {
auth := services.NewContext(r.Context())

View File

@@ -14,13 +14,13 @@ import (
// HandleLocationTreeQuery godoc
//
// @Summary Get Locations Tree
// @Tags Locations
// @Produce json
// @Param withItems query bool false "include items in response tree"
// @Success 200 {object} []repo.TreeItem
// @Router /v1/locations/tree [GET]
// @Security Bearer
// @Summary Get Locations Tree
// @Tags Locations
// @Produce json
// @Param withItems query bool false "include items in response tree"
// @Success 200 {object} []repo.TreeItem
// @Router /v1/locations/tree [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationTreeQuery() errchain.HandlerFunc {
fn := func(r *http.Request, query repo.TreeQuery) ([]repo.TreeItem, error) {
auth := services.NewContext(r.Context())
@@ -32,13 +32,13 @@ func (ctrl *V1Controller) HandleLocationTreeQuery() errchain.HandlerFunc {
// HandleLocationGetAll godoc
//
// @Summary Get All Locations
// @Tags Locations
// @Produce json
// @Param filterChildren query bool false "Filter locations with parents"
// @Success 200 {object} []repo.LocationOutCount
// @Router /v1/locations [GET]
// @Security Bearer
// @Summary Get All Locations
// @Tags Locations
// @Produce json
// @Param filterChildren query bool false "Filter locations with parents"
// @Success 200 {object} []repo.LocationOutCount
// @Router /v1/locations [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationGetAll() errchain.HandlerFunc {
fn := func(r *http.Request, q repo.LocationQuery) ([]repo.LocationOutCount, error) {
auth := services.NewContext(r.Context())
@@ -50,13 +50,13 @@ func (ctrl *V1Controller) HandleLocationGetAll() errchain.HandlerFunc {
// HandleLocationCreate godoc
//
// @Summary Create Location
// @Tags Locations
// @Produce json
// @Param payload body repo.LocationCreate true "Location Data"
// @Success 200 {object} repo.LocationSummary
// @Router /v1/locations [POST]
// @Security Bearer
// @Summary Create Location
// @Tags Locations
// @Produce json
// @Param payload body repo.LocationCreate true "Location Data"
// @Success 200 {object} repo.LocationSummary
// @Router /v1/locations [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationCreate() errchain.HandlerFunc {
fn := func(r *http.Request, createData repo.LocationCreate) (repo.LocationOut, error) {
auth := services.NewContext(r.Context())
@@ -68,13 +68,13 @@ func (ctrl *V1Controller) HandleLocationCreate() errchain.HandlerFunc {
// HandleLocationDelete godoc
//
// @Summary Delete Location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Success 204
// @Router /v1/locations/{id} [DELETE]
// @Security Bearer
// @Summary Delete Location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Success 204
// @Router /v1/locations/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationDelete() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID) (any, error) {
auth := services.NewContext(r.Context())
@@ -99,6 +99,11 @@ func (ctrl *V1Controller) GetLocationWithPrice(auth context.Context, gid uuid.UU
}
for _, item := range items.Items {
// Skip items with a non-zero SoldTime
if !item.SoldTime.IsZero() {
continue
}
// Convert item.Quantity to float64 for multiplication
quantity := float64(item.Quantity)
itemTotal := big.NewInt(int64(item.PurchasePrice * quantity * 100))
@@ -124,13 +129,13 @@ func (ctrl *V1Controller) GetLocationWithPrice(auth context.Context, gid uuid.UU
// HandleLocationGet godoc
//
// @Summary Get Location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Success 200 {object} repo.LocationOut
// @Router /v1/locations/{id} [GET]
// @Security Bearer
// @Summary Get Location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Success 200 {object} repo.LocationOut
// @Router /v1/locations/{id} [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationGet() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID) (repo.LocationOut, error) {
auth := services.NewContext(r.Context())
@@ -144,14 +149,14 @@ func (ctrl *V1Controller) HandleLocationGet() errchain.HandlerFunc {
// HandleLocationUpdate godoc
//
// @Summary Update Location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Param payload body repo.LocationUpdate true "Location Data"
// @Success 200 {object} repo.LocationOut
// @Router /v1/locations/{id} [PUT]
// @Security Bearer
// @Summary Update Location
// @Tags Locations
// @Produce json
// @Param id path string true "Location ID"
// @Param payload body repo.LocationUpdate true "Location Data"
// @Success 200 {object} repo.LocationOut
// @Router /v1/locations/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleLocationUpdate() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID, body repo.LocationUpdate) (repo.LocationOut, error) {
auth := services.NewContext(r.Context())

View File

@@ -12,13 +12,14 @@ import (
// HandleMaintenanceLogGet godoc
//
// @Summary Get Maintenance Log
// @Tags Item Maintenance
// @Produce json
// @Param filters query repo.MaintenanceFilters false "which maintenance to retrieve"
// @Success 200 {array} repo.MaintenanceEntryWithDetails[]
// @Router /v1/items/{id}/maintenance [GET]
// @Security Bearer
// @Summary Get Maintenance Log
// @Tags Item Maintenance
// @Produce json
// @Param id path string true "Item ID"
// @Param filters query repo.MaintenanceFilters false "which maintenance to retrieve"
// @Success 200 {array} repo.MaintenanceEntryWithDetails[]
// @Router /v1/items/{id}/maintenance [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleMaintenanceLogGet() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID, filters repo.MaintenanceFilters) ([]repo.MaintenanceEntryWithDetails, error) {
auth := services.NewContext(r.Context())
@@ -30,13 +31,14 @@ func (ctrl *V1Controller) HandleMaintenanceLogGet() errchain.HandlerFunc {
// HandleMaintenanceEntryCreate godoc
//
// @Summary Create Maintenance Entry
// @Tags Item Maintenance
// @Produce json
// @Param payload body repo.MaintenanceEntryCreate true "Entry Data"
// @Success 201 {object} repo.MaintenanceEntry
// @Router /v1/items/{id}/maintenance [POST]
// @Security Bearer
// @Summary Create Maintenance Entry
// @Tags Item Maintenance
// @Produce json
// @Param id path string true "Item ID"
// @Param payload body repo.MaintenanceEntryCreate true "Entry Data"
// @Success 201 {object} repo.MaintenanceEntry
// @Router /v1/items/{id}/maintenance [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleMaintenanceEntryCreate() errchain.HandlerFunc {
fn := func(r *http.Request, itemID uuid.UUID, body repo.MaintenanceEntryCreate) (repo.MaintenanceEntry, error) {
auth := services.NewContext(r.Context())

View File

@@ -12,13 +12,13 @@ import (
// HandleMaintenanceGetAll godoc
//
// @Summary Query All Maintenance
// @Tags Maintenance
// @Produce json
// @Param filters query repo.MaintenanceFilters false "which maintenance to retrieve"
// @Success 200 {array} repo.MaintenanceEntryWithDetails[]
// @Router /v1/maintenance [GET]
// @Security Bearer
// @Summary Query All Maintenance
// @Tags Maintenance
// @Produce json
// @Param filters query repo.MaintenanceFilters false "which maintenance to retrieve"
// @Success 200 {array} repo.MaintenanceEntryWithDetails[]
// @Router /v1/maintenance [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleMaintenanceGetAll() errchain.HandlerFunc {
fn := func(r *http.Request, filters repo.MaintenanceFilters) ([]repo.MaintenanceEntryWithDetails, error) {
auth := services.NewContext(r.Context())
@@ -30,13 +30,14 @@ func (ctrl *V1Controller) HandleMaintenanceGetAll() errchain.HandlerFunc {
// HandleMaintenanceEntryUpdate godoc
//
// @Summary Update Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Param payload body repo.MaintenanceEntryUpdate true "Entry Data"
// @Success 200 {object} repo.MaintenanceEntry
// @Router /v1/maintenance/{id} [PUT]
// @Security Bearer
// @Summary Update Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Param id path string true "Maintenance ID"
// @Param payload body repo.MaintenanceEntryUpdate true "Entry Data"
// @Success 200 {object} repo.MaintenanceEntry
// @Router /v1/maintenance/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleMaintenanceEntryUpdate() errchain.HandlerFunc {
fn := func(r *http.Request, entryID uuid.UUID, body repo.MaintenanceEntryUpdate) (repo.MaintenanceEntry, error) {
auth := services.NewContext(r.Context())
@@ -48,12 +49,13 @@ func (ctrl *V1Controller) HandleMaintenanceEntryUpdate() errchain.HandlerFunc {
// HandleMaintenanceEntryDelete godoc
//
// @Summary Delete Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Success 204
// @Router /v1/maintenance/{id} [DELETE]
// @Security Bearer
// @Summary Delete Maintenance Entry
// @Tags Maintenance
// @Produce json
// @Param id path string true "Maintenance ID"
// @Success 204
// @Router /v1/maintenance/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleMaintenanceEntryDelete() errchain.HandlerFunc {
fn := func(r *http.Request, entryID uuid.UUID) (any, error) {
auth := services.NewContext(r.Context())

View File

@@ -13,12 +13,12 @@ import (
// HandleGetUserNotifiers godoc
//
// @Summary Get Notifiers
// @Tags Notifiers
// @Produce json
// @Success 200 {object} []repo.NotifierOut
// @Router /v1/notifiers [GET]
// @Security Bearer
// @Summary Get Notifiers
// @Tags Notifiers
// @Produce json
// @Success 200 {object} []repo.NotifierOut
// @Router /v1/notifiers [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGetUserNotifiers() errchain.HandlerFunc {
fn := func(r *http.Request, _ struct{}) ([]repo.NotifierOut, error) {
user := services.UseUserCtx(r.Context())
@@ -30,13 +30,13 @@ func (ctrl *V1Controller) HandleGetUserNotifiers() errchain.HandlerFunc {
// HandleCreateNotifier godoc
//
// @Summary Create Notifier
// @Tags Notifiers
// @Produce json
// @Param payload body repo.NotifierCreate true "Notifier Data"
// @Success 200 {object} repo.NotifierOut
// @Router /v1/notifiers [POST]
// @Security Bearer
// @Summary Create Notifier
// @Tags Notifiers
// @Produce json
// @Param payload body repo.NotifierCreate true "Notifier Data"
// @Success 200 {object} repo.NotifierOut
// @Router /v1/notifiers [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleCreateNotifier() errchain.HandlerFunc {
fn := func(r *http.Request, in repo.NotifierCreate) (repo.NotifierOut, error) {
auth := services.NewContext(r.Context())
@@ -48,12 +48,12 @@ func (ctrl *V1Controller) HandleCreateNotifier() errchain.HandlerFunc {
// HandleDeleteNotifier godocs
//
// @Summary Delete a Notifier
// @Tags Notifiers
// @Param id path string true "Notifier ID"
// @Success 204
// @Router /v1/notifiers/{id} [DELETE]
// @Security Bearer
// @Summary Delete a Notifier
// @Tags Notifiers
// @Param id path string true "Notifier ID"
// @Success 204
// @Router /v1/notifiers/{id} [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleDeleteNotifier() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID) (any, error) {
auth := services.NewContext(r.Context())
@@ -65,13 +65,13 @@ func (ctrl *V1Controller) HandleDeleteNotifier() errchain.HandlerFunc {
// HandleUpdateNotifier godocs
//
// @Summary Update Notifier
// @Tags Notifiers
// @Param id path string true "Notifier ID"
// @Param payload body repo.NotifierUpdate true "Notifier Data"
// @Success 200 {object} repo.NotifierOut
// @Router /v1/notifiers/{id} [PUT]
// @Security Bearer
// @Summary Update Notifier
// @Tags Notifiers
// @Param id path string true "Notifier ID"
// @Param payload body repo.NotifierUpdate true "Notifier Data"
// @Success 200 {object} repo.NotifierOut
// @Router /v1/notifiers/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleUpdateNotifier() errchain.HandlerFunc {
fn := func(r *http.Request, ID uuid.UUID, in repo.NotifierUpdate) (repo.NotifierOut, error) {
auth := services.NewContext(r.Context())
@@ -83,14 +83,13 @@ func (ctrl *V1Controller) HandleUpdateNotifier() errchain.HandlerFunc {
// HandlerNotifierTest godoc
//
// @Summary Test Notifier
// @Tags Notifiers
// @Produce json
// @Param id path string true "Notifier ID"
// @Param url query string true "URL"
// @Success 204
// @Router /v1/notifiers/test [POST]
// @Security Bearer
// @Summary Test Notifier
// @Tags Notifiers
// @Produce json
// @Param url query string true "URL"
// @Success 204
// @Router /v1/notifiers/test [POST]
// @Security Bearer
func (ctrl *V1Controller) HandlerNotifierTest() errchain.HandlerFunc {
type body struct {
URL string `json:"url" validate:"required"`

View File

@@ -20,13 +20,13 @@ var qrcodeLogo []byte
// HandleGenerateQRCode godoc
//
// @Summary Create QR Code
// @Tags Items
// @Produce json
// @Param data query string false "data to be encoded into qrcode"
// @Success 200 {string} string "image/jpeg"
// @Router /v1/qrcode [GET]
// @Security Bearer
// @Summary Create QR Code
// @Tags Items
// @Produce json
// @Param data query string false "data to be encoded into qrcode"
// @Success 200 {string} string "image/jpeg"
// @Router /v1/qrcode [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGenerateQRCode() errchain.HandlerFunc {
type query struct {
// 4,296 characters is the maximum length of a QR code

View File

@@ -8,12 +8,12 @@ import (
// HandleBillOfMaterialsExport godoc
//
// @Summary Export Bill of Materials
// @Tags Reporting
// @Produce json
// @Success 200 {string} string "text/csv"
// @Router /v1/reporting/bill-of-materials [GET]
// @Security Bearer
// @Summary Export Bill of Materials
// @Tags Reporting
// @Produce json
// @Success 200 {string} string "text/csv"
// @Router /v1/reporting/bill-of-materials [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleBillOfMaterialsExport() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
actor := services.UseUserCtx(r.Context())

View File

@@ -14,12 +14,12 @@ import (
// HandleGroupStatisticsLocations godoc
//
// @Summary Get Location Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} []repo.TotalsByOrganizer
// @Router /v1/groups/statistics/locations [GET]
// @Security Bearer
// @Summary Get Location Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} []repo.TotalsByOrganizer
// @Router /v1/groups/statistics/locations [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupStatisticsLocations() errchain.HandlerFunc {
fn := func(r *http.Request) ([]repo.TotalsByOrganizer, error) {
auth := services.NewContext(r.Context())
@@ -31,12 +31,12 @@ func (ctrl *V1Controller) HandleGroupStatisticsLocations() errchain.HandlerFunc
// HandleGroupStatisticsLabels godoc
//
// @Summary Get Label Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} []repo.TotalsByOrganizer
// @Router /v1/groups/statistics/labels [GET]
// @Security Bearer
// @Summary Get Label Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} []repo.TotalsByOrganizer
// @Router /v1/groups/statistics/labels [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupStatisticsLabels() errchain.HandlerFunc {
fn := func(r *http.Request) ([]repo.TotalsByOrganizer, error) {
auth := services.NewContext(r.Context())
@@ -48,12 +48,12 @@ func (ctrl *V1Controller) HandleGroupStatisticsLabels() errchain.HandlerFunc {
// HandleGroupStatistics godoc
//
// @Summary Get Group Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} repo.GroupStatistics
// @Router /v1/groups/statistics [GET]
// @Security Bearer
// @Summary Get Group Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} repo.GroupStatistics
// @Router /v1/groups/statistics [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupStatistics() errchain.HandlerFunc {
fn := func(r *http.Request) (repo.GroupStatistics, error) {
auth := services.NewContext(r.Context())
@@ -65,14 +65,14 @@ func (ctrl *V1Controller) HandleGroupStatistics() errchain.HandlerFunc {
// HandleGroupStatisticsPriceOverTime godoc
//
// @Summary Get Purchase Price Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} repo.ValueOverTime
// @Param start query string false "start date"
// @Param end query string false "end date"
// @Router /v1/groups/statistics/purchase-price [GET]
// @Security Bearer
// @Summary Get Purchase Price Statistics
// @Tags Statistics
// @Produce json
// @Success 200 {object} repo.ValueOverTime
// @Param start query string false "start date"
// @Param end query string false "end date"
// @Router /v1/groups/statistics/purchase-price [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleGroupStatisticsPriceOverTime() errchain.HandlerFunc {
parseDate := func(datestr string, defaultDate time.Time) (time.Time, error) {
if datestr == "" {

View File

@@ -15,12 +15,12 @@ import (
// HandleUserRegistration godoc
//
// @Summary Register New User
// @Tags User
// @Produce json
// @Param payload body services.UserRegistration true "User Data"
// @Success 204
// @Router /v1/users/register [Post]
// @Summary Register New User
// @Tags User
// @Produce json
// @Param payload body services.UserRegistration true "User Data"
// @Success 204
// @Router /v1/users/register [Post]
func (ctrl *V1Controller) HandleUserRegistration() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
regData := services.UserRegistration{}
@@ -46,12 +46,12 @@ func (ctrl *V1Controller) HandleUserRegistration() errchain.HandlerFunc {
// HandleUserSelf godoc
//
// @Summary Get User Self
// @Tags User
// @Produce json
// @Success 200 {object} Wrapped{item=repo.UserOut}
// @Router /v1/users/self [GET]
// @Security Bearer
// @Summary Get User Self
// @Tags User
// @Produce json
// @Success 200 {object} Wrapped{item=repo.UserOut}
// @Router /v1/users/self [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelf() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
token := services.UseTokenCtx(r.Context())
@@ -67,13 +67,13 @@ func (ctrl *V1Controller) HandleUserSelf() errchain.HandlerFunc {
// HandleUserSelfUpdate godoc
//
// @Summary Update Account
// @Tags User
// @Produce json
// @Param payload body repo.UserUpdate true "User Data"
// @Success 200 {object} Wrapped{item=repo.UserUpdate}
// @Router /v1/users/self [PUT]
// @Security Bearer
// @Summary Update Account
// @Tags User
// @Produce json
// @Param payload body repo.UserUpdate true "User Data"
// @Success 200 {object} Wrapped{item=repo.UserUpdate}
// @Router /v1/users/self [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelfUpdate() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
updateData := repo.UserUpdate{}
@@ -94,12 +94,12 @@ func (ctrl *V1Controller) HandleUserSelfUpdate() errchain.HandlerFunc {
// HandleUserSelfDelete godoc
//
// @Summary Delete Account
// @Tags User
// @Produce json
// @Success 204
// @Router /v1/users/self [DELETE]
// @Security Bearer
// @Summary Delete Account
// @Tags User
// @Produce json
// @Success 204
// @Router /v1/users/self [DELETE]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelfDelete() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
if ctrl.isDemo {
@@ -124,12 +124,12 @@ type (
// HandleUserSelfChangePassword godoc
//
// @Summary Change Password
// @Tags User
// @Success 204
// @Param payload body ChangePassword true "Password Payload"
// @Router /v1/users/change-password [PUT]
// @Security Bearer
// @Summary Change Password
// @Tags User
// @Success 204
// @Param payload body ChangePassword true "Password Payload"
// @Router /v1/users/change-password [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelfChangePassword() errchain.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) error {
if ctrl.isDemo {

View File

@@ -18,7 +18,10 @@ func (a *app) setupLogger() {
}
level, err := zerolog.ParseLevel(a.conf.Log.Level)
if err == nil {
if err != nil {
log.Error().Err(err).Str("level", a.conf.Log.Level).Msg("invalid log level, falling back to info")
zerolog.SetGlobalLevel(zerolog.InfoLevel)
} else {
zerolog.SetGlobalLevel(level)
}
}

View File

@@ -1,18 +1,15 @@
package main
import (
"bytes"
"context"
"fmt"
"net/http"
"os"
"path/filepath"
"time"
atlas "ariga.io/atlas/sql/migrate"
"entgo.io/ent/dialect/sql/schema"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/pressly/goose/v3"
"github.com/sysadminsmedia/homebox/backend/internal/sys/analytics"
"net/http"
"strings"
"time"
"github.com/hay-kot/httpkit/errchain"
"github.com/hay-kot/httpkit/graceful"
@@ -28,7 +25,18 @@ import (
"github.com/sysadminsmedia/homebox/backend/internal/sys/config"
"github.com/sysadminsmedia/homebox/backend/internal/web/mid"
_ "github.com/lib/pq"
_ "github.com/sysadminsmedia/homebox/backend/internal/data/migrations/postgres"
_ "github.com/sysadminsmedia/homebox/backend/internal/data/migrations/sqlite3"
_ "github.com/sysadminsmedia/homebox/backend/pkgs/cgofreesqlite"
_ "gocloud.dev/pubsub/awssnssqs"
_ "gocloud.dev/pubsub/azuresb"
_ "gocloud.dev/pubsub/gcppubsub"
_ "gocloud.dev/pubsub/kafkapubsub"
_ "gocloud.dev/pubsub/mempubsub"
_ "gocloud.dev/pubsub/natspubsub"
_ "gocloud.dev/pubsub/rabbitpubsub"
)
var (
@@ -46,15 +54,33 @@ func build() string {
return fmt.Sprintf("%s, commit %s, built at %s", version, short, buildTime)
}
// @title Homebox API
// @version 1.0
// @description Track, Manage, and Organize your Things.
// @contact.name Don't
// @BasePath /api
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description "Type 'Bearer TOKEN' to correctly set the API Key"
func validatePostgresSSLMode(sslMode string) bool {
validModes := map[string]bool{
"": true,
"disable": true,
"allow": true,
"prefer": true,
"require": true,
"verify-ca": true,
"verify-full": true,
}
return validModes[strings.ToLower(strings.TrimSpace(sslMode))]
}
// @title Homebox API
// @version 1.0
// @description Track, Manage, and Organize your Things.
// @contact.name Homebox Team
// @contact.url https://discord.homebox.software
// @host demo.homebox.software
// @schemes https http
// @BasePath /api
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
// @description "Type 'Bearer TOKEN' to correctly set the API Key"
// @externalDocs.url https://homebox.software/en/api
func main() {
zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack
@@ -74,82 +100,45 @@ func run(cfg *config.Config) error {
// =========================================================================
// Initialize Database & Repos
setupStorageDir(cfg)
err := os.MkdirAll(cfg.Storage.Data, 0o755)
if err != nil {
log.Fatal().Err(err).Msg("failed to create data directory")
if strings.ToLower(cfg.Database.Driver) == "postgres" {
if !validatePostgresSSLMode(cfg.Database.SslMode) {
log.Fatal().Str("sslmode", cfg.Database.SslMode).Msg("invalid sslmode")
}
}
c, err := ent.Open("sqlite3", cfg.Storage.SqliteURL)
databaseURL := setupDatabaseURL(cfg)
c, err := ent.Open(strings.ToLower(cfg.Database.Driver), databaseURL)
if err != nil {
log.Fatal().
Err(err).
Str("driver", "sqlite").
Str("url", cfg.Storage.SqliteURL).
Msg("failed opening connection to sqlite")
Str("driver", strings.ToLower(cfg.Database.Driver)).
Str("host", cfg.Database.Host).
Str("port", cfg.Database.Port).
Str("database", cfg.Database.Database).
Msg("failed opening connection to {driver} database at {host}:{port}/{database}")
}
defer func(c *ent.Client) {
err := c.Close()
if err != nil {
log.Fatal().Err(err).Msg("failed to close database connection")
}
}(c)
temp := filepath.Join(os.TempDir(), "migrations")
err = migrations.Write(temp)
goose.SetBaseFS(migrations.Migrations(strings.ToLower(cfg.Database.Driver)))
err = goose.SetDialect(strings.ToLower(cfg.Database.Driver))
if err != nil {
log.Fatal().Str("driver", cfg.Database.Driver).Msg("unsupported database driver")
return fmt.Errorf("unsupported database driver: %s", cfg.Database.Driver)
}
err = goose.Up(c.Sql(), strings.ToLower(cfg.Database.Driver))
if err != nil {
log.Error().Err(err).Msg("failed to migrate database")
return err
}
dir, err := atlas.NewLocalDir(temp)
collectFuncs, err := loadCurrencies(cfg)
if err != nil {
return err
}
options := []schema.MigrateOption{
schema.WithDir(dir),
schema.WithDropColumn(true),
schema.WithDropIndex(true),
}
err = c.Schema.Create(context.Background(), options...)
if err != nil {
log.Error().
Err(err).
Str("driver", "sqlite").
Str("url", cfg.Storage.SqliteURL).
Msg("failed creating schema resources")
return err
}
err = os.RemoveAll(temp)
if err != nil {
log.Error().Err(err).Msg("failed to remove temporary directory for database migrations")
return err
}
collectFuncs := []currencies.CollectorFunc{
currencies.CollectDefaults(),
}
if cfg.Options.CurrencyConfig != "" {
log.Info().
Str("path", cfg.Options.CurrencyConfig).
Msg("loading currency config file")
content, err := os.ReadFile(cfg.Options.CurrencyConfig)
if err != nil {
log.Error().
Err(err).
Str("path", cfg.Options.CurrencyConfig).
Msg("failed to read currency config file")
return err
}
collectFuncs = append(collectFuncs, currencies.CollectJSON(bytes.NewReader(content)))
}
currencies, err := currencies.CollectionCurrencies(collectFuncs...)
if err != nil {
log.Error().
@@ -160,7 +149,7 @@ func run(cfg *config.Config) error {
app.bus = eventbus.New()
app.db = c
app.repos = repo.New(c, app.bus, cfg.Storage.Data)
app.repos = repo.New(c, app.bus, cfg.Storage, cfg.Database.PubSubConnString, cfg.Thumbnail)
app.services = services.New(
app.repos,
services.WithAutoIncrementAssetID(cfg.Options.AutoIncrementAssetID),
@@ -205,73 +194,30 @@ func run(cfg *config.Config) error {
return httpserver.ListenAndServe()
})
// =========================================================================
// Start Reoccurring Tasks
registerRecurringTasks(app, cfg, runner)
runner.AddFunc("eventbus", app.bus.Run)
runner.AddFunc("seed_database", func(ctx context.Context) error {
// TODO: Remove through external API that does setup
if cfg.Demo {
log.Info().Msg("Running in demo mode, creating demo data")
err := app.SetupDemo()
if err != nil {
log.Fatal().Msg(err.Error())
// Send analytics if enabled at around midnight UTC
if cfg.Options.AllowAnalytics {
analyticsTime := time.Second
runner.AddPlugin(NewTask("send-analytics", analyticsTime, func(ctx context.Context) {
for {
now := time.Now().UTC()
nextMidnight := time.Date(now.Year(), now.Month(), now.Day()+1, 0, 0, 0, 0, time.UTC)
dur := time.Until(nextMidnight)
analyticsTime = dur
select {
case <-ctx.Done():
return
case <-time.After(dur):
log.Debug().Msg("running send analytics")
err := analytics.Send(version, build())
if err != nil {
log.Error().Err(err).Msg("failed to send analytics")
}
}
}
}
return nil
})
runner.AddPlugin(NewTask("purge-tokens", time.Duration(24)*time.Hour, func(ctx context.Context) {
_, err := app.repos.AuthTokens.PurgeExpiredTokens(ctx)
if err != nil {
log.Error().
Err(err).
Msg("failed to purge expired tokens")
}
}))
runner.AddPlugin(NewTask("purge-invitations", time.Duration(24)*time.Hour, func(ctx context.Context) {
_, err := app.repos.Groups.InvitationPurge(ctx)
if err != nil {
log.Error().
Err(err).
Msg("failed to purge expired invitations")
}
}))
runner.AddPlugin(NewTask("send-notifications", time.Duration(1)*time.Hour, func(ctx context.Context) {
now := time.Now()
if now.Hour() == 8 {
fmt.Println("run notifiers")
err := app.services.BackgroundService.SendNotifiersToday(context.Background())
if err != nil {
log.Error().
Err(err).
Msg("failed to send notifiers")
}
}
}))
if cfg.Debug.Enabled {
runner.AddFunc("debug", func(ctx context.Context) error {
debugserver := http.Server{
Addr: fmt.Sprintf("%s:%s", cfg.Web.Host, cfg.Debug.Port),
Handler: app.debugRouter(),
ReadTimeout: cfg.Web.ReadTimeout,
WriteTimeout: cfg.Web.WriteTimeout,
IdleTimeout: cfg.Web.IdleTimeout,
}
go func() {
<-ctx.Done()
_ = debugserver.Shutdown(context.Background())
}()
log.Info().Msgf("Debug server is running on %s:%s", cfg.Web.Host, cfg.Debug.Port)
return debugserver.ListenAndServe()
})
}))
}
return runner.Start(context.Background())

View File

@@ -0,0 +1,150 @@
package main
import (
"context"
"fmt"
"github.com/hay-kot/httpkit/graceful"
"github.com/sysadminsmedia/homebox/backend/internal/sys/config"
"net/http"
"time"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
"github.com/sysadminsmedia/homebox/backend/pkgs/utils"
"gocloud.dev/pubsub"
)
func registerRecurringTasks(app *app, cfg *config.Config, runner *graceful.Runner) {
runner.AddFunc("eventbus", app.bus.Run)
runner.AddFunc("seed_database", func(ctx context.Context) error {
if cfg.Demo {
log.Info().Msg("Running in demo mode, creating demo data")
err := app.SetupDemo()
if err != nil {
log.Fatal().Msg(err.Error())
}
}
return nil
})
runner.AddPlugin(NewTask("purge-tokens", 24*time.Hour, func(ctx context.Context) {
_, err := app.repos.AuthTokens.PurgeExpiredTokens(ctx)
if err != nil {
log.Error().Err(err).Msg("failed to purge expired tokens")
}
}))
runner.AddPlugin(NewTask("purge-invitations", 24*time.Hour, func(ctx context.Context) {
_, err := app.repos.Groups.InvitationPurge(ctx)
if err != nil {
log.Error().Err(err).Msg("failed to purge expired invitations")
}
}))
runner.AddPlugin(NewTask("send-notifications", time.Hour, func(ctx context.Context) {
now := time.Now()
if now.Hour() == 8 {
fmt.Println("run notifiers")
err := app.services.BackgroundService.SendNotifiersToday(context.Background())
if err != nil {
log.Error().Err(err).Msg("failed to send notifiers")
}
}
}))
if cfg.Thumbnail.Enabled {
runner.AddFunc("create-thumbnails-subscription", func(ctx context.Context) error {
pubsubString, err := utils.GenerateSubPubConn(cfg.Database.PubSubConnString, "thumbnails")
if err != nil {
log.Error().Err(err).Msg("failed to generate pubsub connection string")
return err
}
topic, err := pubsub.OpenTopic(ctx, pubsubString)
if err != nil {
return err
}
defer func(topic *pubsub.Topic, ctx context.Context) {
err := topic.Shutdown(ctx)
if err != nil {
log.Err(err).Msg("fail to shutdown pubsub topic")
}
}(topic, ctx)
subscription, err := pubsub.OpenSubscription(ctx, pubsubString)
if err != nil {
log.Err(err).Msg("failed to open pubsub topic")
return err
}
defer func(topic *pubsub.Subscription, ctx context.Context) {
err := topic.Shutdown(ctx)
if err != nil {
log.Err(err).Msg("fail to shutdown pubsub topic")
}
}(subscription, ctx)
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
msg, err := subscription.Receive(ctx)
log.Debug().Msg("received thumbnail generation request from pubsub topic")
if err != nil {
log.Err(err).Msg("failed to receive message from pubsub topic")
continue
}
if msg == nil {
log.Warn().Msg("received nil message from pubsub topic")
continue
}
groupId, err := uuid.Parse(msg.Metadata["group_id"])
if err != nil {
log.Error().Err(err).Str("group_id", msg.Metadata["group_id"]).Msg("failed to parse group ID from message metadata")
}
attachmentId, err := uuid.Parse(msg.Metadata["attachment_id"])
if err != nil {
log.Error().Err(err).Str("attachment_id", msg.Metadata["attachment_id"]).Msg("failed to parse attachment ID from message metadata")
}
err = app.repos.Attachments.CreateThumbnail(ctx, groupId, attachmentId, msg.Metadata["title"], msg.Metadata["path"])
if err != nil {
log.Err(err).Msg("failed to create thumbnail")
}
msg.Ack()
}
}
})
}
if cfg.Options.GithubReleaseCheck {
runner.AddPlugin(NewTask("get-latest-github-release", time.Hour, func(ctx context.Context) {
log.Debug().Msg("running get latest github release")
err := app.services.BackgroundService.GetLatestGithubRelease(context.Background())
if err != nil {
log.Error().Err(err).Msg("failed to get latest github release")
}
}))
}
if cfg.Debug.Enabled {
runner.AddFunc("debug", func(ctx context.Context) error {
debugserver := http.Server{
Addr: fmt.Sprintf("%s:%s", cfg.Web.Host, cfg.Debug.Port),
Handler: app.debugRouter(),
ReadTimeout: cfg.Web.ReadTimeout,
WriteTimeout: cfg.Web.WriteTimeout,
IdleTimeout: cfg.Web.IdleTimeout,
}
go func() {
<-ctx.Done()
_ = debugserver.Shutdown(context.Background())
}()
log.Info().Msgf("Debug server is running on %s:%s", cfg.Web.Host, cfg.Debug.Port)
return debugserver.ListenAndServe()
})
// Print the configuration to the console
cfg.Print()
}
}

View File

@@ -52,6 +52,7 @@ func (a *app) mountRoutes(r *chi.Mux, chain *errchain.ErrChain, repos *repo.AllR
a.services,
a.repos,
a.bus,
a.conf,
v1.WithMaxUploadSize(a.conf.Web.MaxUploadSize),
v1.WithRegistration(a.conf.Options.AllowRegistration),
v1.WithDemoStatus(a.conf.Demo), // Disable Password Change in Demo Mode
@@ -101,6 +102,7 @@ func (a *app) mountRoutes(r *chi.Mux, chain *errchain.ErrChain, repos *repo.AllR
r.Post("/actions/zero-item-time-fields", chain.ToHandlerFunc(v1Ctrl.HandleItemDateZeroOut(), userMW...))
r.Post("/actions/ensure-import-refs", chain.ToHandlerFunc(v1Ctrl.HandleEnsureImportRefs(), userMW...))
r.Post("/actions/set-primary-photos", chain.ToHandlerFunc(v1Ctrl.HandleSetPrimaryPhotos(), userMW...))
r.Post("/actions/create-missing-thumbnails", chain.ToHandlerFunc(v1Ctrl.HandleCreateMissingThumbnails(), userMW...))
r.Get("/locations", chain.ToHandlerFunc(v1Ctrl.HandleLocationGetAll(), userMW...))
r.Post("/locations", chain.ToHandlerFunc(v1Ctrl.HandleLocationCreate(), userMW...))
@@ -161,6 +163,11 @@ func (a *app) mountRoutes(r *chi.Mux, chain *errchain.ErrChain, repos *repo.AllR
chain.ToHandlerFunc(v1Ctrl.HandleItemAttachmentGet(), assetMW...),
)
// Labelmaker
r.Get("/labelmaker/location/{id}", chain.ToHandlerFunc(v1Ctrl.HandleGetLocationLabel(), userMW...))
r.Get("/labelmaker/item/{id}", chain.ToHandlerFunc(v1Ctrl.HandleGetItemLabel(), userMW...))
r.Get("/labelmaker/asset/{id}", chain.ToHandlerFunc(v1Ctrl.HandleGetAssetLabel(), userMW...))
// Reporting Services
r.Get("/reporting/bill-of-materials", chain.ToHandlerFunc(v1Ctrl.HandleBillOfMaterialsExport(), userMW...))

93
backend/app/api/setup.go Normal file
View File

@@ -0,0 +1,93 @@
package main
import (
"bytes"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/rs/zerolog/log"
"github.com/sysadminsmedia/homebox/backend/internal/core/currencies"
"github.com/sysadminsmedia/homebox/backend/internal/sys/config"
)
// setupStorageDir handles the creation and validation of the storage directory.
func setupStorageDir(cfg *config.Config) {
if strings.HasPrefix(cfg.Storage.ConnString, "file:///./") {
raw := strings.TrimPrefix(cfg.Storage.ConnString, "file:///./")
clean := filepath.Clean(raw)
absBase, err := filepath.Abs(clean)
if err != nil {
log.Fatal().Err(err).Msg("failed to get absolute path for storage connection string")
}
storageDir := filepath.Join(absBase, cfg.Storage.PrefixPath)
storageDir = strings.ReplaceAll(storageDir, "\\", "/")
if !strings.HasPrefix(storageDir, absBase+"/") && storageDir != absBase {
log.Fatal().Str("path", storageDir).Msg("invalid storage path: you tried to use a prefix that is not a subdirectory of the base path")
}
if err := os.MkdirAll(storageDir, 0o750); err != nil {
log.Fatal().Err(err).Msg("failed to create data directory")
}
}
}
// setupDatabaseURL returns the database URL and ensures any required directories exist.
func setupDatabaseURL(cfg *config.Config) string {
databaseURL := ""
switch strings.ToLower(cfg.Database.Driver) {
case "sqlite3":
databaseURL = cfg.Database.SqlitePath
dbFilePath := strings.Split(cfg.Database.SqlitePath, "?")[0]
dbDir := filepath.Dir(dbFilePath)
if err := os.MkdirAll(dbDir, 0o755); err != nil {
log.Fatal().Err(err).Str("path", dbDir).Msg("failed to create SQLite database directory")
}
case "postgres":
databaseURL = fmt.Sprintf("host=%s port=%s dbname=%s sslmode=%s", cfg.Database.Host, cfg.Database.Port, cfg.Database.Database, cfg.Database.SslMode)
if cfg.Database.Username != "" {
databaseURL += fmt.Sprintf(" user=%s", cfg.Database.Username)
}
if cfg.Database.Password != "" {
databaseURL += fmt.Sprintf(" password=%s", cfg.Database.Password)
}
if cfg.Database.SslRootCert != "" {
if _, err := os.Stat(cfg.Database.SslRootCert); err != nil || !os.IsNotExist(err) {
log.Fatal().Err(err).Str("path", cfg.Database.SslRootCert).Msg("SSL root certificate file does not accessible")
}
databaseURL += fmt.Sprintf(" sslrootcert=%s", cfg.Database.SslRootCert)
}
if cfg.Database.SslCert != "" {
if _, err := os.Stat(cfg.Database.SslCert); err != nil || !os.IsNotExist(err) {
log.Fatal().Err(err).Str("path", cfg.Database.SslCert).Msg("SSL certificate file does not accessible")
}
databaseURL += fmt.Sprintf(" sslcert=%s", cfg.Database.SslCert)
}
if cfg.Database.SslKey != "" {
if _, err := os.Stat(cfg.Database.SslKey); err != nil || !os.IsNotExist(err) {
log.Fatal().Err(err).Str("path", cfg.Database.SslKey).Msg("SSL key file does not accessible")
}
databaseURL += fmt.Sprintf(" sslkey=%s", cfg.Database.SslKey)
}
default:
log.Fatal().Str("driver", cfg.Database.Driver).Msg("unsupported database driver")
}
return databaseURL
}
// loadCurrencies loads currency data from config if provided.
func loadCurrencies(cfg *config.Config) ([]currencies.CollectorFunc, error) {
collectFuncs := []currencies.CollectorFunc{
currencies.CollectDefaults(),
}
if cfg.Options.CurrencyConfig != "" {
log.Info().Str("path", cfg.Options.CurrencyConfig).Msg("loading currency config file")
content, err := os.ReadFile(cfg.Options.CurrencyConfig)
if err != nil {
log.Error().Err(err).Str("path", cfg.Options.CurrencyConfig).Msg("failed to read currency config file")
return nil, err
}
collectFuncs = append(collectFuncs, currencies.CollectJSON(bytes.NewReader(content)))
}
return collectFuncs, nil
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,45 +0,0 @@
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/migrate"
atlas "ariga.io/atlas/sql/migrate"
_ "ariga.io/atlas/sql/sqlite"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql/schema"
_ "github.com/mattn/go-sqlite3"
)
func main() {
ctx := context.Background()
// Create a local migration directory able to understand Atlas migration file format for replay.
dir, err := atlas.NewLocalDir("internal/data/migrations/migrations")
if err != nil {
log.Fatalf("failed creating atlas migration directory: %v", err)
}
// Migrate diff options.
opts := []schema.MigrateOption{
schema.WithDir(dir), // provide migration directory
schema.WithMigrationMode(schema.ModeReplay), // provide migration mode
schema.WithDialect(dialect.SQLite), // Ent dialect to use
schema.WithFormatter(atlas.DefaultFormatter),
schema.WithDropIndex(true),
schema.WithDropColumn(true),
}
if len(os.Args) != 2 {
log.Fatalln("migration name is required. Use: 'go run -mod=mod ent/migrate/main.go <name>'")
}
// Generate migrations using Atlas support for MySQL (note the Ent dialect option passed above).
err = migrate.NamedDiff(ctx, "sqlite://.data/homebox.migration.db?_fk=1", os.Args[1], opts...)
if err != nil {
log.Fatalf("failed generating migration file: %v", err)
}
fmt.Println("Migration file generated successfully.")
}

11
backend/cosign.key Normal file
View File

@@ -0,0 +1,11 @@
-----BEGIN ENCRYPTED SIGSTORE PRIVATE KEY-----
eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjo2NTUzNiwiciI6
OCwicCI6MX0sInNhbHQiOiJ3bmU3TTd2dndlL2FBS1piUEE2QktsdFNzMkhkSk9v
eXlvOTNLMnByRXdJPSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
Iiwibm9uY2UiOiJoOWdIMHRsYk9zMnZIbVBTYk5zaGxBQU5TYUlkcVZoQiJ9LCJj
aXBoZXJ0ZXh0IjoiTERiQk5ac3ZlVnRMbTlQdkRTa2t6bzRrWGExVGRTTEY5VzVO
cGd6M05GNVJLRWlGRmJQRDJDYzhnTWNkRmkrTU8xd2FTUzFGWWdXU3BIdnI3QXZ3
K0tUTXVWLzhSZ1pnOE9ieHNJY2xKSlZldHRLTzdzWXY2aWgxM09iZlVBV0lQcGpS
ZUQ5UmE3WjJwbWd0SkpBdjl2dlk1RGNNeGRKcFFrOEY1UStLZytSbnhLRUd6Z1ZN
MWUxdjF3UGhsOWhVRGRMSFVSTzE5Z0w3aFE9PSJ9
-----END ENCRYPTED SIGSTORE PRIVATE KEY-----

4
backend/cosign.pub Normal file
View File

@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2DXKcerPznDayM+rMJ/25w+ubI8g
e3ZTbm07VqLFz6uI2vXqN8X7/72dygtJlUw07FpR0oLXaSia0adaywz1JA==
-----END PUBLIC KEY-----

View File

@@ -1,76 +1,207 @@
module github.com/sysadminsmedia/homebox/backend
go 1.23.0
go 1.24
toolchain go1.24.3
require (
ariga.io/atlas v0.19.1
entgo.io/ent v0.14.1
github.com/ardanlabs/conf/v3 v3.1.8
entgo.io/ent v0.14.4
github.com/ardanlabs/conf/v3 v3.8.0
github.com/containrrr/shoutrrr v0.8.0
github.com/go-chi/chi/v5 v5.1.0
github.com/go-playground/validator/v10 v10.22.1
github.com/evanoberholster/imagemeta v0.3.1
github.com/gen2brain/avif v0.4.4
github.com/gen2brain/heic v0.4.5
github.com/gen2brain/jpegxl v0.4.5
github.com/gen2brain/webp v0.5.5
github.com/go-chi/chi/v5 v5.2.2
github.com/go-playground/validator/v10 v10.26.0
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/google/uuid v1.6.0
github.com/gorilla/schema v1.4.1
github.com/hay-kot/httpkit v0.0.11
github.com/mattn/go-sqlite3 v1.14.24
github.com/lib/pq v1.10.9
github.com/mattn/go-sqlite3 v1.14.28
github.com/olahol/melody v1.2.1
github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.33.0
github.com/stretchr/testify v1.9.0
github.com/pressly/goose/v3 v3.24.3
github.com/rs/zerolog v1.34.0
github.com/shirou/gopsutil/v4 v4.25.5
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.10.0
github.com/swaggo/http-swagger/v2 v2.0.2
github.com/swaggo/swag v1.16.3
github.com/yeqown/go-qrcode/v2 v2.2.4
github.com/yeqown/go-qrcode/writer/standard v1.2.4
golang.org/x/crypto v0.28.0
modernc.org/sqlite v1.33.1
github.com/swaggo/swag v1.16.4
github.com/yeqown/go-qrcode/v2 v2.2.5
github.com/yeqown/go-qrcode/writer/standard v1.3.0
github.com/zeebo/blake3 v0.2.4
gocloud.dev v0.41.0
gocloud.dev/pubsub/kafkapubsub v0.41.0
gocloud.dev/pubsub/natspubsub v0.41.0
gocloud.dev/pubsub/rabbitpubsub v0.41.0
golang.org/x/crypto v0.39.0
golang.org/x/image v0.28.0
golang.org/x/text v0.26.0
modernc.org/sqlite v1.37.1
)
require (
ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83 // indirect
cel.dev/expr v0.22.1 // indirect
cloud.google.com/go v0.120.0 // indirect
cloud.google.com/go/auth v0.15.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.4.2 // indirect
cloud.google.com/go/monitoring v1.24.1 // indirect
cloud.google.com/go/pubsub v1.48.0 // indirect
cloud.google.com/go/storage v1.51.0 // indirect
github.com/Azure/azure-amqp-common-go/v3 v3.2.3 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0 // indirect
github.com/Azure/go-amqp v1.4.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest/to v0.4.1 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 // indirect
github.com/IBM/sarama v1.45.1 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/aws/aws-sdk-go v1.55.6 // indirect
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect
github.com/aws/aws-sdk-go-v2/config v1.29.12 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.65 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.69 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.78.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sns v1.34.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sqs v1.38.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect
github.com/aws/smithy-go v1.22.3 // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/eapache/go-resiliency v1.7.0 // indirect
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fogleman/gg v1.3.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/spec v0.20.9 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/spec v0.20.6 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl/v2 v2.19.1 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/wire v0.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/hcl/v2 v2.13.0 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.7.6 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mfridman/interpolate v0.0.2 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/nats-io/nats.go v1.40.1 // indirect
github.com/nats-io/nkeys v0.4.10 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/philhofer/fwd v1.1.2 // indirect
github.com/pierrec/lz4/v4 v4.1.22 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/rabbitmq/amqp091-go v1.10.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/sethvargo/go-retry v0.3.0 // indirect
github.com/swaggo/files/v2 v2.0.0 // indirect
github.com/tetratelabs/wazero v1.9.0 // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/yeqown/reedsolomon v1.0.0 // indirect
github.com/zclconf/go-cty v1.14.1 // indirect
golang.org/x/image v0.18.0 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/tools v0.24.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
github.com/zclconf/go-cty v1.14.4 // indirect
github.com/zclconf/go-cty-yaml v1.1.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.35.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/oauth2 v0.28.0 // indirect
golang.org/x/sync v0.15.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.33.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
google.golang.org/api v0.228.0 // indirect
google.golang.org/genproto v0.0.0-20250324211829-b45e905df463 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
google.golang.org/grpc v1.71.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.55.3 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
modernc.org/libc v1.65.7 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
)

View File

@@ -1,21 +1,143 @@
ariga.io/atlas v0.19.1 h1:QzBHkakwzEhmPWOzNhw8Yr/Bbicj6Iq5hwEoNI/Jr9A=
ariga.io/atlas v0.19.1/go.mod h1:VPlcXdd4w2KqKnH54yEZcry79UAhpaWaxEsmn5JRNoE=
ariga.io/atlas v0.28.0 h1:qmn9tUyJypJkIw+X3ECUwDtkMTiFupgstHbjRN4xGH0=
ariga.io/atlas v0.28.0/go.mod h1:LOOp18LCL9r+VifvVlJqgYJwYl271rrXD9/wIyzJ8sw=
entgo.io/ent v0.12.5 h1:KREM5E4CSoej4zeGa88Ou/gfturAnpUv0mzAjch1sj4=
entgo.io/ent v0.12.5/go.mod h1:Y3JVAjtlIk8xVZYSn3t3mf8xlZIn5SAOXZQxD6kKI+Q=
entgo.io/ent v0.14.1 h1:fUERL506Pqr92EPHJqr8EYxbPioflJo6PudkrEA8a/s=
entgo.io/ent v0.14.1/go.mod h1:MH6XLG0KXpkcDQhKiHfANZSzR55TJyPL5IGNpI8wpco=
ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83 h1:nX4HXncwIdvQ8/8sIUIf1nyCkK8qdBaHQ7EtzPpuiGE=
ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w=
cel.dev/expr v0.22.1 h1:xoFEsNh972Yzey8N9TCPx2nDvMN7TMhQEzxLuj/iRrI=
cel.dev/expr v0.22.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA=
cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q=
cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps=
cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
cloud.google.com/go/iam v1.4.2 h1:4AckGYAYsowXeHzsn/LCKWIwSWLkdb0eGjH8wWkd27Q=
cloud.google.com/go/iam v1.4.2/go.mod h1:REGlrt8vSlh4dfCJfSEcNjLGq75wW75c5aU3FLOYq34=
cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc=
cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA=
cloud.google.com/go/longrunning v0.6.6 h1:XJNDo5MUfMM05xK3ewpbSdmt7R2Zw+aQEMbdQR65Rbw=
cloud.google.com/go/longrunning v0.6.6/go.mod h1:hyeGJUrPHcx0u2Uu1UFSoYZLn4lkMrccJig0t4FI7yw=
cloud.google.com/go/monitoring v1.24.1 h1:vKiypZVFD/5a3BbQMvI4gZdl8445ITzXFh257XBgrS0=
cloud.google.com/go/monitoring v1.24.1/go.mod h1:Z05d1/vn9NaujqY2voG6pVQXoJGbp+r3laV+LySt9K0=
cloud.google.com/go/pubsub v1.48.0 h1:ntFpQVrr10Wj/GXSOpxGmexGynldv/bFp25H0jy8aOs=
cloud.google.com/go/pubsub v1.48.0/go.mod h1:AAtyjyIT/+zaY1ERKFJbefOvkUxRDNp3nD6TdfdqUZk=
cloud.google.com/go/storage v1.51.0 h1:ZVZ11zCiD7b3k+cH5lQs/qcNaoSz3U9I0jgwVzqDlCw=
cloud.google.com/go/storage v1.51.0/go.mod h1:YEJfu/Ki3i5oHC/7jyTgsGZwdQ8P9hqMqvpi5kRKGgc=
cloud.google.com/go/trace v1.11.5 h1:CALS1loyxJMnRiCwZSpdf8ac7iCsjreMxFD2WGxzzHU=
cloud.google.com/go/trace v1.11.5/go.mod h1:TwblCcqNInriu5/qzaeYEIH7wzUcchSdeY2l5wL3Eec=
entgo.io/ent v0.14.4 h1:/DhDraSLXIkBhyiVoJeSshr4ZYi7femzhj6/TckzZuI=
entgo.io/ent v0.14.4/go.mod h1:aDPE/OziPEu8+OWbzy4UlvWmD2/kbRuWfK2A40hcxJM=
github.com/Azure/azure-amqp-common-go/v3 v3.2.3 h1:uDF62mbd9bypXWi19V1bN5NZEO84JqgmI5G73ibAmrk=
github.com/Azure/azure-amqp-common-go/v3 v3.2.3/go.mod h1:7rPmbSfszeovxGfc5fSAXE4ehlXQZHpMja2OtxC2Tas=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1 h1:DSDNVxqkoXJiko6x8a90zidoYqnYYa6c1MTzDKzKkTo=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.1/go.mod h1:zGqV2R4Cr/k8Uye5w+dgQ06WJtEcbQG/8J7BB6hnCr4=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.8.0 h1:JNgM3Tz592fUHU2vgwgvOgKxo5s9Ki0y2wicBeckn70=
github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus v1.8.0/go.mod h1:6vUKmzY17h6dpn9ZLAhM4R/rcrltBeq52qZIkUR7Oro=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0 h1:UXT0o77lXQrikd1kgwIPQOUect7EoR/+sbP4wQKdzxM=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.0/go.mod h1:cTvi54pg19DoT07ekoeMgE/taAwNtCShVeZqA+Iv2xI=
github.com/Azure/go-amqp v0.17.0/go.mod h1:9YJ3RhxRT1gquYnzpZO1vcYMMpAdJT+QEg6fwmw9Zlg=
github.com/Azure/go-amqp v1.4.0 h1:Xj3caqi4comOF/L1Uc5iuBxR/pB6KumejC01YQOqOR4=
github.com/Azure/go-amqp v1.4.0/go.mod h1:vZAogwdrkbyK3Mla8m/CxSc/aKdnTZ4IbPxl51Y5WZE=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/to v0.4.1 h1:CxNHBqdzTr7rLtdrtb5CMjJcDut+WNGCVv7OmS5+lTc=
github.com/Azure/go-autorest/autorest/to v0.4.1/go.mod h1:EtaofgU4zmtvn1zT2ARsjRFdq9vXx0YWtmElwL+GZ9M=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 h1:fYE9p3esPxA/C0rQ0AHhP0drtPXDRhaWiwg1DPqO7IU=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0/go.mod h1:BnBReJLvVYx2CS/UHOgVz2BXKXD9wsQPxZug20nZhd0=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0 h1:OqVGm6Ei3x5+yZmSJG1Mh2NwHvpVmZ08CB5qJhT9Nuk=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0/go.mod h1:SZiPHWGOOk3bl8tkevxkoiwPgsIl6CwrWcbwjfHZpdM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 h1:6/0iUd0xrnX7qt+mLNRwg5c0PGv8wpE8K90ryANQwMI=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0=
github.com/IBM/sarama v1.45.1 h1:nY30XqYpqyXOXSNoe2XCgjj9jklGM1Ye94ierUb1jQ0=
github.com/IBM/sarama v1.45.1/go.mod h1:qifDhA3VWSrQ1TjSMyxDl3nYL3oX2C83u+G6L79sq4w=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/ardanlabs/conf/v3 v3.1.8 h1:r0KUV9/Hni5XdeWR2+A1BiedIDnry5CjezoqgJ0rnFQ=
github.com/ardanlabs/conf/v3 v3.1.8/go.mod h1:OIi6NK95fj8jKFPdZ/UmcPlY37JBg99hdP9o5XmNK9c=
github.com/ardanlabs/conf/v3 v3.8.0 h1:Mvv2wZJz8tIl705m5BU3ZRCP1V6TKY6qebA8i4sykrY=
github.com/ardanlabs/conf/v3 v3.8.0/go.mod h1:XlL9P0quWP4m1weOVFmlezabinbZLI05niDof/+Ochk=
github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk=
github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14=
github.com/aws/aws-sdk-go-v2/config v1.29.12 h1:Y/2a+jLPrPbHpFkpAAYkVEtJmxORlXoo5k2g1fa2sUo=
github.com/aws/aws-sdk-go-v2/config v1.29.12/go.mod h1:xse1YTjmORlb/6fhkWi8qJh3cvZi4JoVNhc+NbJt4kI=
github.com/aws/aws-sdk-go-v2/credentials v1.17.65 h1:q+nV2yYegofO/SUXruT+pn4KxkxmaQ++1B/QedcKBFM=
github.com/aws/aws-sdk-go-v2/credentials v1.17.65/go.mod h1:4zyjAuGOdikpNYiSGpsGz8hLGmUzlY8pc8r9QQ/RXYQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.69 h1:6VFPH/Zi9xYFMJKPQOX5URYkQoXRWeJ7V/7Y6ZDYoms=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.69/go.mod h1:GJj8mmO6YT6EqgduWocwhMoxTLFitkhIrK+owzrYL2I=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 h1:ZNTqv4nIdE/DiBfUUfXcLZ/Spcuz+RjeziUtNJackkM=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34/go.mod h1:zf7Vcd1ViW7cPqYWEHLHJkS50X0JS2IKz9Cgaj6ugrs=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0 h1:lguz0bmOoGzozP9XfRJR1QIayEYo+2vP/No3OfLF0pU=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0/go.mod h1:iu6FSzgt+M2/x3Dk8zhycdIcHjEFb36IS8HVUVFoMg0=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 h1:moLQUoVq91LiqT1nbvzDukyqAlCv89ZmwaHw/ZFlFZg=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15/go.mod h1:ZH34PJUc8ApjBIfgQCFvkWcUDBtl/WTD+uiYHjd8igA=
github.com/aws/aws-sdk-go-v2/service/s3 v1.78.2 h1:jIiopHEV22b4yQP2q36Y0OmwLbsxNWdWwfZRR5QRRO4=
github.com/aws/aws-sdk-go-v2/service/s3 v1.78.2/go.mod h1:U5SNqwhXB3Xe6F47kXvWihPl/ilGaEDe8HD/50Z9wxc=
github.com/aws/aws-sdk-go-v2/service/sns v1.34.2 h1:PajtbJ/5bEo6iUAIGMYnK8ljqg2F1h4mMCGh1acjN30=
github.com/aws/aws-sdk-go-v2/service/sns v1.34.2/go.mod h1:PJtxxMdj747j8DeZENRTTYAz/lx/pADn/U0k7YNNiUY=
github.com/aws/aws-sdk-go-v2/service/sqs v1.38.3 h1:j5BchjfDoS7K26vPdyJlyxBIIBGDflq3qjjJKBDlbcI=
github.com/aws/aws-sdk-go-v2/service/sqs v1.38.3/go.mod h1:Bar4MrRxeqdn6XIh8JGfiXuFRmyrrsZNTJotxEJmWW0=
github.com/aws/aws-sdk-go-v2/service/sso v1.25.2 h1:pdgODsAhGo4dvzC3JAG5Ce0PX8kWXrTZGx+jxADD+5E=
github.com/aws/aws-sdk-go-v2/service/sso v1.25.2/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0 h1:90uX0veLKcdHVfvxhkWUQSCi5VabtwMLFutYiRke4oo=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.0/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs=
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 h1:PZV5W8yk4OtH1JAuhV2PXwwO9v5G5Aoj+eMCn4T+1Kc=
github.com/aws/aws-sdk-go-v2/service/sts v1.33.17/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4=
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f h1:C5bqEmzEPLsHm9Mv73lSE9e9bKV23aB1vxOsmZrkl3k=
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=
github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
github.com/containrrr/shoutrrr v0.8.0 h1:mfG2ATzIS7NR2Ec6XL+xyoHzN97H8WPjir8aYzJUSec=
github.com/containrrr/shoutrrr v0.8.0/go.mod h1:ioyQAyu1LJY6sILuNyKaQaw+9Ttik5QePU8atnAdO2o=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
@@ -23,45 +145,81 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/eapache/go-resiliency v1.7.0 h1:n3NRTnBn5N0Cbi/IeOHuQn9s2UwVUH7Ga0ZWcP+9JTA=
github.com/eapache/go-resiliency v1.7.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws=
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA=
github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A=
github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
github.com/evanoberholster/imagemeta v0.3.1 h1:E4GUjXcvlVMjP9joN25+bBNf3Al3MTTfMqCrDOCW+LE=
github.com/evanoberholster/imagemeta v0.3.1/go.mod h1:V0vtDJmjTqvwAYO8r+u33NRVIMXQb0qSqEfImoKEiXM=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/gen2brain/avif v0.4.4 h1:Ga/ss7qcWWQm2bxFpnjYjhJsNfZrWs5RsyklgFjKRSE=
github.com/gen2brain/avif v0.4.4/go.mod h1:/XCaJcjZraQwKVhpu9aEd9aLOssYOawLvhMBtmHVGqk=
github.com/gen2brain/heic v0.4.5 h1:Cq3hPu6wwlTJNv2t48ro3oWje54h82Q5pALeCBNgaSk=
github.com/gen2brain/heic v0.4.5/go.mod h1:ECnpqbqLu0qSje4KSNWUUDK47UPXPzl80T27GWGEL5I=
github.com/gen2brain/jpegxl v0.4.5 h1:TWpVEn5xkIfsswzkjHBArd0Cc9AE0tbjBSoa0jDsrbo=
github.com/gen2brain/jpegxl v0.4.5/go.mod h1:4kWYJ18xCEuO2vzocYdGpeqNJ990/Gjy3uLMg5TBN6I=
github.com/gen2brain/webp v0.5.5 h1:MvQR75yIPU/9nSqYT5h13k4URaJK3gf9tgz/ksRbyEg=
github.com/gen2brain/webp v0.5.5/go.mod h1:xOSMzp4aROt2KFW++9qcK/RBTOVC2S9tJG66ip/9Oc0=
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ=
github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
@@ -69,32 +227,107 @@ github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3a
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 h1:FWNFq4fM1wPfcK40yHE5UO3RUdSNPaBC+j3PokzA6OQ=
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-replayers/grpcreplay v1.3.0 h1:1Keyy0m1sIpqstQmgz307zhiJ1pV4uIlFds5weTmxbo=
github.com/google/go-replayers/grpcreplay v1.3.0/go.mod h1:v6NgKtkijC0d3e3RW8il6Sy5sqRVUwoQa4mHOGEy8DI=
github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk=
github.com/google/go-replayers/httpreplay v1.2.0/go.mod h1:WahEFFZZ7a1P4VM1qEeHy+tME4bwyqPcwWbNlUI1Mcg=
github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc=
github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI=
github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA=
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI=
github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/hcl/v2 v2.13.0 h1:0Apadu1w6M11dyGFxWnmhhcMjkbAiKCv7G1r/2QgCNc=
github.com/hashicorp/hcl/v2 v2.13.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
github.com/hay-kot/httpkit v0.0.11 h1:ZdB2uqsFBSDpfUoClGK5c5orjBjQkEVSXh7fZX5FKEk=
github.com/hay-kot/httpkit v0.0.11/go.mod h1:0kZdk5/swzdfqfg2c6pBWimcgeJ9PTyO97EbHnYl2Sw=
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs=
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -105,11 +338,14 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@@ -118,12 +354,24 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/nats-io/jwt/v2 v2.5.0 h1:WQQ40AAlqqfx+f6ku+i0pOVm+ASirD4fUh+oQsiE9Ak=
github.com/nats-io/jwt/v2 v2.5.0/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+vu/+ibI=
github.com/nats-io/nats-server/v2 v2.9.23 h1:6Wj6H6QpP9FMlpCyWUaNu2yeZ/qGj+mdRkZ1wbikExU=
github.com/nats-io/nats-server/v2 v2.9.23/go.mod h1:wEjrEy9vnqIGE4Pqz4/c75v9Pmaq7My2IgFmnykc4C0=
github.com/nats-io/nats.go v1.40.1 h1:MLjDkdsbGUeCMKFyCFoLnNn/HDTqcgVa3EQm+pMNDPk=
github.com/nats-io/nats.go v1.40.1/go.mod h1:wV73x0FSI/orHPSYoyMeJB+KajMDoWyXmFaRrrYaaTo=
github.com/nats-io/nkeys v0.4.10 h1:glmRrpCmYLHByYcePvnTBEAwawwapjCPMjy2huw20wc=
github.com/nats-io/nkeys v0.4.10/go.mod h1:OjRrnIKnWBFl+s4YK5ChQfvHP2fxqZexrKJoVVyWB3U=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -135,19 +383,44 @@ github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU=
github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pressly/goose/v3 v3.24.3 h1:DSWWNwwggVUsYZ0X2VitiAa9sKuqtBfe+Jr9zFGwWlM=
github.com/pressly/goose/v3 v3.24.3/go.mod h1:v9zYL4xdViLHCUUJh/mhjnm6JrK7Eul8AS93IxiZM4E=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc=
github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -156,88 +429,259 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
github.com/swaggo/http-swagger/v2 v2.0.2 h1:FKCdLsl+sFCx60KFsyM0rDarwiUSZ8DqbfSyIKC9OBg=
github.com/swaggo/http-swagger/v2 v2.0.2/go.mod h1:r7/GBkAWIfK6E/OLnE8fXnviHiDeAHmgIyooa4xm3AQ=
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
github.com/yeqown/go-qrcode/v2 v2.2.4 h1:cXdYlrhzHzVAnJHiwr/T6lAUmS9MtEStjEZBjArrvnc=
github.com/yeqown/go-qrcode/v2 v2.2.4/go.mod h1:uHpt9CM0V1HeXLz+Wg5MN50/sI/fQhfkZlOM+cOTHxw=
github.com/yeqown/go-qrcode/writer/standard v1.2.4 h1:41e/aLr1AMVWlug6oUMkDg2r0+dv5ofB7UaTkekKZBc=
github.com/yeqown/go-qrcode/writer/standard v1.2.4/go.mod h1:H8nLSGYUWBpNyBPjDcJzAanMzYBBYMFtrU2lwoSRn+k=
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/yeqown/go-qrcode/v2 v2.2.5 h1:HCOe2bSjkhZyYoyyNaXNzh4DJZll6inVJQQw+8228Zk=
github.com/yeqown/go-qrcode/v2 v2.2.5/go.mod h1:uHpt9CM0V1HeXLz+Wg5MN50/sI/fQhfkZlOM+cOTHxw=
github.com/yeqown/go-qrcode/writer/standard v1.3.0 h1:chdyhEfRtUPgQtuPeaWVGQ/TQx4rE1PqeoW3U+53t34=
github.com/yeqown/go-qrcode/writer/standard v1.3.0/go.mod h1:O4MbzsotGCvy8upYPCR91j81dr5XLT7heuljcNXW+oQ=
github.com/yeqown/reedsolomon v1.0.0 h1:x1h/Ej/uJnNu8jaX7GLHBWmZKCAWjEJTetkqaabr4B0=
github.com/yeqown/reedsolomon v1.0.0/go.mod h1:P76zpcn2TCuL0ul1Fso373qHRc69LKwAw/Iy6g1WiiM=
github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA=
github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8=
github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0=
github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs=
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/detectors/gcp v1.35.0 h1:bGvFt68+KTiAKFlacHW6AhA56GF2rS0bdD3aJYEnmzA=
go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I=
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
gocloud.dev v0.41.0 h1:qBKd9jZkBKEghYbP/uThpomhedK5s2Gy6Lz7h/zYYrM=
gocloud.dev v0.41.0/go.mod h1:IetpBcWLUwroOOxKr90lhsZ8vWxeSkuszBnW62sbcf0=
gocloud.dev/pubsub/kafkapubsub v0.41.0 h1:Ft6YB77ejqk++VjW51UP39RH/WDAMtv6ed3+PHMxBzg=
gocloud.dev/pubsub/kafkapubsub v0.41.0/go.mod h1:kJf4c6b+4yJk6nXmv33yXKblbrgWmrYCzI5QEsr27G0=
gocloud.dev/pubsub/natspubsub v0.41.0 h1:UxNb0DiAzdnyHut6jcCG7u6lsB/hzxTyZ/RHWeCUJ4Q=
gocloud.dev/pubsub/natspubsub v0.41.0/go.mod h1:uCBKjwvIcuNuf3+ft4wUI9hPHHKQvroxq9ZPB/410ac=
gocloud.dev/pubsub/rabbitpubsub v0.41.0 h1:RutvHbacZxlFr0t3wlr+kz63j53UOfHY3PJR8NKN1EI=
gocloud.dev/pubsub/rabbitpubsub v0.41.0/go.mod h1:s7oQXOlQ2FOj8XmYMv5Ocgs1t+8hIXfsKaWGgECM9SQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
golang.org/x/image v0.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE=
golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
google.golang.org/api v0.228.0 h1:X2DJ/uoWGnY5obVjewbp8icSL5U4FzuCfy9OjbLSnLs=
google.golang.org/api v0.228.0/go.mod h1:wNvRS1Pbe8r4+IfBIniV8fwCpGwTrYa+kMUDiC5z5a4=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20250324211829-b45e905df463 h1:qEFnJI6AnfZk0NNe8YTyXQh5i//Zxi4gBHwRgp76qpw=
google.golang.org/genproto v0.0.0-20250324211829-b45e905df463/go.mod h1:SqIx1NV9hcvqdLHo7uNZDS5lrUJybQ3evo3+z/WBfA0=
google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463 h1:hE3bRWtU6uceqlh4fhrSnUyjKHMKB9KrTLLG+bc0ddM=
google.golang.org/genproto/googleapis/api v0.0.0-20250324211829-b45e905df463/go.mod h1:U90ffi8eUL9MwPcrJylN5+Mk2v3vuPDptd5yyNUiRR8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U=
modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
modernc.org/sqlite v1.33.0 h1:WWkA/T2G17okiLGgKAj4/RMIvgyMT19yQ038160IeYk=
modernc.org/sqlite v1.33.0/go.mod h1:9uQ9hF/pCZoYZK73D/ud5Z7cIRIILSZI8NdIemVMTX8=
modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM=
modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8=
modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/libc v1.65.7 h1:Ia9Z4yzZtWNtUIuiPuQ7Qf7kxYrxP1/jeHZzG8bFu00=
modernc.org/libc v1.65.7/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.37.1 h1:EgHJK/FPoqC+q2YBXg7fUmES37pCHFc97sI7zSayBEs=
modernc.org/sqlite v1.37.1/go.mod h1:XwdRtsE1MpiBcL54+MbKcaDvcuej+IYSMfLN6gSKV8g=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=

File diff suppressed because it is too large Load Diff

View File

@@ -61,7 +61,7 @@ func New(repos *repo.AllRepos, opts ...OptionsFunc) *AllServices {
repo: repos,
autoIncrementAssetID: options.autoIncrementAssetID,
},
BackgroundService: &BackgroundService{repos},
BackgroundService: &BackgroundService{repos, Latest{}},
Currencies: currencies.NewCurrencyService(options.currencies),
}
}

View File

@@ -2,6 +2,7 @@ package services
import (
"context"
"github.com/sysadminsmedia/homebox/backend/internal/sys/config"
"log"
"os"
"testing"
@@ -50,7 +51,7 @@ func bootstrap() {
}
func MainNoExit(m *testing.M) int {
client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1&_time_format=sqlite")
if err != nil {
log.Fatalf("failed opening connection to sqlite: %v", err)
}
@@ -61,7 +62,19 @@ func MainNoExit(m *testing.M) int {
}
tClient = client
tRepos = repo.New(tClient, tbus, os.TempDir()+"/homebox")
tRepos = repo.New(tClient, tbus, config.Storage{
PrefixPath: "/",
ConnString: "file://" + os.TempDir(),
}, "mem://{{ .Topic }}", config.Thumbnail{
Enabled: false,
Width: 0,
Height: 0,
})
err = os.MkdirAll(os.TempDir()+"/homebox", 0o755)
if err != nil {
return 0
}
defaults, _ := currencies.CollectionCurrencies(
currencies.CollectDefaults(),

View File

@@ -2,6 +2,9 @@ package services
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
@@ -11,8 +14,13 @@ import (
"github.com/sysadminsmedia/homebox/backend/internal/data/types"
)
type Latest struct {
Version string `json:"version"`
Date string `json:"date"`
}
type BackgroundService struct {
repos *repo.AllRepos
repos *repo.AllRepos
latest Latest
}
func (svc *BackgroundService) SendNotifiersToday(ctx context.Context) error {
@@ -79,3 +87,52 @@ func (svc *BackgroundService) SendNotifiersToday(ctx context.Context) error {
return nil
}
func (svc *BackgroundService) GetLatestGithubRelease(ctx context.Context) error {
url := "https://api.github.com/repos/sysadminsmedia/homebox/releases/latest"
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return fmt.Errorf("failed to create latest version request: %w", err)
}
req.Header.Set("User-Agent", "Homebox-Version-Checker")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to make latest version request: %w", err)
}
defer func() {
err := resp.Body.Close()
if err != nil {
log.Printf("error closing latest version response body: %v", err)
}
}()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("latest version unexpected status code: %d", resp.StatusCode)
}
// ignoring fields that are not relevant
type Release struct {
ReleaseVersion string `json:"tag_name"`
PublishedAt time.Time `json:"published_at"`
}
var release Release
if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
return fmt.Errorf("failed to decode latest version response: %w", err)
}
svc.latest = Latest{
Version: release.ReleaseVersion,
Date: release.PublishedAt.String(),
}
return nil
}
func (svc *BackgroundService) GetLatestVersion() Latest {
return svc.latest
}

View File

@@ -2,35 +2,33 @@ package services
import (
"context"
"io"
"os"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/repo"
"io"
)
func (svc *ItemService) AttachmentPath(ctx context.Context, attachmentID uuid.UUID) (*ent.Document, error) {
attachment, err := svc.repo.Attachments.Get(ctx, attachmentID)
func (svc *ItemService) AttachmentPath(ctx context.Context, gid uuid.UUID, attachmentID uuid.UUID) (*ent.Attachment, error) {
attachment, err := svc.repo.Attachments.Get(ctx, gid, attachmentID)
if err != nil {
return nil, err
}
return attachment.Edges.Document, nil
return attachment, nil
}
func (svc *ItemService) AttachmentUpdate(ctx Context, itemID uuid.UUID, data *repo.ItemAttachmentUpdate) (repo.ItemOut, error) {
func (svc *ItemService) AttachmentUpdate(ctx Context, gid uuid.UUID, itemID uuid.UUID, data *repo.ItemAttachmentUpdate) (repo.ItemOut, error) {
// Update Attachment
attachment, err := svc.repo.Attachments.Update(ctx, data.ID, data)
attachment, err := svc.repo.Attachments.Update(ctx, gid, data.ID, data)
if err != nil {
return repo.ItemOut{}, err
}
// Update Document
attDoc := attachment.Edges.Document
_, err = svc.repo.Docs.Rename(ctx, attDoc.ID, data.Title)
attDoc := attachment
_, err = svc.repo.Attachments.Rename(ctx, gid, attDoc.ID, data.Title)
if err != nil {
return repo.ItemOut{}, err
}
@@ -41,50 +39,28 @@ func (svc *ItemService) AttachmentUpdate(ctx Context, itemID uuid.UUID, data *re
// AttachmentAdd adds an attachment to an item by creating an entry in the Documents table and linking it to the Attachment
// Table and Items table. The file provided via the reader is stored on the file system based on the provided
// relative path during construction of the service.
func (svc *ItemService) AttachmentAdd(ctx Context, itemID uuid.UUID, filename string, attachmentType attachment.Type, file io.Reader) (repo.ItemOut, error) {
func (svc *ItemService) AttachmentAdd(ctx Context, itemID uuid.UUID, filename string, attachmentType attachment.Type, primary bool, file io.Reader) (repo.ItemOut, error) {
// Get the Item
_, err := svc.repo.Items.GetOneByGroup(ctx, ctx.GID, itemID)
if err != nil {
return repo.ItemOut{}, err
}
// Create the document
doc, err := svc.repo.Docs.Create(ctx, ctx.GID, repo.DocumentCreate{Title: filename, Content: file})
if err != nil {
log.Err(err).Msg("failed to create document")
return repo.ItemOut{}, err
}
// Create the attachment
_, err = svc.repo.Attachments.Create(ctx, itemID, doc.ID, attachmentType)
_, err = svc.repo.Attachments.Create(ctx, itemID, repo.ItemCreateAttachment{Title: filename, Content: file}, attachmentType, primary)
if err != nil {
log.Err(err).Msg("failed to create attachment")
return repo.ItemOut{}, err
}
return svc.repo.Items.GetOneByGroup(ctx, ctx.GID, itemID)
}
func (svc *ItemService) AttachmentDelete(ctx context.Context, gid, itemID, attachmentID uuid.UUID) error {
// Get the Item
_, err := svc.repo.Items.GetOneByGroup(ctx, gid, itemID)
if err != nil {
return err
}
attachment, err := svc.repo.Attachments.Get(ctx, attachmentID)
if err != nil {
return err
}
func (svc *ItemService) AttachmentDelete(ctx context.Context, gid uuid.UUID, id uuid.UUID, attachmentID uuid.UUID) error {
// Delete the attachment
err = svc.repo.Attachments.Delete(ctx, attachmentID)
err := svc.repo.Attachments.Delete(ctx, gid, id, attachmentID)
if err != nil {
return err
}
// Remove File
err = os.Remove(attachment.Edges.Document.Path)
return err
}

View File

@@ -45,18 +45,18 @@ func TestItemService_AddAttachment(t *testing.T) {
reader := strings.NewReader(contents)
// Setup
afterAttachment, err := svc.AttachmentAdd(tCtx, itm.ID, "testfile.txt", "attachment", reader)
afterAttachment, err := svc.AttachmentAdd(tCtx, itm.ID, "testfile.txt", "attachment", false, reader)
require.NoError(t, err)
assert.NotNil(t, afterAttachment)
// Check that the file exists
storedPath := afterAttachment.Attachments[0].Document.Path
storedPath := afterAttachment.Attachments[0].Path
// {root}/{group}/{item}/{attachment}
assert.Equal(t, path.Join(temp, "homebox", tGroup.ID.String(), "documents"), path.Dir(storedPath))
assert.Equal(t, path.Join("/", tGroup.ID.String(), "documents"), path.Dir(storedPath))
// Check that the file contents are correct
bts, err := os.ReadFile(storedPath)
bts, err := os.ReadFile(path.Join(os.TempDir(), storedPath))
require.NoError(t, err)
assert.Equal(t, contents, string(bts))
}

View File

@@ -190,10 +190,23 @@ func (svc *UserService) Login(ctx context.Context, username, password string, ex
return UserAuthTokenDetail{}, ErrorInvalidLogin
}
if !hasher.CheckPasswordHash(password, usr.PasswordHash) {
check, rehash := hasher.CheckPasswordHash(password, usr.PasswordHash)
if !check {
return UserAuthTokenDetail{}, ErrorInvalidLogin
}
if rehash {
hash, err := hasher.HashPassword(password)
if err != nil {
log.Err(err).Msg("Failed to hash password")
return UserAuthTokenDetail{}, err
}
err = svc.repos.Users.ChangePassword(ctx, usr.ID, hash)
if err != nil {
return UserAuthTokenDetail{}, err
}
}
return svc.createSessionToken(ctx, usr.ID, extendedSession)
}
@@ -227,7 +240,8 @@ func (svc *UserService) ChangePassword(ctx Context, current string, new string)
return false
}
if !hasher.CheckPasswordHash(current, usr.PasswordHash) {
match, _ := hasher.CheckPasswordHash(current, usr.PasswordHash)
if !match {
log.Err(errors.New("current password is incorrect")).Msg("Failed to change password")
return false
}

View File

@@ -11,7 +11,6 @@ import (
"entgo.io/ent/dialect/sql"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
)
@@ -28,10 +27,16 @@ type Attachment struct {
Type attachment.Type `json:"type,omitempty"`
// Primary holds the value of the "primary" field.
Primary bool `json:"primary,omitempty"`
// Title holds the value of the "title" field.
Title string `json:"title,omitempty"`
// Path holds the value of the "path" field.
Path string `json:"path,omitempty"`
// MimeType holds the value of the "mime_type" field.
MimeType string `json:"mime_type,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the AttachmentQuery when eager-loading is set.
Edges AttachmentEdges `json:"edges"`
document_attachments *uuid.UUID
attachment_thumbnail *uuid.UUID
item_attachments *uuid.UUID
selectValues sql.SelectValues
}
@@ -40,8 +45,8 @@ type Attachment struct {
type AttachmentEdges struct {
// Item holds the value of the item edge.
Item *Item `json:"item,omitempty"`
// Document holds the value of the document edge.
Document *Document `json:"document,omitempty"`
// Thumbnail holds the value of the thumbnail edge.
Thumbnail *Attachment `json:"thumbnail,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [2]bool
@@ -58,15 +63,15 @@ func (e AttachmentEdges) ItemOrErr() (*Item, error) {
return nil, &NotLoadedError{edge: "item"}
}
// DocumentOrErr returns the Document value or an error if the edge
// ThumbnailOrErr returns the Thumbnail value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e AttachmentEdges) DocumentOrErr() (*Document, error) {
if e.Document != nil {
return e.Document, nil
func (e AttachmentEdges) ThumbnailOrErr() (*Attachment, error) {
if e.Thumbnail != nil {
return e.Thumbnail, nil
} else if e.loadedTypes[1] {
return nil, &NotFoundError{label: document.Label}
return nil, &NotFoundError{label: attachment.Label}
}
return nil, &NotLoadedError{edge: "document"}
return nil, &NotLoadedError{edge: "thumbnail"}
}
// scanValues returns the types for scanning values from sql.Rows.
@@ -76,13 +81,13 @@ func (*Attachment) scanValues(columns []string) ([]any, error) {
switch columns[i] {
case attachment.FieldPrimary:
values[i] = new(sql.NullBool)
case attachment.FieldType:
case attachment.FieldType, attachment.FieldTitle, attachment.FieldPath, attachment.FieldMimeType:
values[i] = new(sql.NullString)
case attachment.FieldCreatedAt, attachment.FieldUpdatedAt:
values[i] = new(sql.NullTime)
case attachment.FieldID:
values[i] = new(uuid.UUID)
case attachment.ForeignKeys[0]: // document_attachments
case attachment.ForeignKeys[0]: // attachment_thumbnail
values[i] = &sql.NullScanner{S: new(uuid.UUID)}
case attachment.ForeignKeys[1]: // item_attachments
values[i] = &sql.NullScanner{S: new(uuid.UUID)}
@@ -131,12 +136,30 @@ func (a *Attachment) assignValues(columns []string, values []any) error {
} else if value.Valid {
a.Primary = value.Bool
}
case attachment.FieldTitle:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field title", values[i])
} else if value.Valid {
a.Title = value.String
}
case attachment.FieldPath:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field path", values[i])
} else if value.Valid {
a.Path = value.String
}
case attachment.FieldMimeType:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field mime_type", values[i])
} else if value.Valid {
a.MimeType = value.String
}
case attachment.ForeignKeys[0]:
if value, ok := values[i].(*sql.NullScanner); !ok {
return fmt.Errorf("unexpected type %T for field document_attachments", values[i])
return fmt.Errorf("unexpected type %T for field attachment_thumbnail", values[i])
} else if value.Valid {
a.document_attachments = new(uuid.UUID)
*a.document_attachments = *value.S.(*uuid.UUID)
a.attachment_thumbnail = new(uuid.UUID)
*a.attachment_thumbnail = *value.S.(*uuid.UUID)
}
case attachment.ForeignKeys[1]:
if value, ok := values[i].(*sql.NullScanner); !ok {
@@ -163,9 +186,9 @@ func (a *Attachment) QueryItem() *ItemQuery {
return NewAttachmentClient(a.config).QueryItem(a)
}
// QueryDocument queries the "document" edge of the Attachment entity.
func (a *Attachment) QueryDocument() *DocumentQuery {
return NewAttachmentClient(a.config).QueryDocument(a)
// QueryThumbnail queries the "thumbnail" edge of the Attachment entity.
func (a *Attachment) QueryThumbnail() *AttachmentQuery {
return NewAttachmentClient(a.config).QueryThumbnail(a)
}
// Update returns a builder for updating this Attachment.
@@ -202,6 +225,15 @@ func (a *Attachment) String() string {
builder.WriteString(", ")
builder.WriteString("primary=")
builder.WriteString(fmt.Sprintf("%v", a.Primary))
builder.WriteString(", ")
builder.WriteString("title=")
builder.WriteString(a.Title)
builder.WriteString(", ")
builder.WriteString("path=")
builder.WriteString(a.Path)
builder.WriteString(", ")
builder.WriteString("mime_type=")
builder.WriteString(a.MimeType)
builder.WriteByte(')')
return builder.String()
}

View File

@@ -24,10 +24,16 @@ const (
FieldType = "type"
// FieldPrimary holds the string denoting the primary field in the database.
FieldPrimary = "primary"
// FieldTitle holds the string denoting the title field in the database.
FieldTitle = "title"
// FieldPath holds the string denoting the path field in the database.
FieldPath = "path"
// FieldMimeType holds the string denoting the mime_type field in the database.
FieldMimeType = "mime_type"
// EdgeItem holds the string denoting the item edge name in mutations.
EdgeItem = "item"
// EdgeDocument holds the string denoting the document edge name in mutations.
EdgeDocument = "document"
// EdgeThumbnail holds the string denoting the thumbnail edge name in mutations.
EdgeThumbnail = "thumbnail"
// Table holds the table name of the attachment in the database.
Table = "attachments"
// ItemTable is the table that holds the item relation/edge.
@@ -37,13 +43,10 @@ const (
ItemInverseTable = "items"
// ItemColumn is the table column denoting the item relation/edge.
ItemColumn = "item_attachments"
// DocumentTable is the table that holds the document relation/edge.
DocumentTable = "attachments"
// DocumentInverseTable is the table name for the Document entity.
// It exists in this package in order to avoid circular dependency with the "document" package.
DocumentInverseTable = "documents"
// DocumentColumn is the table column denoting the document relation/edge.
DocumentColumn = "document_attachments"
// ThumbnailTable is the table that holds the thumbnail relation/edge.
ThumbnailTable = "attachments"
// ThumbnailColumn is the table column denoting the thumbnail relation/edge.
ThumbnailColumn = "attachment_thumbnail"
)
// Columns holds all SQL columns for attachment fields.
@@ -53,12 +56,15 @@ var Columns = []string{
FieldUpdatedAt,
FieldType,
FieldPrimary,
FieldTitle,
FieldPath,
FieldMimeType,
}
// ForeignKeys holds the SQL foreign-keys that are owned by the "attachments"
// table and are not defined as standalone fields in the schema.
var ForeignKeys = []string{
"document_attachments",
"attachment_thumbnail",
"item_attachments",
}
@@ -86,6 +92,12 @@ var (
UpdateDefaultUpdatedAt func() time.Time
// DefaultPrimary holds the default value on creation for the "primary" field.
DefaultPrimary bool
// DefaultTitle holds the default value on creation for the "title" field.
DefaultTitle string
// DefaultPath holds the default value on creation for the "path" field.
DefaultPath string
// DefaultMimeType holds the default value on creation for the "mime_type" field.
DefaultMimeType string
// DefaultID holds the default value on creation for the "id" field.
DefaultID func() uuid.UUID
)
@@ -103,6 +115,7 @@ const (
TypeWarranty Type = "warranty"
TypeAttachment Type = "attachment"
TypeReceipt Type = "receipt"
TypeThumbnail Type = "thumbnail"
)
func (_type Type) String() string {
@@ -112,7 +125,7 @@ func (_type Type) String() string {
// TypeValidator is a validator for the "type" field enum values. It is called by the builders before save.
func TypeValidator(_type Type) error {
switch _type {
case TypePhoto, TypeManual, TypeWarranty, TypeAttachment, TypeReceipt:
case TypePhoto, TypeManual, TypeWarranty, TypeAttachment, TypeReceipt, TypeThumbnail:
return nil
default:
return fmt.Errorf("attachment: invalid enum value for type field: %q", _type)
@@ -147,6 +160,21 @@ func ByPrimary(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPrimary, opts...).ToFunc()
}
// ByTitle orders the results by the title field.
func ByTitle(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldTitle, opts...).ToFunc()
}
// ByPath orders the results by the path field.
func ByPath(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPath, opts...).ToFunc()
}
// ByMimeType orders the results by the mime_type field.
func ByMimeType(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldMimeType, opts...).ToFunc()
}
// ByItemField orders the results by item field.
func ByItemField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
@@ -154,10 +182,10 @@ func ByItemField(field string, opts ...sql.OrderTermOption) OrderOption {
}
}
// ByDocumentField orders the results by document field.
func ByDocumentField(field string, opts ...sql.OrderTermOption) OrderOption {
// ByThumbnailField orders the results by thumbnail field.
func ByThumbnailField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newDocumentStep(), sql.OrderByField(field, opts...))
sqlgraph.OrderByNeighborTerms(s, newThumbnailStep(), sql.OrderByField(field, opts...))
}
}
func newItemStep() *sqlgraph.Step {
@@ -167,10 +195,10 @@ func newItemStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.M2O, true, ItemTable, ItemColumn),
)
}
func newDocumentStep() *sqlgraph.Step {
func newThumbnailStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(DocumentInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, DocumentTable, DocumentColumn),
sqlgraph.To(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2O, false, ThumbnailTable, ThumbnailColumn),
)
}

View File

@@ -71,6 +71,21 @@ func Primary(v bool) predicate.Attachment {
return predicate.Attachment(sql.FieldEQ(FieldPrimary, v))
}
// Title applies equality check predicate on the "title" field. It's identical to TitleEQ.
func Title(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldEQ(FieldTitle, v))
}
// Path applies equality check predicate on the "path" field. It's identical to PathEQ.
func Path(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldEQ(FieldPath, v))
}
// MimeType applies equality check predicate on the "mime_type" field. It's identical to MimeTypeEQ.
func MimeType(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldEQ(FieldMimeType, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.Attachment {
return predicate.Attachment(sql.FieldEQ(FieldCreatedAt, v))
@@ -181,6 +196,201 @@ func PrimaryNEQ(v bool) predicate.Attachment {
return predicate.Attachment(sql.FieldNEQ(FieldPrimary, v))
}
// TitleEQ applies the EQ predicate on the "title" field.
func TitleEQ(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldEQ(FieldTitle, v))
}
// TitleNEQ applies the NEQ predicate on the "title" field.
func TitleNEQ(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldNEQ(FieldTitle, v))
}
// TitleIn applies the In predicate on the "title" field.
func TitleIn(vs ...string) predicate.Attachment {
return predicate.Attachment(sql.FieldIn(FieldTitle, vs...))
}
// TitleNotIn applies the NotIn predicate on the "title" field.
func TitleNotIn(vs ...string) predicate.Attachment {
return predicate.Attachment(sql.FieldNotIn(FieldTitle, vs...))
}
// TitleGT applies the GT predicate on the "title" field.
func TitleGT(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldGT(FieldTitle, v))
}
// TitleGTE applies the GTE predicate on the "title" field.
func TitleGTE(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldGTE(FieldTitle, v))
}
// TitleLT applies the LT predicate on the "title" field.
func TitleLT(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldLT(FieldTitle, v))
}
// TitleLTE applies the LTE predicate on the "title" field.
func TitleLTE(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldLTE(FieldTitle, v))
}
// TitleContains applies the Contains predicate on the "title" field.
func TitleContains(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldContains(FieldTitle, v))
}
// TitleHasPrefix applies the HasPrefix predicate on the "title" field.
func TitleHasPrefix(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldHasPrefix(FieldTitle, v))
}
// TitleHasSuffix applies the HasSuffix predicate on the "title" field.
func TitleHasSuffix(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldHasSuffix(FieldTitle, v))
}
// TitleEqualFold applies the EqualFold predicate on the "title" field.
func TitleEqualFold(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldEqualFold(FieldTitle, v))
}
// TitleContainsFold applies the ContainsFold predicate on the "title" field.
func TitleContainsFold(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldContainsFold(FieldTitle, v))
}
// PathEQ applies the EQ predicate on the "path" field.
func PathEQ(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldEQ(FieldPath, v))
}
// PathNEQ applies the NEQ predicate on the "path" field.
func PathNEQ(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldNEQ(FieldPath, v))
}
// PathIn applies the In predicate on the "path" field.
func PathIn(vs ...string) predicate.Attachment {
return predicate.Attachment(sql.FieldIn(FieldPath, vs...))
}
// PathNotIn applies the NotIn predicate on the "path" field.
func PathNotIn(vs ...string) predicate.Attachment {
return predicate.Attachment(sql.FieldNotIn(FieldPath, vs...))
}
// PathGT applies the GT predicate on the "path" field.
func PathGT(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldGT(FieldPath, v))
}
// PathGTE applies the GTE predicate on the "path" field.
func PathGTE(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldGTE(FieldPath, v))
}
// PathLT applies the LT predicate on the "path" field.
func PathLT(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldLT(FieldPath, v))
}
// PathLTE applies the LTE predicate on the "path" field.
func PathLTE(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldLTE(FieldPath, v))
}
// PathContains applies the Contains predicate on the "path" field.
func PathContains(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldContains(FieldPath, v))
}
// PathHasPrefix applies the HasPrefix predicate on the "path" field.
func PathHasPrefix(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldHasPrefix(FieldPath, v))
}
// PathHasSuffix applies the HasSuffix predicate on the "path" field.
func PathHasSuffix(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldHasSuffix(FieldPath, v))
}
// PathEqualFold applies the EqualFold predicate on the "path" field.
func PathEqualFold(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldEqualFold(FieldPath, v))
}
// PathContainsFold applies the ContainsFold predicate on the "path" field.
func PathContainsFold(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldContainsFold(FieldPath, v))
}
// MimeTypeEQ applies the EQ predicate on the "mime_type" field.
func MimeTypeEQ(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldEQ(FieldMimeType, v))
}
// MimeTypeNEQ applies the NEQ predicate on the "mime_type" field.
func MimeTypeNEQ(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldNEQ(FieldMimeType, v))
}
// MimeTypeIn applies the In predicate on the "mime_type" field.
func MimeTypeIn(vs ...string) predicate.Attachment {
return predicate.Attachment(sql.FieldIn(FieldMimeType, vs...))
}
// MimeTypeNotIn applies the NotIn predicate on the "mime_type" field.
func MimeTypeNotIn(vs ...string) predicate.Attachment {
return predicate.Attachment(sql.FieldNotIn(FieldMimeType, vs...))
}
// MimeTypeGT applies the GT predicate on the "mime_type" field.
func MimeTypeGT(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldGT(FieldMimeType, v))
}
// MimeTypeGTE applies the GTE predicate on the "mime_type" field.
func MimeTypeGTE(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldGTE(FieldMimeType, v))
}
// MimeTypeLT applies the LT predicate on the "mime_type" field.
func MimeTypeLT(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldLT(FieldMimeType, v))
}
// MimeTypeLTE applies the LTE predicate on the "mime_type" field.
func MimeTypeLTE(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldLTE(FieldMimeType, v))
}
// MimeTypeContains applies the Contains predicate on the "mime_type" field.
func MimeTypeContains(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldContains(FieldMimeType, v))
}
// MimeTypeHasPrefix applies the HasPrefix predicate on the "mime_type" field.
func MimeTypeHasPrefix(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldHasPrefix(FieldMimeType, v))
}
// MimeTypeHasSuffix applies the HasSuffix predicate on the "mime_type" field.
func MimeTypeHasSuffix(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldHasSuffix(FieldMimeType, v))
}
// MimeTypeEqualFold applies the EqualFold predicate on the "mime_type" field.
func MimeTypeEqualFold(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldEqualFold(FieldMimeType, v))
}
// MimeTypeContainsFold applies the ContainsFold predicate on the "mime_type" field.
func MimeTypeContainsFold(v string) predicate.Attachment {
return predicate.Attachment(sql.FieldContainsFold(FieldMimeType, v))
}
// HasItem applies the HasEdge predicate on the "item" edge.
func HasItem() predicate.Attachment {
return predicate.Attachment(func(s *sql.Selector) {
@@ -204,21 +414,21 @@ func HasItemWith(preds ...predicate.Item) predicate.Attachment {
})
}
// HasDocument applies the HasEdge predicate on the "document" edge.
func HasDocument() predicate.Attachment {
// HasThumbnail applies the HasEdge predicate on the "thumbnail" edge.
func HasThumbnail() predicate.Attachment {
return predicate.Attachment(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, DocumentTable, DocumentColumn),
sqlgraph.Edge(sqlgraph.O2O, false, ThumbnailTable, ThumbnailColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasDocumentWith applies the HasEdge predicate on the "document" edge with a given conditions (other predicates).
func HasDocumentWith(preds ...predicate.Document) predicate.Attachment {
// HasThumbnailWith applies the HasEdge predicate on the "thumbnail" edge with a given conditions (other predicates).
func HasThumbnailWith(preds ...predicate.Attachment) predicate.Attachment {
return predicate.Attachment(func(s *sql.Selector) {
step := newDocumentStep()
step := newThumbnailStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)

View File

@@ -12,7 +12,6 @@ import (
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
)
@@ -79,6 +78,48 @@ func (ac *AttachmentCreate) SetNillablePrimary(b *bool) *AttachmentCreate {
return ac
}
// SetTitle sets the "title" field.
func (ac *AttachmentCreate) SetTitle(s string) *AttachmentCreate {
ac.mutation.SetTitle(s)
return ac
}
// SetNillableTitle sets the "title" field if the given value is not nil.
func (ac *AttachmentCreate) SetNillableTitle(s *string) *AttachmentCreate {
if s != nil {
ac.SetTitle(*s)
}
return ac
}
// SetPath sets the "path" field.
func (ac *AttachmentCreate) SetPath(s string) *AttachmentCreate {
ac.mutation.SetPath(s)
return ac
}
// SetNillablePath sets the "path" field if the given value is not nil.
func (ac *AttachmentCreate) SetNillablePath(s *string) *AttachmentCreate {
if s != nil {
ac.SetPath(*s)
}
return ac
}
// SetMimeType sets the "mime_type" field.
func (ac *AttachmentCreate) SetMimeType(s string) *AttachmentCreate {
ac.mutation.SetMimeType(s)
return ac
}
// SetNillableMimeType sets the "mime_type" field if the given value is not nil.
func (ac *AttachmentCreate) SetNillableMimeType(s *string) *AttachmentCreate {
if s != nil {
ac.SetMimeType(*s)
}
return ac
}
// SetID sets the "id" field.
func (ac *AttachmentCreate) SetID(u uuid.UUID) *AttachmentCreate {
ac.mutation.SetID(u)
@@ -99,20 +140,36 @@ func (ac *AttachmentCreate) SetItemID(id uuid.UUID) *AttachmentCreate {
return ac
}
// SetNillableItemID sets the "item" edge to the Item entity by ID if the given value is not nil.
func (ac *AttachmentCreate) SetNillableItemID(id *uuid.UUID) *AttachmentCreate {
if id != nil {
ac = ac.SetItemID(*id)
}
return ac
}
// SetItem sets the "item" edge to the Item entity.
func (ac *AttachmentCreate) SetItem(i *Item) *AttachmentCreate {
return ac.SetItemID(i.ID)
}
// SetDocumentID sets the "document" edge to the Document entity by ID.
func (ac *AttachmentCreate) SetDocumentID(id uuid.UUID) *AttachmentCreate {
ac.mutation.SetDocumentID(id)
// SetThumbnailID sets the "thumbnail" edge to the Attachment entity by ID.
func (ac *AttachmentCreate) SetThumbnailID(id uuid.UUID) *AttachmentCreate {
ac.mutation.SetThumbnailID(id)
return ac
}
// SetDocument sets the "document" edge to the Document entity.
func (ac *AttachmentCreate) SetDocument(d *Document) *AttachmentCreate {
return ac.SetDocumentID(d.ID)
// SetNillableThumbnailID sets the "thumbnail" edge to the Attachment entity by ID if the given value is not nil.
func (ac *AttachmentCreate) SetNillableThumbnailID(id *uuid.UUID) *AttachmentCreate {
if id != nil {
ac = ac.SetThumbnailID(*id)
}
return ac
}
// SetThumbnail sets the "thumbnail" edge to the Attachment entity.
func (ac *AttachmentCreate) SetThumbnail(a *Attachment) *AttachmentCreate {
return ac.SetThumbnailID(a.ID)
}
// Mutation returns the AttachmentMutation object of the builder.
@@ -166,6 +223,18 @@ func (ac *AttachmentCreate) defaults() {
v := attachment.DefaultPrimary
ac.mutation.SetPrimary(v)
}
if _, ok := ac.mutation.Title(); !ok {
v := attachment.DefaultTitle
ac.mutation.SetTitle(v)
}
if _, ok := ac.mutation.Path(); !ok {
v := attachment.DefaultPath
ac.mutation.SetPath(v)
}
if _, ok := ac.mutation.MimeType(); !ok {
v := attachment.DefaultMimeType
ac.mutation.SetMimeType(v)
}
if _, ok := ac.mutation.ID(); !ok {
v := attachment.DefaultID()
ac.mutation.SetID(v)
@@ -191,11 +260,14 @@ func (ac *AttachmentCreate) check() error {
if _, ok := ac.mutation.Primary(); !ok {
return &ValidationError{Name: "primary", err: errors.New(`ent: missing required field "Attachment.primary"`)}
}
if len(ac.mutation.ItemIDs()) == 0 {
return &ValidationError{Name: "item", err: errors.New(`ent: missing required edge "Attachment.item"`)}
if _, ok := ac.mutation.Title(); !ok {
return &ValidationError{Name: "title", err: errors.New(`ent: missing required field "Attachment.title"`)}
}
if len(ac.mutation.DocumentIDs()) == 0 {
return &ValidationError{Name: "document", err: errors.New(`ent: missing required edge "Attachment.document"`)}
if _, ok := ac.mutation.Path(); !ok {
return &ValidationError{Name: "path", err: errors.New(`ent: missing required field "Attachment.path"`)}
}
if _, ok := ac.mutation.MimeType(); !ok {
return &ValidationError{Name: "mime_type", err: errors.New(`ent: missing required field "Attachment.mime_type"`)}
}
return nil
}
@@ -248,6 +320,18 @@ func (ac *AttachmentCreate) createSpec() (*Attachment, *sqlgraph.CreateSpec) {
_spec.SetField(attachment.FieldPrimary, field.TypeBool, value)
_node.Primary = value
}
if value, ok := ac.mutation.Title(); ok {
_spec.SetField(attachment.FieldTitle, field.TypeString, value)
_node.Title = value
}
if value, ok := ac.mutation.Path(); ok {
_spec.SetField(attachment.FieldPath, field.TypeString, value)
_node.Path = value
}
if value, ok := ac.mutation.MimeType(); ok {
_spec.SetField(attachment.FieldMimeType, field.TypeString, value)
_node.MimeType = value
}
if nodes := ac.mutation.ItemIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@@ -265,21 +349,21 @@ func (ac *AttachmentCreate) createSpec() (*Attachment, *sqlgraph.CreateSpec) {
_node.item_attachments = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := ac.mutation.DocumentIDs(); len(nodes) > 0 {
if nodes := ac.mutation.ThumbnailIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: attachment.DocumentTable,
Columns: []string{attachment.DocumentColumn},
Bidi: false,
Rel: sqlgraph.O2O,
Inverse: false,
Table: attachment.ThumbnailTable,
Columns: []string{attachment.ThumbnailColumn},
Bidi: true,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.document_attachments = &nodes[0]
_node.attachment_thumbnail = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec

View File

@@ -13,7 +13,6 @@ import (
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/predicate"
)
@@ -21,13 +20,13 @@ import (
// AttachmentQuery is the builder for querying Attachment entities.
type AttachmentQuery struct {
config
ctx *QueryContext
order []attachment.OrderOption
inters []Interceptor
predicates []predicate.Attachment
withItem *ItemQuery
withDocument *DocumentQuery
withFKs bool
ctx *QueryContext
order []attachment.OrderOption
inters []Interceptor
predicates []predicate.Attachment
withItem *ItemQuery
withThumbnail *AttachmentQuery
withFKs bool
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@@ -86,9 +85,9 @@ func (aq *AttachmentQuery) QueryItem() *ItemQuery {
return query
}
// QueryDocument chains the current query on the "document" edge.
func (aq *AttachmentQuery) QueryDocument() *DocumentQuery {
query := (&DocumentClient{config: aq.config}).Query()
// QueryThumbnail chains the current query on the "thumbnail" edge.
func (aq *AttachmentQuery) QueryThumbnail() *AttachmentQuery {
query := (&AttachmentClient{config: aq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := aq.prepareQuery(ctx); err != nil {
return nil, err
@@ -99,8 +98,8 @@ func (aq *AttachmentQuery) QueryDocument() *DocumentQuery {
}
step := sqlgraph.NewStep(
sqlgraph.From(attachment.Table, attachment.FieldID, selector),
sqlgraph.To(document.Table, document.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, attachment.DocumentTable, attachment.DocumentColumn),
sqlgraph.To(attachment.Table, attachment.FieldID),
sqlgraph.Edge(sqlgraph.O2O, false, attachment.ThumbnailTable, attachment.ThumbnailColumn),
)
fromU = sqlgraph.SetNeighbors(aq.driver.Dialect(), step)
return fromU, nil
@@ -295,13 +294,13 @@ func (aq *AttachmentQuery) Clone() *AttachmentQuery {
return nil
}
return &AttachmentQuery{
config: aq.config,
ctx: aq.ctx.Clone(),
order: append([]attachment.OrderOption{}, aq.order...),
inters: append([]Interceptor{}, aq.inters...),
predicates: append([]predicate.Attachment{}, aq.predicates...),
withItem: aq.withItem.Clone(),
withDocument: aq.withDocument.Clone(),
config: aq.config,
ctx: aq.ctx.Clone(),
order: append([]attachment.OrderOption{}, aq.order...),
inters: append([]Interceptor{}, aq.inters...),
predicates: append([]predicate.Attachment{}, aq.predicates...),
withItem: aq.withItem.Clone(),
withThumbnail: aq.withThumbnail.Clone(),
// clone intermediate query.
sql: aq.sql.Clone(),
path: aq.path,
@@ -319,14 +318,14 @@ func (aq *AttachmentQuery) WithItem(opts ...func(*ItemQuery)) *AttachmentQuery {
return aq
}
// WithDocument tells the query-builder to eager-load the nodes that are connected to
// the "document" edge. The optional arguments are used to configure the query builder of the edge.
func (aq *AttachmentQuery) WithDocument(opts ...func(*DocumentQuery)) *AttachmentQuery {
query := (&DocumentClient{config: aq.config}).Query()
// WithThumbnail tells the query-builder to eager-load the nodes that are connected to
// the "thumbnail" edge. The optional arguments are used to configure the query builder of the edge.
func (aq *AttachmentQuery) WithThumbnail(opts ...func(*AttachmentQuery)) *AttachmentQuery {
query := (&AttachmentClient{config: aq.config}).Query()
for _, opt := range opts {
opt(query)
}
aq.withDocument = query
aq.withThumbnail = query
return aq
}
@@ -411,10 +410,10 @@ func (aq *AttachmentQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*A
_spec = aq.querySpec()
loadedTypes = [2]bool{
aq.withItem != nil,
aq.withDocument != nil,
aq.withThumbnail != nil,
}
)
if aq.withItem != nil || aq.withDocument != nil {
if aq.withItem != nil || aq.withThumbnail != nil {
withFKs = true
}
if withFKs {
@@ -444,9 +443,9 @@ func (aq *AttachmentQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*A
return nil, err
}
}
if query := aq.withDocument; query != nil {
if err := aq.loadDocument(ctx, query, nodes, nil,
func(n *Attachment, e *Document) { n.Edges.Document = e }); err != nil {
if query := aq.withThumbnail; query != nil {
if err := aq.loadThumbnail(ctx, query, nodes, nil,
func(n *Attachment, e *Attachment) { n.Edges.Thumbnail = e }); err != nil {
return nil, err
}
}
@@ -485,14 +484,14 @@ func (aq *AttachmentQuery) loadItem(ctx context.Context, query *ItemQuery, nodes
}
return nil
}
func (aq *AttachmentQuery) loadDocument(ctx context.Context, query *DocumentQuery, nodes []*Attachment, init func(*Attachment), assign func(*Attachment, *Document)) error {
func (aq *AttachmentQuery) loadThumbnail(ctx context.Context, query *AttachmentQuery, nodes []*Attachment, init func(*Attachment), assign func(*Attachment, *Attachment)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Attachment)
for i := range nodes {
if nodes[i].document_attachments == nil {
if nodes[i].attachment_thumbnail == nil {
continue
}
fk := *nodes[i].document_attachments
fk := *nodes[i].attachment_thumbnail
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
@@ -501,7 +500,7 @@ func (aq *AttachmentQuery) loadDocument(ctx context.Context, query *DocumentQuer
if len(ids) == 0 {
return nil
}
query.Where(document.IDIn(ids...))
query.Where(attachment.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
@@ -509,7 +508,7 @@ func (aq *AttachmentQuery) loadDocument(ctx context.Context, query *DocumentQuer
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "document_attachments" returned %v`, n.ID)
return fmt.Errorf(`unexpected foreign-key "attachment_thumbnail" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)

View File

@@ -13,7 +13,6 @@ import (
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/predicate"
)
@@ -65,26 +64,84 @@ func (au *AttachmentUpdate) SetNillablePrimary(b *bool) *AttachmentUpdate {
return au
}
// SetTitle sets the "title" field.
func (au *AttachmentUpdate) SetTitle(s string) *AttachmentUpdate {
au.mutation.SetTitle(s)
return au
}
// SetNillableTitle sets the "title" field if the given value is not nil.
func (au *AttachmentUpdate) SetNillableTitle(s *string) *AttachmentUpdate {
if s != nil {
au.SetTitle(*s)
}
return au
}
// SetPath sets the "path" field.
func (au *AttachmentUpdate) SetPath(s string) *AttachmentUpdate {
au.mutation.SetPath(s)
return au
}
// SetNillablePath sets the "path" field if the given value is not nil.
func (au *AttachmentUpdate) SetNillablePath(s *string) *AttachmentUpdate {
if s != nil {
au.SetPath(*s)
}
return au
}
// SetMimeType sets the "mime_type" field.
func (au *AttachmentUpdate) SetMimeType(s string) *AttachmentUpdate {
au.mutation.SetMimeType(s)
return au
}
// SetNillableMimeType sets the "mime_type" field if the given value is not nil.
func (au *AttachmentUpdate) SetNillableMimeType(s *string) *AttachmentUpdate {
if s != nil {
au.SetMimeType(*s)
}
return au
}
// SetItemID sets the "item" edge to the Item entity by ID.
func (au *AttachmentUpdate) SetItemID(id uuid.UUID) *AttachmentUpdate {
au.mutation.SetItemID(id)
return au
}
// SetNillableItemID sets the "item" edge to the Item entity by ID if the given value is not nil.
func (au *AttachmentUpdate) SetNillableItemID(id *uuid.UUID) *AttachmentUpdate {
if id != nil {
au = au.SetItemID(*id)
}
return au
}
// SetItem sets the "item" edge to the Item entity.
func (au *AttachmentUpdate) SetItem(i *Item) *AttachmentUpdate {
return au.SetItemID(i.ID)
}
// SetDocumentID sets the "document" edge to the Document entity by ID.
func (au *AttachmentUpdate) SetDocumentID(id uuid.UUID) *AttachmentUpdate {
au.mutation.SetDocumentID(id)
// SetThumbnailID sets the "thumbnail" edge to the Attachment entity by ID.
func (au *AttachmentUpdate) SetThumbnailID(id uuid.UUID) *AttachmentUpdate {
au.mutation.SetThumbnailID(id)
return au
}
// SetDocument sets the "document" edge to the Document entity.
func (au *AttachmentUpdate) SetDocument(d *Document) *AttachmentUpdate {
return au.SetDocumentID(d.ID)
// SetNillableThumbnailID sets the "thumbnail" edge to the Attachment entity by ID if the given value is not nil.
func (au *AttachmentUpdate) SetNillableThumbnailID(id *uuid.UUID) *AttachmentUpdate {
if id != nil {
au = au.SetThumbnailID(*id)
}
return au
}
// SetThumbnail sets the "thumbnail" edge to the Attachment entity.
func (au *AttachmentUpdate) SetThumbnail(a *Attachment) *AttachmentUpdate {
return au.SetThumbnailID(a.ID)
}
// Mutation returns the AttachmentMutation object of the builder.
@@ -98,9 +155,9 @@ func (au *AttachmentUpdate) ClearItem() *AttachmentUpdate {
return au
}
// ClearDocument clears the "document" edge to the Document entity.
func (au *AttachmentUpdate) ClearDocument() *AttachmentUpdate {
au.mutation.ClearDocument()
// ClearThumbnail clears the "thumbnail" edge to the Attachment entity.
func (au *AttachmentUpdate) ClearThumbnail() *AttachmentUpdate {
au.mutation.ClearThumbnail()
return au
}
@@ -147,12 +204,6 @@ func (au *AttachmentUpdate) check() error {
return &ValidationError{Name: "type", err: fmt.Errorf(`ent: validator failed for field "Attachment.type": %w`, err)}
}
}
if au.mutation.ItemCleared() && len(au.mutation.ItemIDs()) > 0 {
return errors.New(`ent: clearing a required unique edge "Attachment.item"`)
}
if au.mutation.DocumentCleared() && len(au.mutation.DocumentIDs()) > 0 {
return errors.New(`ent: clearing a required unique edge "Attachment.document"`)
}
return nil
}
@@ -177,6 +228,15 @@ func (au *AttachmentUpdate) sqlSave(ctx context.Context) (n int, err error) {
if value, ok := au.mutation.Primary(); ok {
_spec.SetField(attachment.FieldPrimary, field.TypeBool, value)
}
if value, ok := au.mutation.Title(); ok {
_spec.SetField(attachment.FieldTitle, field.TypeString, value)
}
if value, ok := au.mutation.Path(); ok {
_spec.SetField(attachment.FieldPath, field.TypeString, value)
}
if value, ok := au.mutation.MimeType(); ok {
_spec.SetField(attachment.FieldMimeType, field.TypeString, value)
}
if au.mutation.ItemCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@@ -206,28 +266,28 @@ func (au *AttachmentUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if au.mutation.DocumentCleared() {
if au.mutation.ThumbnailCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: attachment.DocumentTable,
Columns: []string{attachment.DocumentColumn},
Bidi: false,
Rel: sqlgraph.O2O,
Inverse: false,
Table: attachment.ThumbnailTable,
Columns: []string{attachment.ThumbnailColumn},
Bidi: true,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := au.mutation.DocumentIDs(); len(nodes) > 0 {
if nodes := au.mutation.ThumbnailIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: attachment.DocumentTable,
Columns: []string{attachment.DocumentColumn},
Bidi: false,
Rel: sqlgraph.O2O,
Inverse: false,
Table: attachment.ThumbnailTable,
Columns: []string{attachment.ThumbnailColumn},
Bidi: true,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
@@ -289,26 +349,84 @@ func (auo *AttachmentUpdateOne) SetNillablePrimary(b *bool) *AttachmentUpdateOne
return auo
}
// SetTitle sets the "title" field.
func (auo *AttachmentUpdateOne) SetTitle(s string) *AttachmentUpdateOne {
auo.mutation.SetTitle(s)
return auo
}
// SetNillableTitle sets the "title" field if the given value is not nil.
func (auo *AttachmentUpdateOne) SetNillableTitle(s *string) *AttachmentUpdateOne {
if s != nil {
auo.SetTitle(*s)
}
return auo
}
// SetPath sets the "path" field.
func (auo *AttachmentUpdateOne) SetPath(s string) *AttachmentUpdateOne {
auo.mutation.SetPath(s)
return auo
}
// SetNillablePath sets the "path" field if the given value is not nil.
func (auo *AttachmentUpdateOne) SetNillablePath(s *string) *AttachmentUpdateOne {
if s != nil {
auo.SetPath(*s)
}
return auo
}
// SetMimeType sets the "mime_type" field.
func (auo *AttachmentUpdateOne) SetMimeType(s string) *AttachmentUpdateOne {
auo.mutation.SetMimeType(s)
return auo
}
// SetNillableMimeType sets the "mime_type" field if the given value is not nil.
func (auo *AttachmentUpdateOne) SetNillableMimeType(s *string) *AttachmentUpdateOne {
if s != nil {
auo.SetMimeType(*s)
}
return auo
}
// SetItemID sets the "item" edge to the Item entity by ID.
func (auo *AttachmentUpdateOne) SetItemID(id uuid.UUID) *AttachmentUpdateOne {
auo.mutation.SetItemID(id)
return auo
}
// SetNillableItemID sets the "item" edge to the Item entity by ID if the given value is not nil.
func (auo *AttachmentUpdateOne) SetNillableItemID(id *uuid.UUID) *AttachmentUpdateOne {
if id != nil {
auo = auo.SetItemID(*id)
}
return auo
}
// SetItem sets the "item" edge to the Item entity.
func (auo *AttachmentUpdateOne) SetItem(i *Item) *AttachmentUpdateOne {
return auo.SetItemID(i.ID)
}
// SetDocumentID sets the "document" edge to the Document entity by ID.
func (auo *AttachmentUpdateOne) SetDocumentID(id uuid.UUID) *AttachmentUpdateOne {
auo.mutation.SetDocumentID(id)
// SetThumbnailID sets the "thumbnail" edge to the Attachment entity by ID.
func (auo *AttachmentUpdateOne) SetThumbnailID(id uuid.UUID) *AttachmentUpdateOne {
auo.mutation.SetThumbnailID(id)
return auo
}
// SetDocument sets the "document" edge to the Document entity.
func (auo *AttachmentUpdateOne) SetDocument(d *Document) *AttachmentUpdateOne {
return auo.SetDocumentID(d.ID)
// SetNillableThumbnailID sets the "thumbnail" edge to the Attachment entity by ID if the given value is not nil.
func (auo *AttachmentUpdateOne) SetNillableThumbnailID(id *uuid.UUID) *AttachmentUpdateOne {
if id != nil {
auo = auo.SetThumbnailID(*id)
}
return auo
}
// SetThumbnail sets the "thumbnail" edge to the Attachment entity.
func (auo *AttachmentUpdateOne) SetThumbnail(a *Attachment) *AttachmentUpdateOne {
return auo.SetThumbnailID(a.ID)
}
// Mutation returns the AttachmentMutation object of the builder.
@@ -322,9 +440,9 @@ func (auo *AttachmentUpdateOne) ClearItem() *AttachmentUpdateOne {
return auo
}
// ClearDocument clears the "document" edge to the Document entity.
func (auo *AttachmentUpdateOne) ClearDocument() *AttachmentUpdateOne {
auo.mutation.ClearDocument()
// ClearThumbnail clears the "thumbnail" edge to the Attachment entity.
func (auo *AttachmentUpdateOne) ClearThumbnail() *AttachmentUpdateOne {
auo.mutation.ClearThumbnail()
return auo
}
@@ -384,12 +502,6 @@ func (auo *AttachmentUpdateOne) check() error {
return &ValidationError{Name: "type", err: fmt.Errorf(`ent: validator failed for field "Attachment.type": %w`, err)}
}
}
if auo.mutation.ItemCleared() && len(auo.mutation.ItemIDs()) > 0 {
return errors.New(`ent: clearing a required unique edge "Attachment.item"`)
}
if auo.mutation.DocumentCleared() && len(auo.mutation.DocumentIDs()) > 0 {
return errors.New(`ent: clearing a required unique edge "Attachment.document"`)
}
return nil
}
@@ -431,6 +543,15 @@ func (auo *AttachmentUpdateOne) sqlSave(ctx context.Context) (_node *Attachment,
if value, ok := auo.mutation.Primary(); ok {
_spec.SetField(attachment.FieldPrimary, field.TypeBool, value)
}
if value, ok := auo.mutation.Title(); ok {
_spec.SetField(attachment.FieldTitle, field.TypeString, value)
}
if value, ok := auo.mutation.Path(); ok {
_spec.SetField(attachment.FieldPath, field.TypeString, value)
}
if value, ok := auo.mutation.MimeType(); ok {
_spec.SetField(attachment.FieldMimeType, field.TypeString, value)
}
if auo.mutation.ItemCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
@@ -460,28 +581,28 @@ func (auo *AttachmentUpdateOne) sqlSave(ctx context.Context) (_node *Attachment,
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if auo.mutation.DocumentCleared() {
if auo.mutation.ThumbnailCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: attachment.DocumentTable,
Columns: []string{attachment.DocumentColumn},
Bidi: false,
Rel: sqlgraph.O2O,
Inverse: false,
Table: attachment.ThumbnailTable,
Columns: []string{attachment.ThumbnailColumn},
Bidi: true,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := auo.mutation.DocumentIDs(); len(nodes) > 0 {
if nodes := auo.mutation.ThumbnailIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: attachment.DocumentTable,
Columns: []string{attachment.DocumentColumn},
Bidi: false,
Rel: sqlgraph.O2O,
Inverse: false,
Table: attachment.ThumbnailTable,
Columns: []string{attachment.ThumbnailColumn},
Bidi: true,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {

View File

@@ -19,7 +19,6 @@ import (
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/authroles"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/authtokens"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/group"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/groupinvitationtoken"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
@@ -42,8 +41,6 @@ type Client struct {
AuthRoles *AuthRolesClient
// AuthTokens is the client for interacting with the AuthTokens builders.
AuthTokens *AuthTokensClient
// Document is the client for interacting with the Document builders.
Document *DocumentClient
// Group is the client for interacting with the Group builders.
Group *GroupClient
// GroupInvitationToken is the client for interacting with the GroupInvitationToken builders.
@@ -76,7 +73,6 @@ func (c *Client) init() {
c.Attachment = NewAttachmentClient(c.config)
c.AuthRoles = NewAuthRolesClient(c.config)
c.AuthTokens = NewAuthTokensClient(c.config)
c.Document = NewDocumentClient(c.config)
c.Group = NewGroupClient(c.config)
c.GroupInvitationToken = NewGroupInvitationTokenClient(c.config)
c.Item = NewItemClient(c.config)
@@ -181,7 +177,6 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
Attachment: NewAttachmentClient(cfg),
AuthRoles: NewAuthRolesClient(cfg),
AuthTokens: NewAuthTokensClient(cfg),
Document: NewDocumentClient(cfg),
Group: NewGroupClient(cfg),
GroupInvitationToken: NewGroupInvitationTokenClient(cfg),
Item: NewItemClient(cfg),
@@ -213,7 +208,6 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
Attachment: NewAttachmentClient(cfg),
AuthRoles: NewAuthRolesClient(cfg),
AuthTokens: NewAuthTokensClient(cfg),
Document: NewDocumentClient(cfg),
Group: NewGroupClient(cfg),
GroupInvitationToken: NewGroupInvitationTokenClient(cfg),
Item: NewItemClient(cfg),
@@ -252,9 +246,9 @@ func (c *Client) Close() error {
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
func (c *Client) Use(hooks ...Hook) {
for _, n := range []interface{ Use(...Hook) }{
c.Attachment, c.AuthRoles, c.AuthTokens, c.Document, c.Group,
c.GroupInvitationToken, c.Item, c.ItemField, c.Label, c.Location,
c.MaintenanceEntry, c.Notifier, c.User,
c.Attachment, c.AuthRoles, c.AuthTokens, c.Group, c.GroupInvitationToken,
c.Item, c.ItemField, c.Label, c.Location, c.MaintenanceEntry, c.Notifier,
c.User,
} {
n.Use(hooks...)
}
@@ -264,9 +258,9 @@ func (c *Client) Use(hooks ...Hook) {
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
func (c *Client) Intercept(interceptors ...Interceptor) {
for _, n := range []interface{ Intercept(...Interceptor) }{
c.Attachment, c.AuthRoles, c.AuthTokens, c.Document, c.Group,
c.GroupInvitationToken, c.Item, c.ItemField, c.Label, c.Location,
c.MaintenanceEntry, c.Notifier, c.User,
c.Attachment, c.AuthRoles, c.AuthTokens, c.Group, c.GroupInvitationToken,
c.Item, c.ItemField, c.Label, c.Location, c.MaintenanceEntry, c.Notifier,
c.User,
} {
n.Intercept(interceptors...)
}
@@ -281,8 +275,6 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
return c.AuthRoles.mutate(ctx, m)
case *AuthTokensMutation:
return c.AuthTokens.mutate(ctx, m)
case *DocumentMutation:
return c.Document.mutate(ctx, m)
case *GroupMutation:
return c.Group.mutate(ctx, m)
case *GroupInvitationTokenMutation:
@@ -430,15 +422,15 @@ func (c *AttachmentClient) QueryItem(a *Attachment) *ItemQuery {
return query
}
// QueryDocument queries the document edge of a Attachment.
func (c *AttachmentClient) QueryDocument(a *Attachment) *DocumentQuery {
query := (&DocumentClient{config: c.config}).Query()
// QueryThumbnail queries the thumbnail edge of a Attachment.
func (c *AttachmentClient) QueryThumbnail(a *Attachment) *AttachmentQuery {
query := (&AttachmentClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := a.ID
step := sqlgraph.NewStep(
sqlgraph.From(attachment.Table, attachment.FieldID, id),
sqlgraph.To(document.Table, document.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, attachment.DocumentTable, attachment.DocumentColumn),
sqlgraph.To(attachment.Table, attachment.FieldID),
sqlgraph.Edge(sqlgraph.O2O, false, attachment.ThumbnailTable, attachment.ThumbnailColumn),
)
fromV = sqlgraph.Neighbors(a.driver.Dialect(), step)
return fromV, nil
@@ -785,171 +777,6 @@ func (c *AuthTokensClient) mutate(ctx context.Context, m *AuthTokensMutation) (V
}
}
// DocumentClient is a client for the Document schema.
type DocumentClient struct {
config
}
// NewDocumentClient returns a client for the Document from the given config.
func NewDocumentClient(c config) *DocumentClient {
return &DocumentClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `document.Hooks(f(g(h())))`.
func (c *DocumentClient) Use(hooks ...Hook) {
c.hooks.Document = append(c.hooks.Document, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `document.Intercept(f(g(h())))`.
func (c *DocumentClient) Intercept(interceptors ...Interceptor) {
c.inters.Document = append(c.inters.Document, interceptors...)
}
// Create returns a builder for creating a Document entity.
func (c *DocumentClient) Create() *DocumentCreate {
mutation := newDocumentMutation(c.config, OpCreate)
return &DocumentCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of Document entities.
func (c *DocumentClient) CreateBulk(builders ...*DocumentCreate) *DocumentCreateBulk {
return &DocumentCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *DocumentClient) MapCreateBulk(slice any, setFunc func(*DocumentCreate, int)) *DocumentCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &DocumentCreateBulk{err: fmt.Errorf("calling to DocumentClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*DocumentCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &DocumentCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for Document.
func (c *DocumentClient) Update() *DocumentUpdate {
mutation := newDocumentMutation(c.config, OpUpdate)
return &DocumentUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *DocumentClient) UpdateOne(d *Document) *DocumentUpdateOne {
mutation := newDocumentMutation(c.config, OpUpdateOne, withDocument(d))
return &DocumentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *DocumentClient) UpdateOneID(id uuid.UUID) *DocumentUpdateOne {
mutation := newDocumentMutation(c.config, OpUpdateOne, withDocumentID(id))
return &DocumentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for Document.
func (c *DocumentClient) Delete() *DocumentDelete {
mutation := newDocumentMutation(c.config, OpDelete)
return &DocumentDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *DocumentClient) DeleteOne(d *Document) *DocumentDeleteOne {
return c.DeleteOneID(d.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *DocumentClient) DeleteOneID(id uuid.UUID) *DocumentDeleteOne {
builder := c.Delete().Where(document.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &DocumentDeleteOne{builder}
}
// Query returns a query builder for Document.
func (c *DocumentClient) Query() *DocumentQuery {
return &DocumentQuery{
config: c.config,
ctx: &QueryContext{Type: TypeDocument},
inters: c.Interceptors(),
}
}
// Get returns a Document entity by its id.
func (c *DocumentClient) Get(ctx context.Context, id uuid.UUID) (*Document, error) {
return c.Query().Where(document.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *DocumentClient) GetX(ctx context.Context, id uuid.UUID) *Document {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryGroup queries the group edge of a Document.
func (c *DocumentClient) QueryGroup(d *Document) *GroupQuery {
query := (&GroupClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := d.ID
step := sqlgraph.NewStep(
sqlgraph.From(document.Table, document.FieldID, id),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, document.GroupTable, document.GroupColumn),
)
fromV = sqlgraph.Neighbors(d.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryAttachments queries the attachments edge of a Document.
func (c *DocumentClient) QueryAttachments(d *Document) *AttachmentQuery {
query := (&AttachmentClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := d.ID
step := sqlgraph.NewStep(
sqlgraph.From(document.Table, document.FieldID, id),
sqlgraph.To(attachment.Table, attachment.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, document.AttachmentsTable, document.AttachmentsColumn),
)
fromV = sqlgraph.Neighbors(d.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *DocumentClient) Hooks() []Hook {
return c.hooks.Document
}
// Interceptors returns the client interceptors.
func (c *DocumentClient) Interceptors() []Interceptor {
return c.inters.Document
}
func (c *DocumentClient) mutate(ctx context.Context, m *DocumentMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&DocumentCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&DocumentUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&DocumentUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&DocumentDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown Document mutation op: %q", m.Op())
}
}
// GroupClient is a client for the Group schema.
type GroupClient struct {
config
@@ -1122,22 +949,6 @@ func (c *GroupClient) QueryLabels(gr *Group) *LabelQuery {
return query
}
// QueryDocuments queries the documents edge of a Group.
func (c *GroupClient) QueryDocuments(gr *Group) *DocumentQuery {
query := (&DocumentClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := gr.ID
step := sqlgraph.NewStep(
sqlgraph.From(group.Table, group.FieldID, id),
sqlgraph.To(document.Table, document.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, group.DocumentsTable, group.DocumentsColumn),
)
fromV = sqlgraph.Neighbors(gr.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryInvitationTokens queries the invitation_tokens edge of a Group.
func (c *GroupClient) QueryInvitationTokens(gr *Group) *GroupInvitationTokenQuery {
query := (&GroupInvitationTokenClient{config: c.config}).Query()
@@ -2614,11 +2425,11 @@ func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error)
// hooks and interceptors per client, for fast access.
type (
hooks struct {
Attachment, AuthRoles, AuthTokens, Document, Group, GroupInvitationToken, Item,
ItemField, Label, Location, MaintenanceEntry, Notifier, User []ent.Hook
Attachment, AuthRoles, AuthTokens, Group, GroupInvitationToken, Item, ItemField,
Label, Location, MaintenanceEntry, Notifier, User []ent.Hook
}
inters struct {
Attachment, AuthRoles, AuthTokens, Document, Group, GroupInvitationToken, Item,
ItemField, Label, Location, MaintenanceEntry, Notifier, User []ent.Interceptor
Attachment, AuthRoles, AuthTokens, Group, GroupInvitationToken, Item, ItemField,
Label, Location, MaintenanceEntry, Notifier, User []ent.Interceptor
}
)

View File

@@ -1,195 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/group"
)
// Document is the model entity for the Document schema.
type Document struct {
config `json:"-"`
// ID of the ent.
ID uuid.UUID `json:"id,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt holds the value of the "updated_at" field.
UpdatedAt time.Time `json:"updated_at,omitempty"`
// Title holds the value of the "title" field.
Title string `json:"title,omitempty"`
// Path holds the value of the "path" field.
Path string `json:"path,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the DocumentQuery when eager-loading is set.
Edges DocumentEdges `json:"edges"`
group_documents *uuid.UUID
selectValues sql.SelectValues
}
// DocumentEdges holds the relations/edges for other nodes in the graph.
type DocumentEdges struct {
// Group holds the value of the group edge.
Group *Group `json:"group,omitempty"`
// Attachments holds the value of the attachments edge.
Attachments []*Attachment `json:"attachments,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [2]bool
}
// GroupOrErr returns the Group value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e DocumentEdges) GroupOrErr() (*Group, error) {
if e.Group != nil {
return e.Group, nil
} else if e.loadedTypes[0] {
return nil, &NotFoundError{label: group.Label}
}
return nil, &NotLoadedError{edge: "group"}
}
// AttachmentsOrErr returns the Attachments value or an error if the edge
// was not loaded in eager-loading.
func (e DocumentEdges) AttachmentsOrErr() ([]*Attachment, error) {
if e.loadedTypes[1] {
return e.Attachments, nil
}
return nil, &NotLoadedError{edge: "attachments"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*Document) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case document.FieldTitle, document.FieldPath:
values[i] = new(sql.NullString)
case document.FieldCreatedAt, document.FieldUpdatedAt:
values[i] = new(sql.NullTime)
case document.FieldID:
values[i] = new(uuid.UUID)
case document.ForeignKeys[0]: // group_documents
values[i] = &sql.NullScanner{S: new(uuid.UUID)}
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the Document fields.
func (d *Document) assignValues(columns []string, values []any) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case document.FieldID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field id", values[i])
} else if value != nil {
d.ID = *value
}
case document.FieldCreatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field created_at", values[i])
} else if value.Valid {
d.CreatedAt = value.Time
}
case document.FieldUpdatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
} else if value.Valid {
d.UpdatedAt = value.Time
}
case document.FieldTitle:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field title", values[i])
} else if value.Valid {
d.Title = value.String
}
case document.FieldPath:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field path", values[i])
} else if value.Valid {
d.Path = value.String
}
case document.ForeignKeys[0]:
if value, ok := values[i].(*sql.NullScanner); !ok {
return fmt.Errorf("unexpected type %T for field group_documents", values[i])
} else if value.Valid {
d.group_documents = new(uuid.UUID)
*d.group_documents = *value.S.(*uuid.UUID)
}
default:
d.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the Document.
// This includes values selected through modifiers, order, etc.
func (d *Document) Value(name string) (ent.Value, error) {
return d.selectValues.Get(name)
}
// QueryGroup queries the "group" edge of the Document entity.
func (d *Document) QueryGroup() *GroupQuery {
return NewDocumentClient(d.config).QueryGroup(d)
}
// QueryAttachments queries the "attachments" edge of the Document entity.
func (d *Document) QueryAttachments() *AttachmentQuery {
return NewDocumentClient(d.config).QueryAttachments(d)
}
// Update returns a builder for updating this Document.
// Note that you need to call Document.Unwrap() before calling this method if this Document
// was returned from a transaction, and the transaction was committed or rolled back.
func (d *Document) Update() *DocumentUpdateOne {
return NewDocumentClient(d.config).UpdateOne(d)
}
// Unwrap unwraps the Document entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (d *Document) Unwrap() *Document {
_tx, ok := d.config.driver.(*txDriver)
if !ok {
panic("ent: Document is not a transactional entity")
}
d.config.driver = _tx.drv
return d
}
// String implements the fmt.Stringer.
func (d *Document) String() string {
var builder strings.Builder
builder.WriteString("Document(")
builder.WriteString(fmt.Sprintf("id=%v, ", d.ID))
builder.WriteString("created_at=")
builder.WriteString(d.CreatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("updated_at=")
builder.WriteString(d.UpdatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("title=")
builder.WriteString(d.Title)
builder.WriteString(", ")
builder.WriteString("path=")
builder.WriteString(d.Path)
builder.WriteByte(')')
return builder.String()
}
// Documents is a parsable slice of Document.
type Documents []*Document

View File

@@ -1,154 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package document
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/google/uuid"
)
const (
// Label holds the string label denoting the document type in the database.
Label = "document"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
FieldUpdatedAt = "updated_at"
// FieldTitle holds the string denoting the title field in the database.
FieldTitle = "title"
// FieldPath holds the string denoting the path field in the database.
FieldPath = "path"
// EdgeGroup holds the string denoting the group edge name in mutations.
EdgeGroup = "group"
// EdgeAttachments holds the string denoting the attachments edge name in mutations.
EdgeAttachments = "attachments"
// Table holds the table name of the document in the database.
Table = "documents"
// GroupTable is the table that holds the group relation/edge.
GroupTable = "documents"
// GroupInverseTable is the table name for the Group entity.
// It exists in this package in order to avoid circular dependency with the "group" package.
GroupInverseTable = "groups"
// GroupColumn is the table column denoting the group relation/edge.
GroupColumn = "group_documents"
// AttachmentsTable is the table that holds the attachments relation/edge.
AttachmentsTable = "attachments"
// AttachmentsInverseTable is the table name for the Attachment entity.
// It exists in this package in order to avoid circular dependency with the "attachment" package.
AttachmentsInverseTable = "attachments"
// AttachmentsColumn is the table column denoting the attachments relation/edge.
AttachmentsColumn = "document_attachments"
)
// Columns holds all SQL columns for document fields.
var Columns = []string{
FieldID,
FieldCreatedAt,
FieldUpdatedAt,
FieldTitle,
FieldPath,
}
// ForeignKeys holds the SQL foreign-keys that are owned by the "documents"
// table and are not defined as standalone fields in the schema.
var ForeignKeys = []string{
"group_documents",
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
for i := range ForeignKeys {
if column == ForeignKeys[i] {
return true
}
}
return false
}
var (
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
DefaultUpdatedAt func() time.Time
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
UpdateDefaultUpdatedAt func() time.Time
// TitleValidator is a validator for the "title" field. It is called by the builders before save.
TitleValidator func(string) error
// PathValidator is a validator for the "path" field. It is called by the builders before save.
PathValidator func(string) error
// DefaultID holds the default value on creation for the "id" field.
DefaultID func() uuid.UUID
)
// OrderOption defines the ordering options for the Document queries.
type OrderOption func(*sql.Selector)
// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}
// ByUpdatedAt orders the results by the updated_at field.
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
}
// ByTitle orders the results by the title field.
func ByTitle(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldTitle, opts...).ToFunc()
}
// ByPath orders the results by the path field.
func ByPath(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPath, opts...).ToFunc()
}
// ByGroupField orders the results by group field.
func ByGroupField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newGroupStep(), sql.OrderByField(field, opts...))
}
}
// ByAttachmentsCount orders the results by attachments count.
func ByAttachmentsCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newAttachmentsStep(), opts...)
}
}
// ByAttachments orders the results by attachments terms.
func ByAttachments(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newAttachmentsStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
func newGroupStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(GroupInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
}
func newAttachmentsStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(AttachmentsInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, AttachmentsTable, AttachmentsColumn),
)
}

View File

@@ -1,348 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package document
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id uuid.UUID) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id uuid.UUID) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id uuid.UUID) predicate.Document {
return predicate.Document(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...uuid.UUID) predicate.Document {
return predicate.Document(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...uuid.UUID) predicate.Document {
return predicate.Document(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id uuid.UUID) predicate.Document {
return predicate.Document(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id uuid.UUID) predicate.Document {
return predicate.Document(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id uuid.UUID) predicate.Document {
return predicate.Document(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id uuid.UUID) predicate.Document {
return predicate.Document(sql.FieldLTE(FieldID, id))
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldCreatedAt, v))
}
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
func UpdatedAt(v time.Time) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldUpdatedAt, v))
}
// Title applies equality check predicate on the "title" field. It's identical to TitleEQ.
func Title(v string) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldTitle, v))
}
// Path applies equality check predicate on the "path" field. It's identical to PathEQ.
func Path(v string) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldPath, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.Document {
return predicate.Document(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.Document {
return predicate.Document(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.Document {
return predicate.Document(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.Document {
return predicate.Document(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.Document {
return predicate.Document(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.Document {
return predicate.Document(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.Document {
return predicate.Document(sql.FieldLTE(FieldCreatedAt, v))
}
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
func UpdatedAtEQ(v time.Time) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldUpdatedAt, v))
}
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
func UpdatedAtNEQ(v time.Time) predicate.Document {
return predicate.Document(sql.FieldNEQ(FieldUpdatedAt, v))
}
// UpdatedAtIn applies the In predicate on the "updated_at" field.
func UpdatedAtIn(vs ...time.Time) predicate.Document {
return predicate.Document(sql.FieldIn(FieldUpdatedAt, vs...))
}
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
func UpdatedAtNotIn(vs ...time.Time) predicate.Document {
return predicate.Document(sql.FieldNotIn(FieldUpdatedAt, vs...))
}
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
func UpdatedAtGT(v time.Time) predicate.Document {
return predicate.Document(sql.FieldGT(FieldUpdatedAt, v))
}
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
func UpdatedAtGTE(v time.Time) predicate.Document {
return predicate.Document(sql.FieldGTE(FieldUpdatedAt, v))
}
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
func UpdatedAtLT(v time.Time) predicate.Document {
return predicate.Document(sql.FieldLT(FieldUpdatedAt, v))
}
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
func UpdatedAtLTE(v time.Time) predicate.Document {
return predicate.Document(sql.FieldLTE(FieldUpdatedAt, v))
}
// TitleEQ applies the EQ predicate on the "title" field.
func TitleEQ(v string) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldTitle, v))
}
// TitleNEQ applies the NEQ predicate on the "title" field.
func TitleNEQ(v string) predicate.Document {
return predicate.Document(sql.FieldNEQ(FieldTitle, v))
}
// TitleIn applies the In predicate on the "title" field.
func TitleIn(vs ...string) predicate.Document {
return predicate.Document(sql.FieldIn(FieldTitle, vs...))
}
// TitleNotIn applies the NotIn predicate on the "title" field.
func TitleNotIn(vs ...string) predicate.Document {
return predicate.Document(sql.FieldNotIn(FieldTitle, vs...))
}
// TitleGT applies the GT predicate on the "title" field.
func TitleGT(v string) predicate.Document {
return predicate.Document(sql.FieldGT(FieldTitle, v))
}
// TitleGTE applies the GTE predicate on the "title" field.
func TitleGTE(v string) predicate.Document {
return predicate.Document(sql.FieldGTE(FieldTitle, v))
}
// TitleLT applies the LT predicate on the "title" field.
func TitleLT(v string) predicate.Document {
return predicate.Document(sql.FieldLT(FieldTitle, v))
}
// TitleLTE applies the LTE predicate on the "title" field.
func TitleLTE(v string) predicate.Document {
return predicate.Document(sql.FieldLTE(FieldTitle, v))
}
// TitleContains applies the Contains predicate on the "title" field.
func TitleContains(v string) predicate.Document {
return predicate.Document(sql.FieldContains(FieldTitle, v))
}
// TitleHasPrefix applies the HasPrefix predicate on the "title" field.
func TitleHasPrefix(v string) predicate.Document {
return predicate.Document(sql.FieldHasPrefix(FieldTitle, v))
}
// TitleHasSuffix applies the HasSuffix predicate on the "title" field.
func TitleHasSuffix(v string) predicate.Document {
return predicate.Document(sql.FieldHasSuffix(FieldTitle, v))
}
// TitleEqualFold applies the EqualFold predicate on the "title" field.
func TitleEqualFold(v string) predicate.Document {
return predicate.Document(sql.FieldEqualFold(FieldTitle, v))
}
// TitleContainsFold applies the ContainsFold predicate on the "title" field.
func TitleContainsFold(v string) predicate.Document {
return predicate.Document(sql.FieldContainsFold(FieldTitle, v))
}
// PathEQ applies the EQ predicate on the "path" field.
func PathEQ(v string) predicate.Document {
return predicate.Document(sql.FieldEQ(FieldPath, v))
}
// PathNEQ applies the NEQ predicate on the "path" field.
func PathNEQ(v string) predicate.Document {
return predicate.Document(sql.FieldNEQ(FieldPath, v))
}
// PathIn applies the In predicate on the "path" field.
func PathIn(vs ...string) predicate.Document {
return predicate.Document(sql.FieldIn(FieldPath, vs...))
}
// PathNotIn applies the NotIn predicate on the "path" field.
func PathNotIn(vs ...string) predicate.Document {
return predicate.Document(sql.FieldNotIn(FieldPath, vs...))
}
// PathGT applies the GT predicate on the "path" field.
func PathGT(v string) predicate.Document {
return predicate.Document(sql.FieldGT(FieldPath, v))
}
// PathGTE applies the GTE predicate on the "path" field.
func PathGTE(v string) predicate.Document {
return predicate.Document(sql.FieldGTE(FieldPath, v))
}
// PathLT applies the LT predicate on the "path" field.
func PathLT(v string) predicate.Document {
return predicate.Document(sql.FieldLT(FieldPath, v))
}
// PathLTE applies the LTE predicate on the "path" field.
func PathLTE(v string) predicate.Document {
return predicate.Document(sql.FieldLTE(FieldPath, v))
}
// PathContains applies the Contains predicate on the "path" field.
func PathContains(v string) predicate.Document {
return predicate.Document(sql.FieldContains(FieldPath, v))
}
// PathHasPrefix applies the HasPrefix predicate on the "path" field.
func PathHasPrefix(v string) predicate.Document {
return predicate.Document(sql.FieldHasPrefix(FieldPath, v))
}
// PathHasSuffix applies the HasSuffix predicate on the "path" field.
func PathHasSuffix(v string) predicate.Document {
return predicate.Document(sql.FieldHasSuffix(FieldPath, v))
}
// PathEqualFold applies the EqualFold predicate on the "path" field.
func PathEqualFold(v string) predicate.Document {
return predicate.Document(sql.FieldEqualFold(FieldPath, v))
}
// PathContainsFold applies the ContainsFold predicate on the "path" field.
func PathContainsFold(v string) predicate.Document {
return predicate.Document(sql.FieldContainsFold(FieldPath, v))
}
// HasGroup applies the HasEdge predicate on the "group" edge.
func HasGroup() predicate.Document {
return predicate.Document(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, GroupTable, GroupColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasGroupWith applies the HasEdge predicate on the "group" edge with a given conditions (other predicates).
func HasGroupWith(preds ...predicate.Group) predicate.Document {
return predicate.Document(func(s *sql.Selector) {
step := newGroupStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasAttachments applies the HasEdge predicate on the "attachments" edge.
func HasAttachments() predicate.Document {
return predicate.Document(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, AttachmentsTable, AttachmentsColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasAttachmentsWith applies the HasEdge predicate on the "attachments" edge with a given conditions (other predicates).
func HasAttachmentsWith(preds ...predicate.Attachment) predicate.Document {
return predicate.Document(func(s *sql.Selector) {
step := newAttachmentsStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.Document) predicate.Document {
return predicate.Document(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.Document) predicate.Document {
return predicate.Document(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.Document) predicate.Document {
return predicate.Document(sql.NotPredicates(p))
}

View File

@@ -1,351 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/group"
)
// DocumentCreate is the builder for creating a Document entity.
type DocumentCreate struct {
config
mutation *DocumentMutation
hooks []Hook
}
// SetCreatedAt sets the "created_at" field.
func (dc *DocumentCreate) SetCreatedAt(t time.Time) *DocumentCreate {
dc.mutation.SetCreatedAt(t)
return dc
}
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
func (dc *DocumentCreate) SetNillableCreatedAt(t *time.Time) *DocumentCreate {
if t != nil {
dc.SetCreatedAt(*t)
}
return dc
}
// SetUpdatedAt sets the "updated_at" field.
func (dc *DocumentCreate) SetUpdatedAt(t time.Time) *DocumentCreate {
dc.mutation.SetUpdatedAt(t)
return dc
}
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
func (dc *DocumentCreate) SetNillableUpdatedAt(t *time.Time) *DocumentCreate {
if t != nil {
dc.SetUpdatedAt(*t)
}
return dc
}
// SetTitle sets the "title" field.
func (dc *DocumentCreate) SetTitle(s string) *DocumentCreate {
dc.mutation.SetTitle(s)
return dc
}
// SetPath sets the "path" field.
func (dc *DocumentCreate) SetPath(s string) *DocumentCreate {
dc.mutation.SetPath(s)
return dc
}
// SetID sets the "id" field.
func (dc *DocumentCreate) SetID(u uuid.UUID) *DocumentCreate {
dc.mutation.SetID(u)
return dc
}
// SetNillableID sets the "id" field if the given value is not nil.
func (dc *DocumentCreate) SetNillableID(u *uuid.UUID) *DocumentCreate {
if u != nil {
dc.SetID(*u)
}
return dc
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (dc *DocumentCreate) SetGroupID(id uuid.UUID) *DocumentCreate {
dc.mutation.SetGroupID(id)
return dc
}
// SetGroup sets the "group" edge to the Group entity.
func (dc *DocumentCreate) SetGroup(g *Group) *DocumentCreate {
return dc.SetGroupID(g.ID)
}
// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by IDs.
func (dc *DocumentCreate) AddAttachmentIDs(ids ...uuid.UUID) *DocumentCreate {
dc.mutation.AddAttachmentIDs(ids...)
return dc
}
// AddAttachments adds the "attachments" edges to the Attachment entity.
func (dc *DocumentCreate) AddAttachments(a ...*Attachment) *DocumentCreate {
ids := make([]uuid.UUID, len(a))
for i := range a {
ids[i] = a[i].ID
}
return dc.AddAttachmentIDs(ids...)
}
// Mutation returns the DocumentMutation object of the builder.
func (dc *DocumentCreate) Mutation() *DocumentMutation {
return dc.mutation
}
// Save creates the Document in the database.
func (dc *DocumentCreate) Save(ctx context.Context) (*Document, error) {
dc.defaults()
return withHooks(ctx, dc.sqlSave, dc.mutation, dc.hooks)
}
// SaveX calls Save and panics if Save returns an error.
func (dc *DocumentCreate) SaveX(ctx context.Context) *Document {
v, err := dc.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (dc *DocumentCreate) Exec(ctx context.Context) error {
_, err := dc.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (dc *DocumentCreate) ExecX(ctx context.Context) {
if err := dc.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (dc *DocumentCreate) defaults() {
if _, ok := dc.mutation.CreatedAt(); !ok {
v := document.DefaultCreatedAt()
dc.mutation.SetCreatedAt(v)
}
if _, ok := dc.mutation.UpdatedAt(); !ok {
v := document.DefaultUpdatedAt()
dc.mutation.SetUpdatedAt(v)
}
if _, ok := dc.mutation.ID(); !ok {
v := document.DefaultID()
dc.mutation.SetID(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (dc *DocumentCreate) check() error {
if _, ok := dc.mutation.CreatedAt(); !ok {
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Document.created_at"`)}
}
if _, ok := dc.mutation.UpdatedAt(); !ok {
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Document.updated_at"`)}
}
if _, ok := dc.mutation.Title(); !ok {
return &ValidationError{Name: "title", err: errors.New(`ent: missing required field "Document.title"`)}
}
if v, ok := dc.mutation.Title(); ok {
if err := document.TitleValidator(v); err != nil {
return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "Document.title": %w`, err)}
}
}
if _, ok := dc.mutation.Path(); !ok {
return &ValidationError{Name: "path", err: errors.New(`ent: missing required field "Document.path"`)}
}
if v, ok := dc.mutation.Path(); ok {
if err := document.PathValidator(v); err != nil {
return &ValidationError{Name: "path", err: fmt.Errorf(`ent: validator failed for field "Document.path": %w`, err)}
}
}
if len(dc.mutation.GroupIDs()) == 0 {
return &ValidationError{Name: "group", err: errors.New(`ent: missing required edge "Document.group"`)}
}
return nil
}
func (dc *DocumentCreate) sqlSave(ctx context.Context) (*Document, error) {
if err := dc.check(); err != nil {
return nil, err
}
_node, _spec := dc.createSpec()
if err := sqlgraph.CreateNode(ctx, dc.driver, _spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
if _spec.ID.Value != nil {
if id, ok := _spec.ID.Value.(*uuid.UUID); ok {
_node.ID = *id
} else if err := _node.ID.Scan(_spec.ID.Value); err != nil {
return nil, err
}
}
dc.mutation.id = &_node.ID
dc.mutation.done = true
return _node, nil
}
func (dc *DocumentCreate) createSpec() (*Document, *sqlgraph.CreateSpec) {
var (
_node = &Document{config: dc.config}
_spec = sqlgraph.NewCreateSpec(document.Table, sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID))
)
if id, ok := dc.mutation.ID(); ok {
_node.ID = id
_spec.ID.Value = &id
}
if value, ok := dc.mutation.CreatedAt(); ok {
_spec.SetField(document.FieldCreatedAt, field.TypeTime, value)
_node.CreatedAt = value
}
if value, ok := dc.mutation.UpdatedAt(); ok {
_spec.SetField(document.FieldUpdatedAt, field.TypeTime, value)
_node.UpdatedAt = value
}
if value, ok := dc.mutation.Title(); ok {
_spec.SetField(document.FieldTitle, field.TypeString, value)
_node.Title = value
}
if value, ok := dc.mutation.Path(); ok {
_spec.SetField(document.FieldPath, field.TypeString, value)
_node.Path = value
}
if nodes := dc.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: document.GroupTable,
Columns: []string{document.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.group_documents = &nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := dc.mutation.AttachmentsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: document.AttachmentsTable,
Columns: []string{document.AttachmentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec
}
// DocumentCreateBulk is the builder for creating many Document entities in bulk.
type DocumentCreateBulk struct {
config
err error
builders []*DocumentCreate
}
// Save creates the Document entities in the database.
func (dcb *DocumentCreateBulk) Save(ctx context.Context) ([]*Document, error) {
if dcb.err != nil {
return nil, dcb.err
}
specs := make([]*sqlgraph.CreateSpec, len(dcb.builders))
nodes := make([]*Document, len(dcb.builders))
mutators := make([]Mutator, len(dcb.builders))
for i := range dcb.builders {
func(i int, root context.Context) {
builder := dcb.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*DocumentMutation)
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err := builder.check(); err != nil {
return nil, err
}
builder.mutation = mutation
var err error
nodes[i], specs[i] = builder.createSpec()
if i < len(mutators)-1 {
_, err = mutators[i+1].Mutate(root, dcb.builders[i+1].mutation)
} else {
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
// Invoke the actual operation on the latest mutation in the chain.
if err = sqlgraph.BatchCreate(ctx, dcb.driver, spec); err != nil {
if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
}
}
if err != nil {
return nil, err
}
mutation.id = &nodes[i].ID
mutation.done = true
return nodes[i], nil
})
for i := len(builder.hooks) - 1; i >= 0; i-- {
mut = builder.hooks[i](mut)
}
mutators[i] = mut
}(i, ctx)
}
if len(mutators) > 0 {
if _, err := mutators[0].Mutate(ctx, dcb.builders[0].mutation); err != nil {
return nil, err
}
}
return nodes, nil
}
// SaveX is like Save, but panics if an error occurs.
func (dcb *DocumentCreateBulk) SaveX(ctx context.Context) []*Document {
v, err := dcb.Save(ctx)
if err != nil {
panic(err)
}
return v
}
// Exec executes the query.
func (dcb *DocumentCreateBulk) Exec(ctx context.Context) error {
_, err := dcb.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (dcb *DocumentCreateBulk) ExecX(ctx context.Context) {
if err := dcb.Exec(ctx); err != nil {
panic(err)
}
}

View File

@@ -1,88 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/predicate"
)
// DocumentDelete is the builder for deleting a Document entity.
type DocumentDelete struct {
config
hooks []Hook
mutation *DocumentMutation
}
// Where appends a list predicates to the DocumentDelete builder.
func (dd *DocumentDelete) Where(ps ...predicate.Document) *DocumentDelete {
dd.mutation.Where(ps...)
return dd
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (dd *DocumentDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, dd.sqlExec, dd.mutation, dd.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (dd *DocumentDelete) ExecX(ctx context.Context) int {
n, err := dd.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (dd *DocumentDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(document.Table, sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID))
if ps := dd.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, dd.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
dd.mutation.done = true
return affected, err
}
// DocumentDeleteOne is the builder for deleting a single Document entity.
type DocumentDeleteOne struct {
dd *DocumentDelete
}
// Where appends a list predicates to the DocumentDelete builder.
func (ddo *DocumentDeleteOne) Where(ps ...predicate.Document) *DocumentDeleteOne {
ddo.dd.mutation.Where(ps...)
return ddo
}
// Exec executes the deletion query.
func (ddo *DocumentDeleteOne) Exec(ctx context.Context) error {
n, err := ddo.dd.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{document.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (ddo *DocumentDeleteOne) ExecX(ctx context.Context) {
if err := ddo.Exec(ctx); err != nil {
panic(err)
}
}

View File

@@ -1,691 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"database/sql/driver"
"fmt"
"math"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/group"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/predicate"
)
// DocumentQuery is the builder for querying Document entities.
type DocumentQuery struct {
config
ctx *QueryContext
order []document.OrderOption
inters []Interceptor
predicates []predicate.Document
withGroup *GroupQuery
withAttachments *AttachmentQuery
withFKs bool
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the DocumentQuery builder.
func (dq *DocumentQuery) Where(ps ...predicate.Document) *DocumentQuery {
dq.predicates = append(dq.predicates, ps...)
return dq
}
// Limit the number of records to be returned by this query.
func (dq *DocumentQuery) Limit(limit int) *DocumentQuery {
dq.ctx.Limit = &limit
return dq
}
// Offset to start from.
func (dq *DocumentQuery) Offset(offset int) *DocumentQuery {
dq.ctx.Offset = &offset
return dq
}
// Unique configures the query builder to filter duplicate records on query.
// By default, unique is set to true, and can be disabled using this method.
func (dq *DocumentQuery) Unique(unique bool) *DocumentQuery {
dq.ctx.Unique = &unique
return dq
}
// Order specifies how the records should be ordered.
func (dq *DocumentQuery) Order(o ...document.OrderOption) *DocumentQuery {
dq.order = append(dq.order, o...)
return dq
}
// QueryGroup chains the current query on the "group" edge.
func (dq *DocumentQuery) QueryGroup() *GroupQuery {
query := (&GroupClient{config: dq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := dq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := dq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(document.Table, document.FieldID, selector),
sqlgraph.To(group.Table, group.FieldID),
sqlgraph.Edge(sqlgraph.M2O, true, document.GroupTable, document.GroupColumn),
)
fromU = sqlgraph.SetNeighbors(dq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryAttachments chains the current query on the "attachments" edge.
func (dq *DocumentQuery) QueryAttachments() *AttachmentQuery {
query := (&AttachmentClient{config: dq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := dq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := dq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(document.Table, document.FieldID, selector),
sqlgraph.To(attachment.Table, attachment.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, document.AttachmentsTable, document.AttachmentsColumn),
)
fromU = sqlgraph.SetNeighbors(dq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first Document entity from the query.
// Returns a *NotFoundError when no Document was found.
func (dq *DocumentQuery) First(ctx context.Context) (*Document, error) {
nodes, err := dq.Limit(1).All(setContextOp(ctx, dq.ctx, ent.OpQueryFirst))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{document.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (dq *DocumentQuery) FirstX(ctx context.Context) *Document {
node, err := dq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first Document ID from the query.
// Returns a *NotFoundError when no Document ID was found.
func (dq *DocumentQuery) FirstID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = dq.Limit(1).IDs(setContextOp(ctx, dq.ctx, ent.OpQueryFirstID)); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{document.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (dq *DocumentQuery) FirstIDX(ctx context.Context) uuid.UUID {
id, err := dq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single Document entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one Document entity is found.
// Returns a *NotFoundError when no Document entities are found.
func (dq *DocumentQuery) Only(ctx context.Context) (*Document, error) {
nodes, err := dq.Limit(2).All(setContextOp(ctx, dq.ctx, ent.OpQueryOnly))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{document.Label}
default:
return nil, &NotSingularError{document.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (dq *DocumentQuery) OnlyX(ctx context.Context) *Document {
node, err := dq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only Document ID in the query.
// Returns a *NotSingularError when more than one Document ID is found.
// Returns a *NotFoundError when no entities are found.
func (dq *DocumentQuery) OnlyID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = dq.Limit(2).IDs(setContextOp(ctx, dq.ctx, ent.OpQueryOnlyID)); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{document.Label}
default:
err = &NotSingularError{document.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (dq *DocumentQuery) OnlyIDX(ctx context.Context) uuid.UUID {
id, err := dq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of Documents.
func (dq *DocumentQuery) All(ctx context.Context) ([]*Document, error) {
ctx = setContextOp(ctx, dq.ctx, ent.OpQueryAll)
if err := dq.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*Document, *DocumentQuery]()
return withInterceptors[[]*Document](ctx, dq, qr, dq.inters)
}
// AllX is like All, but panics if an error occurs.
func (dq *DocumentQuery) AllX(ctx context.Context) []*Document {
nodes, err := dq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of Document IDs.
func (dq *DocumentQuery) IDs(ctx context.Context) (ids []uuid.UUID, err error) {
if dq.ctx.Unique == nil && dq.path != nil {
dq.Unique(true)
}
ctx = setContextOp(ctx, dq.ctx, ent.OpQueryIDs)
if err = dq.Select(document.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (dq *DocumentQuery) IDsX(ctx context.Context) []uuid.UUID {
ids, err := dq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (dq *DocumentQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, dq.ctx, ent.OpQueryCount)
if err := dq.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, dq, querierCount[*DocumentQuery](), dq.inters)
}
// CountX is like Count, but panics if an error occurs.
func (dq *DocumentQuery) CountX(ctx context.Context) int {
count, err := dq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (dq *DocumentQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, dq.ctx, ent.OpQueryExist)
switch _, err := dq.FirstID(ctx); {
case IsNotFound(err):
return false, nil
case err != nil:
return false, fmt.Errorf("ent: check existence: %w", err)
default:
return true, nil
}
}
// ExistX is like Exist, but panics if an error occurs.
func (dq *DocumentQuery) ExistX(ctx context.Context) bool {
exist, err := dq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the DocumentQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (dq *DocumentQuery) Clone() *DocumentQuery {
if dq == nil {
return nil
}
return &DocumentQuery{
config: dq.config,
ctx: dq.ctx.Clone(),
order: append([]document.OrderOption{}, dq.order...),
inters: append([]Interceptor{}, dq.inters...),
predicates: append([]predicate.Document{}, dq.predicates...),
withGroup: dq.withGroup.Clone(),
withAttachments: dq.withAttachments.Clone(),
// clone intermediate query.
sql: dq.sql.Clone(),
path: dq.path,
}
}
// WithGroup tells the query-builder to eager-load the nodes that are connected to
// the "group" edge. The optional arguments are used to configure the query builder of the edge.
func (dq *DocumentQuery) WithGroup(opts ...func(*GroupQuery)) *DocumentQuery {
query := (&GroupClient{config: dq.config}).Query()
for _, opt := range opts {
opt(query)
}
dq.withGroup = query
return dq
}
// WithAttachments tells the query-builder to eager-load the nodes that are connected to
// the "attachments" edge. The optional arguments are used to configure the query builder of the edge.
func (dq *DocumentQuery) WithAttachments(opts ...func(*AttachmentQuery)) *DocumentQuery {
query := (&AttachmentClient{config: dq.config}).Query()
for _, opt := range opts {
opt(query)
}
dq.withAttachments = query
return dq
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// CreatedAt time.Time `json:"created_at,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.Document.Query().
// GroupBy(document.FieldCreatedAt).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (dq *DocumentQuery) GroupBy(field string, fields ...string) *DocumentGroupBy {
dq.ctx.Fields = append([]string{field}, fields...)
grbuild := &DocumentGroupBy{build: dq}
grbuild.flds = &dq.ctx.Fields
grbuild.label = document.Label
grbuild.scan = grbuild.Scan
return grbuild
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// CreatedAt time.Time `json:"created_at,omitempty"`
// }
//
// client.Document.Query().
// Select(document.FieldCreatedAt).
// Scan(ctx, &v)
func (dq *DocumentQuery) Select(fields ...string) *DocumentSelect {
dq.ctx.Fields = append(dq.ctx.Fields, fields...)
sbuild := &DocumentSelect{DocumentQuery: dq}
sbuild.label = document.Label
sbuild.flds, sbuild.scan = &dq.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a DocumentSelect configured with the given aggregations.
func (dq *DocumentQuery) Aggregate(fns ...AggregateFunc) *DocumentSelect {
return dq.Select().Aggregate(fns...)
}
func (dq *DocumentQuery) prepareQuery(ctx context.Context) error {
for _, inter := range dq.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
}
if trv, ok := inter.(Traverser); ok {
if err := trv.Traverse(ctx, dq); err != nil {
return err
}
}
}
for _, f := range dq.ctx.Fields {
if !document.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if dq.path != nil {
prev, err := dq.path(ctx)
if err != nil {
return err
}
dq.sql = prev
}
return nil
}
func (dq *DocumentQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Document, error) {
var (
nodes = []*Document{}
withFKs = dq.withFKs
_spec = dq.querySpec()
loadedTypes = [2]bool{
dq.withGroup != nil,
dq.withAttachments != nil,
}
)
if dq.withGroup != nil {
withFKs = true
}
if withFKs {
_spec.Node.Columns = append(_spec.Node.Columns, document.ForeignKeys...)
}
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*Document).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &Document{config: dq.config}
nodes = append(nodes, node)
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
for i := range hooks {
hooks[i](ctx, _spec)
}
if err := sqlgraph.QueryNodes(ctx, dq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
if query := dq.withGroup; query != nil {
if err := dq.loadGroup(ctx, query, nodes, nil,
func(n *Document, e *Group) { n.Edges.Group = e }); err != nil {
return nil, err
}
}
if query := dq.withAttachments; query != nil {
if err := dq.loadAttachments(ctx, query, nodes,
func(n *Document) { n.Edges.Attachments = []*Attachment{} },
func(n *Document, e *Attachment) { n.Edges.Attachments = append(n.Edges.Attachments, e) }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (dq *DocumentQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Document, init func(*Document), assign func(*Document, *Group)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Document)
for i := range nodes {
if nodes[i].group_documents == nil {
continue
}
fk := *nodes[i].group_documents
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(group.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "group_documents" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (dq *DocumentQuery) loadAttachments(ctx context.Context, query *AttachmentQuery, nodes []*Document, init func(*Document), assign func(*Document, *Attachment)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[uuid.UUID]*Document)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
query.withFKs = true
query.Where(predicate.Attachment(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(document.AttachmentsColumn), fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.document_attachments
if fk == nil {
return fmt.Errorf(`foreign-key "document_attachments" is nil for node %v`, n.ID)
}
node, ok := nodeids[*fk]
if !ok {
return fmt.Errorf(`unexpected referenced foreign-key "document_attachments" returned %v for node %v`, *fk, n.ID)
}
assign(node, n)
}
return nil
}
func (dq *DocumentQuery) sqlCount(ctx context.Context) (int, error) {
_spec := dq.querySpec()
_spec.Node.Columns = dq.ctx.Fields
if len(dq.ctx.Fields) > 0 {
_spec.Unique = dq.ctx.Unique != nil && *dq.ctx.Unique
}
return sqlgraph.CountNodes(ctx, dq.driver, _spec)
}
func (dq *DocumentQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(document.Table, document.Columns, sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID))
_spec.From = dq.sql
if unique := dq.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if dq.path != nil {
_spec.Unique = true
}
if fields := dq.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, document.FieldID)
for i := range fields {
if fields[i] != document.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
}
if ps := dq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := dq.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := dq.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := dq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (dq *DocumentQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(dq.driver.Dialect())
t1 := builder.Table(document.Table)
columns := dq.ctx.Fields
if len(columns) == 0 {
columns = document.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if dq.sql != nil {
selector = dq.sql
selector.Select(selector.Columns(columns...)...)
}
if dq.ctx.Unique != nil && *dq.ctx.Unique {
selector.Distinct()
}
for _, p := range dq.predicates {
p(selector)
}
for _, p := range dq.order {
p(selector)
}
if offset := dq.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := dq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// DocumentGroupBy is the group-by builder for Document entities.
type DocumentGroupBy struct {
selector
build *DocumentQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (dgb *DocumentGroupBy) Aggregate(fns ...AggregateFunc) *DocumentGroupBy {
dgb.fns = append(dgb.fns, fns...)
return dgb
}
// Scan applies the selector query and scans the result into the given value.
func (dgb *DocumentGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, dgb.build.ctx, ent.OpQueryGroupBy)
if err := dgb.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*DocumentQuery, *DocumentGroupBy](ctx, dgb.build, dgb, dgb.build.inters, v)
}
func (dgb *DocumentGroupBy) sqlScan(ctx context.Context, root *DocumentQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(dgb.fns))
for _, fn := range dgb.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*dgb.flds)+len(dgb.fns))
for _, f := range *dgb.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*dgb.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := dgb.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// DocumentSelect is the builder for selecting fields of Document entities.
type DocumentSelect struct {
*DocumentQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (ds *DocumentSelect) Aggregate(fns ...AggregateFunc) *DocumentSelect {
ds.fns = append(ds.fns, fns...)
return ds
}
// Scan applies the selector query and scans the result into the given value.
func (ds *DocumentSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, ds.ctx, ent.OpQuerySelect)
if err := ds.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*DocumentQuery, *DocumentSelect](ctx, ds.DocumentQuery, ds, ds.inters, v)
}
func (ds *DocumentSelect) sqlScan(ctx context.Context, root *DocumentQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(ds.fns))
for _, fn := range ds.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*ds.selector.flds); {
case n == 0 && len(aggregation) > 0:
selector.Select(aggregation...)
case n != 0 && len(aggregation) > 0:
selector.AppendSelect(aggregation...)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := ds.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

View File

@@ -1,579 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/group"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/predicate"
)
// DocumentUpdate is the builder for updating Document entities.
type DocumentUpdate struct {
config
hooks []Hook
mutation *DocumentMutation
}
// Where appends a list predicates to the DocumentUpdate builder.
func (du *DocumentUpdate) Where(ps ...predicate.Document) *DocumentUpdate {
du.mutation.Where(ps...)
return du
}
// SetUpdatedAt sets the "updated_at" field.
func (du *DocumentUpdate) SetUpdatedAt(t time.Time) *DocumentUpdate {
du.mutation.SetUpdatedAt(t)
return du
}
// SetTitle sets the "title" field.
func (du *DocumentUpdate) SetTitle(s string) *DocumentUpdate {
du.mutation.SetTitle(s)
return du
}
// SetNillableTitle sets the "title" field if the given value is not nil.
func (du *DocumentUpdate) SetNillableTitle(s *string) *DocumentUpdate {
if s != nil {
du.SetTitle(*s)
}
return du
}
// SetPath sets the "path" field.
func (du *DocumentUpdate) SetPath(s string) *DocumentUpdate {
du.mutation.SetPath(s)
return du
}
// SetNillablePath sets the "path" field if the given value is not nil.
func (du *DocumentUpdate) SetNillablePath(s *string) *DocumentUpdate {
if s != nil {
du.SetPath(*s)
}
return du
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (du *DocumentUpdate) SetGroupID(id uuid.UUID) *DocumentUpdate {
du.mutation.SetGroupID(id)
return du
}
// SetGroup sets the "group" edge to the Group entity.
func (du *DocumentUpdate) SetGroup(g *Group) *DocumentUpdate {
return du.SetGroupID(g.ID)
}
// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by IDs.
func (du *DocumentUpdate) AddAttachmentIDs(ids ...uuid.UUID) *DocumentUpdate {
du.mutation.AddAttachmentIDs(ids...)
return du
}
// AddAttachments adds the "attachments" edges to the Attachment entity.
func (du *DocumentUpdate) AddAttachments(a ...*Attachment) *DocumentUpdate {
ids := make([]uuid.UUID, len(a))
for i := range a {
ids[i] = a[i].ID
}
return du.AddAttachmentIDs(ids...)
}
// Mutation returns the DocumentMutation object of the builder.
func (du *DocumentUpdate) Mutation() *DocumentMutation {
return du.mutation
}
// ClearGroup clears the "group" edge to the Group entity.
func (du *DocumentUpdate) ClearGroup() *DocumentUpdate {
du.mutation.ClearGroup()
return du
}
// ClearAttachments clears all "attachments" edges to the Attachment entity.
func (du *DocumentUpdate) ClearAttachments() *DocumentUpdate {
du.mutation.ClearAttachments()
return du
}
// RemoveAttachmentIDs removes the "attachments" edge to Attachment entities by IDs.
func (du *DocumentUpdate) RemoveAttachmentIDs(ids ...uuid.UUID) *DocumentUpdate {
du.mutation.RemoveAttachmentIDs(ids...)
return du
}
// RemoveAttachments removes "attachments" edges to Attachment entities.
func (du *DocumentUpdate) RemoveAttachments(a ...*Attachment) *DocumentUpdate {
ids := make([]uuid.UUID, len(a))
for i := range a {
ids[i] = a[i].ID
}
return du.RemoveAttachmentIDs(ids...)
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (du *DocumentUpdate) Save(ctx context.Context) (int, error) {
du.defaults()
return withHooks(ctx, du.sqlSave, du.mutation, du.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (du *DocumentUpdate) SaveX(ctx context.Context) int {
affected, err := du.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (du *DocumentUpdate) Exec(ctx context.Context) error {
_, err := du.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (du *DocumentUpdate) ExecX(ctx context.Context) {
if err := du.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (du *DocumentUpdate) defaults() {
if _, ok := du.mutation.UpdatedAt(); !ok {
v := document.UpdateDefaultUpdatedAt()
du.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (du *DocumentUpdate) check() error {
if v, ok := du.mutation.Title(); ok {
if err := document.TitleValidator(v); err != nil {
return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "Document.title": %w`, err)}
}
}
if v, ok := du.mutation.Path(); ok {
if err := document.PathValidator(v); err != nil {
return &ValidationError{Name: "path", err: fmt.Errorf(`ent: validator failed for field "Document.path": %w`, err)}
}
}
if du.mutation.GroupCleared() && len(du.mutation.GroupIDs()) > 0 {
return errors.New(`ent: clearing a required unique edge "Document.group"`)
}
return nil
}
func (du *DocumentUpdate) sqlSave(ctx context.Context) (n int, err error) {
if err := du.check(); err != nil {
return n, err
}
_spec := sqlgraph.NewUpdateSpec(document.Table, document.Columns, sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID))
if ps := du.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := du.mutation.UpdatedAt(); ok {
_spec.SetField(document.FieldUpdatedAt, field.TypeTime, value)
}
if value, ok := du.mutation.Title(); ok {
_spec.SetField(document.FieldTitle, field.TypeString, value)
}
if value, ok := du.mutation.Path(); ok {
_spec.SetField(document.FieldPath, field.TypeString, value)
}
if du.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: document.GroupTable,
Columns: []string{document.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := du.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: document.GroupTable,
Columns: []string{document.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if du.mutation.AttachmentsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: document.AttachmentsTable,
Columns: []string{document.AttachmentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := du.mutation.RemovedAttachmentsIDs(); len(nodes) > 0 && !du.mutation.AttachmentsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: document.AttachmentsTable,
Columns: []string{document.AttachmentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := du.mutation.AttachmentsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: document.AttachmentsTable,
Columns: []string{document.AttachmentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if n, err = sqlgraph.UpdateNodes(ctx, du.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{document.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
du.mutation.done = true
return n, nil
}
// DocumentUpdateOne is the builder for updating a single Document entity.
type DocumentUpdateOne struct {
config
fields []string
hooks []Hook
mutation *DocumentMutation
}
// SetUpdatedAt sets the "updated_at" field.
func (duo *DocumentUpdateOne) SetUpdatedAt(t time.Time) *DocumentUpdateOne {
duo.mutation.SetUpdatedAt(t)
return duo
}
// SetTitle sets the "title" field.
func (duo *DocumentUpdateOne) SetTitle(s string) *DocumentUpdateOne {
duo.mutation.SetTitle(s)
return duo
}
// SetNillableTitle sets the "title" field if the given value is not nil.
func (duo *DocumentUpdateOne) SetNillableTitle(s *string) *DocumentUpdateOne {
if s != nil {
duo.SetTitle(*s)
}
return duo
}
// SetPath sets the "path" field.
func (duo *DocumentUpdateOne) SetPath(s string) *DocumentUpdateOne {
duo.mutation.SetPath(s)
return duo
}
// SetNillablePath sets the "path" field if the given value is not nil.
func (duo *DocumentUpdateOne) SetNillablePath(s *string) *DocumentUpdateOne {
if s != nil {
duo.SetPath(*s)
}
return duo
}
// SetGroupID sets the "group" edge to the Group entity by ID.
func (duo *DocumentUpdateOne) SetGroupID(id uuid.UUID) *DocumentUpdateOne {
duo.mutation.SetGroupID(id)
return duo
}
// SetGroup sets the "group" edge to the Group entity.
func (duo *DocumentUpdateOne) SetGroup(g *Group) *DocumentUpdateOne {
return duo.SetGroupID(g.ID)
}
// AddAttachmentIDs adds the "attachments" edge to the Attachment entity by IDs.
func (duo *DocumentUpdateOne) AddAttachmentIDs(ids ...uuid.UUID) *DocumentUpdateOne {
duo.mutation.AddAttachmentIDs(ids...)
return duo
}
// AddAttachments adds the "attachments" edges to the Attachment entity.
func (duo *DocumentUpdateOne) AddAttachments(a ...*Attachment) *DocumentUpdateOne {
ids := make([]uuid.UUID, len(a))
for i := range a {
ids[i] = a[i].ID
}
return duo.AddAttachmentIDs(ids...)
}
// Mutation returns the DocumentMutation object of the builder.
func (duo *DocumentUpdateOne) Mutation() *DocumentMutation {
return duo.mutation
}
// ClearGroup clears the "group" edge to the Group entity.
func (duo *DocumentUpdateOne) ClearGroup() *DocumentUpdateOne {
duo.mutation.ClearGroup()
return duo
}
// ClearAttachments clears all "attachments" edges to the Attachment entity.
func (duo *DocumentUpdateOne) ClearAttachments() *DocumentUpdateOne {
duo.mutation.ClearAttachments()
return duo
}
// RemoveAttachmentIDs removes the "attachments" edge to Attachment entities by IDs.
func (duo *DocumentUpdateOne) RemoveAttachmentIDs(ids ...uuid.UUID) *DocumentUpdateOne {
duo.mutation.RemoveAttachmentIDs(ids...)
return duo
}
// RemoveAttachments removes "attachments" edges to Attachment entities.
func (duo *DocumentUpdateOne) RemoveAttachments(a ...*Attachment) *DocumentUpdateOne {
ids := make([]uuid.UUID, len(a))
for i := range a {
ids[i] = a[i].ID
}
return duo.RemoveAttachmentIDs(ids...)
}
// Where appends a list predicates to the DocumentUpdate builder.
func (duo *DocumentUpdateOne) Where(ps ...predicate.Document) *DocumentUpdateOne {
duo.mutation.Where(ps...)
return duo
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (duo *DocumentUpdateOne) Select(field string, fields ...string) *DocumentUpdateOne {
duo.fields = append([]string{field}, fields...)
return duo
}
// Save executes the query and returns the updated Document entity.
func (duo *DocumentUpdateOne) Save(ctx context.Context) (*Document, error) {
duo.defaults()
return withHooks(ctx, duo.sqlSave, duo.mutation, duo.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (duo *DocumentUpdateOne) SaveX(ctx context.Context) *Document {
node, err := duo.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (duo *DocumentUpdateOne) Exec(ctx context.Context) error {
_, err := duo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (duo *DocumentUpdateOne) ExecX(ctx context.Context) {
if err := duo.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (duo *DocumentUpdateOne) defaults() {
if _, ok := duo.mutation.UpdatedAt(); !ok {
v := document.UpdateDefaultUpdatedAt()
duo.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (duo *DocumentUpdateOne) check() error {
if v, ok := duo.mutation.Title(); ok {
if err := document.TitleValidator(v); err != nil {
return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "Document.title": %w`, err)}
}
}
if v, ok := duo.mutation.Path(); ok {
if err := document.PathValidator(v); err != nil {
return &ValidationError{Name: "path", err: fmt.Errorf(`ent: validator failed for field "Document.path": %w`, err)}
}
}
if duo.mutation.GroupCleared() && len(duo.mutation.GroupIDs()) > 0 {
return errors.New(`ent: clearing a required unique edge "Document.group"`)
}
return nil
}
func (duo *DocumentUpdateOne) sqlSave(ctx context.Context) (_node *Document, err error) {
if err := duo.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(document.Table, document.Columns, sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID))
id, ok := duo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Document.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := duo.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, document.FieldID)
for _, f := range fields {
if !document.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != document.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := duo.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := duo.mutation.UpdatedAt(); ok {
_spec.SetField(document.FieldUpdatedAt, field.TypeTime, value)
}
if value, ok := duo.mutation.Title(); ok {
_spec.SetField(document.FieldTitle, field.TypeString, value)
}
if value, ok := duo.mutation.Path(); ok {
_spec.SetField(document.FieldPath, field.TypeString, value)
}
if duo.mutation.GroupCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: document.GroupTable,
Columns: []string{document.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := duo.mutation.GroupIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: true,
Table: document.GroupTable,
Columns: []string{document.GroupColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(group.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if duo.mutation.AttachmentsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: document.AttachmentsTable,
Columns: []string{document.AttachmentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := duo.mutation.RemovedAttachmentsIDs(); len(nodes) > 0 && !duo.mutation.AttachmentsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: document.AttachmentsTable,
Columns: []string{document.AttachmentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := duo.mutation.AttachmentsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: document.AttachmentsTable,
Columns: []string{document.AttachmentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(attachment.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &Document{config: duo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, duo.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{document.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
duo.mutation.done = true
return _node, nil
}

View File

@@ -15,7 +15,6 @@ import (
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/attachment"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/authroles"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/authtokens"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/group"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/groupinvitationtoken"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
@@ -88,7 +87,6 @@ func checkColumn(table, column string) error {
attachment.Table: attachment.ValidColumn,
authroles.Table: authroles.ValidColumn,
authtokens.Table: authtokens.ValidColumn,
document.Table: document.ValidColumn,
group.Table: group.ValidColumn,
groupinvitationtoken.Table: groupinvitationtoken.ValidColumn,
item.Table: item.ValidColumn,

View File

@@ -42,15 +42,13 @@ type GroupEdges struct {
Items []*Item `json:"items,omitempty"`
// Labels holds the value of the labels edge.
Labels []*Label `json:"labels,omitempty"`
// Documents holds the value of the documents edge.
Documents []*Document `json:"documents,omitempty"`
// InvitationTokens holds the value of the invitation_tokens edge.
InvitationTokens []*GroupInvitationToken `json:"invitation_tokens,omitempty"`
// Notifiers holds the value of the notifiers edge.
Notifiers []*Notifier `json:"notifiers,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [7]bool
loadedTypes [6]bool
}
// UsersOrErr returns the Users value or an error if the edge
@@ -89,19 +87,10 @@ func (e GroupEdges) LabelsOrErr() ([]*Label, error) {
return nil, &NotLoadedError{edge: "labels"}
}
// DocumentsOrErr returns the Documents value or an error if the edge
// was not loaded in eager-loading.
func (e GroupEdges) DocumentsOrErr() ([]*Document, error) {
if e.loadedTypes[4] {
return e.Documents, nil
}
return nil, &NotLoadedError{edge: "documents"}
}
// InvitationTokensOrErr returns the InvitationTokens value or an error if the edge
// was not loaded in eager-loading.
func (e GroupEdges) InvitationTokensOrErr() ([]*GroupInvitationToken, error) {
if e.loadedTypes[5] {
if e.loadedTypes[4] {
return e.InvitationTokens, nil
}
return nil, &NotLoadedError{edge: "invitation_tokens"}
@@ -110,7 +99,7 @@ func (e GroupEdges) InvitationTokensOrErr() ([]*GroupInvitationToken, error) {
// NotifiersOrErr returns the Notifiers value or an error if the edge
// was not loaded in eager-loading.
func (e GroupEdges) NotifiersOrErr() ([]*Notifier, error) {
if e.loadedTypes[6] {
if e.loadedTypes[5] {
return e.Notifiers, nil
}
return nil, &NotLoadedError{edge: "notifiers"}
@@ -205,11 +194,6 @@ func (gr *Group) QueryLabels() *LabelQuery {
return NewGroupClient(gr.config).QueryLabels(gr)
}
// QueryDocuments queries the "documents" edge of the Group entity.
func (gr *Group) QueryDocuments() *DocumentQuery {
return NewGroupClient(gr.config).QueryDocuments(gr)
}
// QueryInvitationTokens queries the "invitation_tokens" edge of the Group entity.
func (gr *Group) QueryInvitationTokens() *GroupInvitationTokenQuery {
return NewGroupClient(gr.config).QueryInvitationTokens(gr)

View File

@@ -31,8 +31,6 @@ const (
EdgeItems = "items"
// EdgeLabels holds the string denoting the labels edge name in mutations.
EdgeLabels = "labels"
// EdgeDocuments holds the string denoting the documents edge name in mutations.
EdgeDocuments = "documents"
// EdgeInvitationTokens holds the string denoting the invitation_tokens edge name in mutations.
EdgeInvitationTokens = "invitation_tokens"
// EdgeNotifiers holds the string denoting the notifiers edge name in mutations.
@@ -67,13 +65,6 @@ const (
LabelsInverseTable = "labels"
// LabelsColumn is the table column denoting the labels relation/edge.
LabelsColumn = "group_labels"
// DocumentsTable is the table that holds the documents relation/edge.
DocumentsTable = "documents"
// DocumentsInverseTable is the table name for the Document entity.
// It exists in this package in order to avoid circular dependency with the "document" package.
DocumentsInverseTable = "documents"
// DocumentsColumn is the table column denoting the documents relation/edge.
DocumentsColumn = "group_documents"
// InvitationTokensTable is the table that holds the invitation_tokens relation/edge.
InvitationTokensTable = "group_invitation_tokens"
// InvitationTokensInverseTable is the table name for the GroupInvitationToken entity.
@@ -208,20 +199,6 @@ func ByLabels(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
}
}
// ByDocumentsCount orders the results by documents count.
func ByDocumentsCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newDocumentsStep(), opts...)
}
}
// ByDocuments orders the results by documents terms.
func ByDocuments(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newDocumentsStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
// ByInvitationTokensCount orders the results by invitation_tokens count.
func ByInvitationTokensCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
@@ -277,13 +254,6 @@ func newLabelsStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.O2M, false, LabelsTable, LabelsColumn),
)
}
func newDocumentsStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(DocumentsInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, DocumentsTable, DocumentsColumn),
)
}
func newInvitationTokensStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),

View File

@@ -378,29 +378,6 @@ func HasLabelsWith(preds ...predicate.Label) predicate.Group {
})
}
// HasDocuments applies the HasEdge predicate on the "documents" edge.
func HasDocuments() predicate.Group {
return predicate.Group(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, DocumentsTable, DocumentsColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasDocumentsWith applies the HasEdge predicate on the "documents" edge with a given conditions (other predicates).
func HasDocumentsWith(preds ...predicate.Document) predicate.Group {
return predicate.Group(func(s *sql.Selector) {
step := newDocumentsStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasInvitationTokens applies the HasEdge predicate on the "invitation_tokens" edge.
func HasInvitationTokens() predicate.Group {
return predicate.Group(func(s *sql.Selector) {

View File

@@ -11,7 +11,6 @@ import (
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/group"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/groupinvitationtoken"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
@@ -150,21 +149,6 @@ func (gc *GroupCreate) AddLabels(l ...*Label) *GroupCreate {
return gc.AddLabelIDs(ids...)
}
// AddDocumentIDs adds the "documents" edge to the Document entity by IDs.
func (gc *GroupCreate) AddDocumentIDs(ids ...uuid.UUID) *GroupCreate {
gc.mutation.AddDocumentIDs(ids...)
return gc
}
// AddDocuments adds the "documents" edges to the Document entity.
func (gc *GroupCreate) AddDocuments(d ...*Document) *GroupCreate {
ids := make([]uuid.UUID, len(d))
for i := range d {
ids[i] = d[i].ID
}
return gc.AddDocumentIDs(ids...)
}
// AddInvitationTokenIDs adds the "invitation_tokens" edge to the GroupInvitationToken entity by IDs.
func (gc *GroupCreate) AddInvitationTokenIDs(ids ...uuid.UUID) *GroupCreate {
gc.mutation.AddInvitationTokenIDs(ids...)
@@ -382,22 +366,6 @@ func (gc *GroupCreate) createSpec() (*Group, *sqlgraph.CreateSpec) {
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := gc.mutation.DocumentsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.DocumentsTable,
Columns: []string{group.DocumentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := gc.mutation.InvitationTokensIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,

View File

@@ -13,7 +13,6 @@ import (
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/group"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/groupinvitationtoken"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
@@ -35,7 +34,6 @@ type GroupQuery struct {
withLocations *LocationQuery
withItems *ItemQuery
withLabels *LabelQuery
withDocuments *DocumentQuery
withInvitationTokens *GroupInvitationTokenQuery
withNotifiers *NotifierQuery
// intermediate query (i.e. traversal path).
@@ -162,28 +160,6 @@ func (gq *GroupQuery) QueryLabels() *LabelQuery {
return query
}
// QueryDocuments chains the current query on the "documents" edge.
func (gq *GroupQuery) QueryDocuments() *DocumentQuery {
query := (&DocumentClient{config: gq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := gq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := gq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(group.Table, group.FieldID, selector),
sqlgraph.To(document.Table, document.FieldID),
sqlgraph.Edge(sqlgraph.O2M, false, group.DocumentsTable, group.DocumentsColumn),
)
fromU = sqlgraph.SetNeighbors(gq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryInvitationTokens chains the current query on the "invitation_tokens" edge.
func (gq *GroupQuery) QueryInvitationTokens() *GroupInvitationTokenQuery {
query := (&GroupInvitationTokenClient{config: gq.config}).Query()
@@ -424,7 +400,6 @@ func (gq *GroupQuery) Clone() *GroupQuery {
withLocations: gq.withLocations.Clone(),
withItems: gq.withItems.Clone(),
withLabels: gq.withLabels.Clone(),
withDocuments: gq.withDocuments.Clone(),
withInvitationTokens: gq.withInvitationTokens.Clone(),
withNotifiers: gq.withNotifiers.Clone(),
// clone intermediate query.
@@ -477,17 +452,6 @@ func (gq *GroupQuery) WithLabels(opts ...func(*LabelQuery)) *GroupQuery {
return gq
}
// WithDocuments tells the query-builder to eager-load the nodes that are connected to
// the "documents" edge. The optional arguments are used to configure the query builder of the edge.
func (gq *GroupQuery) WithDocuments(opts ...func(*DocumentQuery)) *GroupQuery {
query := (&DocumentClient{config: gq.config}).Query()
for _, opt := range opts {
opt(query)
}
gq.withDocuments = query
return gq
}
// WithInvitationTokens tells the query-builder to eager-load the nodes that are connected to
// the "invitation_tokens" edge. The optional arguments are used to configure the query builder of the edge.
func (gq *GroupQuery) WithInvitationTokens(opts ...func(*GroupInvitationTokenQuery)) *GroupQuery {
@@ -588,12 +552,11 @@ func (gq *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
var (
nodes = []*Group{}
_spec = gq.querySpec()
loadedTypes = [7]bool{
loadedTypes = [6]bool{
gq.withUsers != nil,
gq.withLocations != nil,
gq.withItems != nil,
gq.withLabels != nil,
gq.withDocuments != nil,
gq.withInvitationTokens != nil,
gq.withNotifiers != nil,
}
@@ -644,13 +607,6 @@ func (gq *GroupQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Group,
return nil, err
}
}
if query := gq.withDocuments; query != nil {
if err := gq.loadDocuments(ctx, query, nodes,
func(n *Group) { n.Edges.Documents = []*Document{} },
func(n *Group, e *Document) { n.Edges.Documents = append(n.Edges.Documents, e) }); err != nil {
return nil, err
}
}
if query := gq.withInvitationTokens; query != nil {
if err := gq.loadInvitationTokens(ctx, query, nodes,
func(n *Group) { n.Edges.InvitationTokens = []*GroupInvitationToken{} },
@@ -794,37 +750,6 @@ func (gq *GroupQuery) loadLabels(ctx context.Context, query *LabelQuery, nodes [
}
return nil
}
func (gq *GroupQuery) loadDocuments(ctx context.Context, query *DocumentQuery, nodes []*Group, init func(*Group), assign func(*Group, *Document)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[uuid.UUID]*Group)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
query.withFKs = true
query.Where(predicate.Document(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(group.DocumentsColumn), fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.group_documents
if fk == nil {
return fmt.Errorf(`foreign-key "group_documents" is nil for node %v`, n.ID)
}
node, ok := nodeids[*fk]
if !ok {
return fmt.Errorf(`unexpected referenced foreign-key "group_documents" returned %v for node %v`, *fk, n.ID)
}
assign(node, n)
}
return nil
}
func (gq *GroupQuery) loadInvitationTokens(ctx context.Context, query *GroupInvitationTokenQuery, nodes []*Group, init func(*Group), assign func(*Group, *GroupInvitationToken)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[uuid.UUID]*Group)

View File

@@ -12,7 +12,6 @@ import (
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/document"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/group"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/groupinvitationtoken"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
@@ -130,21 +129,6 @@ func (gu *GroupUpdate) AddLabels(l ...*Label) *GroupUpdate {
return gu.AddLabelIDs(ids...)
}
// AddDocumentIDs adds the "documents" edge to the Document entity by IDs.
func (gu *GroupUpdate) AddDocumentIDs(ids ...uuid.UUID) *GroupUpdate {
gu.mutation.AddDocumentIDs(ids...)
return gu
}
// AddDocuments adds the "documents" edges to the Document entity.
func (gu *GroupUpdate) AddDocuments(d ...*Document) *GroupUpdate {
ids := make([]uuid.UUID, len(d))
for i := range d {
ids[i] = d[i].ID
}
return gu.AddDocumentIDs(ids...)
}
// AddInvitationTokenIDs adds the "invitation_tokens" edge to the GroupInvitationToken entity by IDs.
func (gu *GroupUpdate) AddInvitationTokenIDs(ids ...uuid.UUID) *GroupUpdate {
gu.mutation.AddInvitationTokenIDs(ids...)
@@ -264,27 +248,6 @@ func (gu *GroupUpdate) RemoveLabels(l ...*Label) *GroupUpdate {
return gu.RemoveLabelIDs(ids...)
}
// ClearDocuments clears all "documents" edges to the Document entity.
func (gu *GroupUpdate) ClearDocuments() *GroupUpdate {
gu.mutation.ClearDocuments()
return gu
}
// RemoveDocumentIDs removes the "documents" edge to Document entities by IDs.
func (gu *GroupUpdate) RemoveDocumentIDs(ids ...uuid.UUID) *GroupUpdate {
gu.mutation.RemoveDocumentIDs(ids...)
return gu
}
// RemoveDocuments removes "documents" edges to Document entities.
func (gu *GroupUpdate) RemoveDocuments(d ...*Document) *GroupUpdate {
ids := make([]uuid.UUID, len(d))
for i := range d {
ids[i] = d[i].ID
}
return gu.RemoveDocumentIDs(ids...)
}
// ClearInvitationTokens clears all "invitation_tokens" edges to the GroupInvitationToken entity.
func (gu *GroupUpdate) ClearInvitationTokens() *GroupUpdate {
gu.mutation.ClearInvitationTokens()
@@ -574,51 +537,6 @@ func (gu *GroupUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if gu.mutation.DocumentsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.DocumentsTable,
Columns: []string{group.DocumentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := gu.mutation.RemovedDocumentsIDs(); len(nodes) > 0 && !gu.mutation.DocumentsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.DocumentsTable,
Columns: []string{group.DocumentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := gu.mutation.DocumentsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.DocumentsTable,
Columns: []string{group.DocumentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if gu.mutation.InvitationTokensCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
@@ -823,21 +741,6 @@ func (guo *GroupUpdateOne) AddLabels(l ...*Label) *GroupUpdateOne {
return guo.AddLabelIDs(ids...)
}
// AddDocumentIDs adds the "documents" edge to the Document entity by IDs.
func (guo *GroupUpdateOne) AddDocumentIDs(ids ...uuid.UUID) *GroupUpdateOne {
guo.mutation.AddDocumentIDs(ids...)
return guo
}
// AddDocuments adds the "documents" edges to the Document entity.
func (guo *GroupUpdateOne) AddDocuments(d ...*Document) *GroupUpdateOne {
ids := make([]uuid.UUID, len(d))
for i := range d {
ids[i] = d[i].ID
}
return guo.AddDocumentIDs(ids...)
}
// AddInvitationTokenIDs adds the "invitation_tokens" edge to the GroupInvitationToken entity by IDs.
func (guo *GroupUpdateOne) AddInvitationTokenIDs(ids ...uuid.UUID) *GroupUpdateOne {
guo.mutation.AddInvitationTokenIDs(ids...)
@@ -957,27 +860,6 @@ func (guo *GroupUpdateOne) RemoveLabels(l ...*Label) *GroupUpdateOne {
return guo.RemoveLabelIDs(ids...)
}
// ClearDocuments clears all "documents" edges to the Document entity.
func (guo *GroupUpdateOne) ClearDocuments() *GroupUpdateOne {
guo.mutation.ClearDocuments()
return guo
}
// RemoveDocumentIDs removes the "documents" edge to Document entities by IDs.
func (guo *GroupUpdateOne) RemoveDocumentIDs(ids ...uuid.UUID) *GroupUpdateOne {
guo.mutation.RemoveDocumentIDs(ids...)
return guo
}
// RemoveDocuments removes "documents" edges to Document entities.
func (guo *GroupUpdateOne) RemoveDocuments(d ...*Document) *GroupUpdateOne {
ids := make([]uuid.UUID, len(d))
for i := range d {
ids[i] = d[i].ID
}
return guo.RemoveDocumentIDs(ids...)
}
// ClearInvitationTokens clears all "invitation_tokens" edges to the GroupInvitationToken entity.
func (guo *GroupUpdateOne) ClearInvitationTokens() *GroupUpdateOne {
guo.mutation.ClearInvitationTokens()
@@ -1297,51 +1179,6 @@ func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (_node *Group, err error
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if guo.mutation.DocumentsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.DocumentsTable,
Columns: []string{group.DocumentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := guo.mutation.RemovedDocumentsIDs(); len(nodes) > 0 && !guo.mutation.DocumentsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.DocumentsTable,
Columns: []string{group.DocumentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := guo.mutation.DocumentsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: false,
Table: group.DocumentsTable,
Columns: []string{group.DocumentsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(document.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if guo.mutation.InvitationTokensCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,

View File

@@ -16,10 +16,6 @@ func (at *AuthTokens) GetID() uuid.UUID {
return at.ID
}
func (d *Document) GetID() uuid.UUID {
return d.ID
}
func (gr *Group) GetID() uuid.UUID {
return gr.ID
}

View File

@@ -45,18 +45,6 @@ func (f AuthTokensFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value,
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.AuthTokensMutation", m)
}
// The DocumentFunc type is an adapter to allow the use of ordinary
// function as Document mutator.
type DocumentFunc func(context.Context, *ent.DocumentMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f DocumentFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.DocumentMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.DocumentMutation", m)
}
// The GroupFunc type is an adapter to allow the use of ordinary
// function as Group mutator.
type GroupFunc func(context.Context, *ent.GroupMutation) (ent.Value, error)

View File

@@ -40,6 +40,8 @@ type Item struct {
Archived bool `json:"archived,omitempty"`
// AssetID holds the value of the "asset_id" field.
AssetID int `json:"asset_id,omitempty"`
// SyncChildItemsLocations holds the value of the "sync_child_items_locations" field.
SyncChildItemsLocations bool `json:"sync_child_items_locations,omitempty"`
// SerialNumber holds the value of the "serial_number" field.
SerialNumber string `json:"serial_number,omitempty"`
// ModelNumber holds the value of the "model_number" field.
@@ -181,7 +183,7 @@ func (*Item) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case item.FieldInsured, item.FieldArchived, item.FieldLifetimeWarranty:
case item.FieldInsured, item.FieldArchived, item.FieldSyncChildItemsLocations, item.FieldLifetimeWarranty:
values[i] = new(sql.NullBool)
case item.FieldPurchasePrice, item.FieldSoldPrice:
values[i] = new(sql.NullFloat64)
@@ -280,6 +282,12 @@ func (i *Item) assignValues(columns []string, values []any) error {
} else if value.Valid {
i.AssetID = int(value.Int64)
}
case item.FieldSyncChildItemsLocations:
if value, ok := values[j].(*sql.NullBool); !ok {
return fmt.Errorf("unexpected type %T for field sync_child_items_locations", values[j])
} else if value.Valid {
i.SyncChildItemsLocations = value.Bool
}
case item.FieldSerialNumber:
if value, ok := values[j].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field serial_number", values[j])
@@ -485,6 +493,9 @@ func (i *Item) String() string {
builder.WriteString("asset_id=")
builder.WriteString(fmt.Sprintf("%v", i.AssetID))
builder.WriteString(", ")
builder.WriteString("sync_child_items_locations=")
builder.WriteString(fmt.Sprintf("%v", i.SyncChildItemsLocations))
builder.WriteString(", ")
builder.WriteString("serial_number=")
builder.WriteString(i.SerialNumber)
builder.WriteString(", ")

View File

@@ -35,6 +35,8 @@ const (
FieldArchived = "archived"
// FieldAssetID holds the string denoting the asset_id field in the database.
FieldAssetID = "asset_id"
// FieldSyncChildItemsLocations holds the string denoting the sync_child_items_locations field in the database.
FieldSyncChildItemsLocations = "sync_child_items_locations"
// FieldSerialNumber holds the string denoting the serial_number field in the database.
FieldSerialNumber = "serial_number"
// FieldModelNumber holds the string denoting the model_number field in the database.
@@ -142,6 +144,7 @@ var Columns = []string{
FieldInsured,
FieldArchived,
FieldAssetID,
FieldSyncChildItemsLocations,
FieldSerialNumber,
FieldModelNumber,
FieldManufacturer,
@@ -209,6 +212,8 @@ var (
DefaultArchived bool
// DefaultAssetID holds the default value on creation for the "asset_id" field.
DefaultAssetID int
// DefaultSyncChildItemsLocations holds the default value on creation for the "sync_child_items_locations" field.
DefaultSyncChildItemsLocations bool
// SerialNumberValidator is a validator for the "serial_number" field. It is called by the builders before save.
SerialNumberValidator func(string) error
// ModelNumberValidator is a validator for the "model_number" field. It is called by the builders before save.
@@ -287,6 +292,11 @@ func ByAssetID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldAssetID, opts...).ToFunc()
}
// BySyncChildItemsLocations orders the results by the sync_child_items_locations field.
func BySyncChildItemsLocations(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSyncChildItemsLocations, opts...).ToFunc()
}
// BySerialNumber orders the results by the serial_number field.
func BySerialNumber(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldSerialNumber, opts...).ToFunc()

View File

@@ -106,6 +106,11 @@ func AssetID(v int) predicate.Item {
return predicate.Item(sql.FieldEQ(FieldAssetID, v))
}
// SyncChildItemsLocations applies equality check predicate on the "sync_child_items_locations" field. It's identical to SyncChildItemsLocationsEQ.
func SyncChildItemsLocations(v bool) predicate.Item {
return predicate.Item(sql.FieldEQ(FieldSyncChildItemsLocations, v))
}
// SerialNumber applies equality check predicate on the "serial_number" field. It's identical to SerialNumberEQ.
func SerialNumber(v string) predicate.Item {
return predicate.Item(sql.FieldEQ(FieldSerialNumber, v))
@@ -641,6 +646,16 @@ func AssetIDLTE(v int) predicate.Item {
return predicate.Item(sql.FieldLTE(FieldAssetID, v))
}
// SyncChildItemsLocationsEQ applies the EQ predicate on the "sync_child_items_locations" field.
func SyncChildItemsLocationsEQ(v bool) predicate.Item {
return predicate.Item(sql.FieldEQ(FieldSyncChildItemsLocations, v))
}
// SyncChildItemsLocationsNEQ applies the NEQ predicate on the "sync_child_items_locations" field.
func SyncChildItemsLocationsNEQ(v bool) predicate.Item {
return predicate.Item(sql.FieldNEQ(FieldSyncChildItemsLocations, v))
}
// SerialNumberEQ applies the EQ predicate on the "serial_number" field.
func SerialNumberEQ(v string) predicate.Item {
return predicate.Item(sql.FieldEQ(FieldSerialNumber, v))

View File

@@ -159,6 +159,20 @@ func (ic *ItemCreate) SetNillableAssetID(i *int) *ItemCreate {
return ic
}
// SetSyncChildItemsLocations sets the "sync_child_items_locations" field.
func (ic *ItemCreate) SetSyncChildItemsLocations(b bool) *ItemCreate {
ic.mutation.SetSyncChildItemsLocations(b)
return ic
}
// SetNillableSyncChildItemsLocations sets the "sync_child_items_locations" field if the given value is not nil.
func (ic *ItemCreate) SetNillableSyncChildItemsLocations(b *bool) *ItemCreate {
if b != nil {
ic.SetSyncChildItemsLocations(*b)
}
return ic
}
// SetSerialNumber sets the "serial_number" field.
func (ic *ItemCreate) SetSerialNumber(s string) *ItemCreate {
ic.mutation.SetSerialNumber(s)
@@ -538,6 +552,10 @@ func (ic *ItemCreate) defaults() {
v := item.DefaultAssetID
ic.mutation.SetAssetID(v)
}
if _, ok := ic.mutation.SyncChildItemsLocations(); !ok {
v := item.DefaultSyncChildItemsLocations
ic.mutation.SetSyncChildItemsLocations(v)
}
if _, ok := ic.mutation.LifetimeWarranty(); !ok {
v := item.DefaultLifetimeWarranty
ic.mutation.SetLifetimeWarranty(v)
@@ -599,6 +617,9 @@ func (ic *ItemCreate) check() error {
if _, ok := ic.mutation.AssetID(); !ok {
return &ValidationError{Name: "asset_id", err: errors.New(`ent: missing required field "Item.asset_id"`)}
}
if _, ok := ic.mutation.SyncChildItemsLocations(); !ok {
return &ValidationError{Name: "sync_child_items_locations", err: errors.New(`ent: missing required field "Item.sync_child_items_locations"`)}
}
if v, ok := ic.mutation.SerialNumber(); ok {
if err := item.SerialNumberValidator(v); err != nil {
return &ValidationError{Name: "serial_number", err: fmt.Errorf(`ent: validator failed for field "Item.serial_number": %w`, err)}
@@ -711,6 +732,10 @@ func (ic *ItemCreate) createSpec() (*Item, *sqlgraph.CreateSpec) {
_spec.SetField(item.FieldAssetID, field.TypeInt, value)
_node.AssetID = value
}
if value, ok := ic.mutation.SyncChildItemsLocations(); ok {
_spec.SetField(item.FieldSyncChildItemsLocations, field.TypeBool, value)
_node.SyncChildItemsLocations = value
}
if value, ok := ic.mutation.SerialNumber(); ok {
_spec.SetField(item.FieldSerialNumber, field.TypeString, value)
_node.SerialNumber = value

View File

@@ -0,0 +1,127 @@
package ent
import (
"entgo.io/ent/dialect/sql"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/item"
"github.com/sysadminsmedia/homebox/backend/internal/data/ent/predicate"
"github.com/sysadminsmedia/homebox/backend/pkgs/textutils"
)
// AccentInsensitiveContains creates a predicate that performs accent-insensitive text search.
// It normalizes both the database field value and the search value for comparison.
func AccentInsensitiveContains(field string, searchValue string) predicate.Item {
if searchValue == "" {
return predicate.Item(func(s *sql.Selector) {
// Return a predicate that never matches if search is empty
s.Where(sql.False())
})
}
// Normalize the search value
normalizedSearch := textutils.NormalizeSearchQuery(searchValue)
return predicate.Item(func(s *sql.Selector) {
dialect := s.Dialect()
switch dialect {
case "sqlite3":
// For SQLite, we'll create a custom normalization function using REPLACE
// to handle common accented characters
normalizeFunc := buildSQLiteNormalizeExpression(s.C(field))
s.Where(sql.ExprP(
"LOWER("+normalizeFunc+") LIKE ?",
"%"+normalizedSearch+"%",
))
case "postgres":
// For PostgreSQL, try to use unaccent extension if available
// Fall back to REPLACE-based normalization if not available
normalizeFunc := buildPostgreSQLNormalizeExpression(s.C(field))
s.Where(sql.ExprP(
"LOWER("+normalizeFunc+") LIKE ?",
"%"+normalizedSearch+"%",
))
default:
// Default fallback using REPLACE for common accented characters
normalizeFunc := buildGenericNormalizeExpression(s.C(field))
s.Where(sql.ExprP(
"LOWER("+normalizeFunc+") LIKE ?",
"%"+normalizedSearch+"%",
))
}
})
}
// buildSQLiteNormalizeExpression creates a SQLite expression to normalize accented characters
func buildSQLiteNormalizeExpression(fieldExpr string) string {
return buildGenericNormalizeExpression(fieldExpr)
}
// buildPostgreSQLNormalizeExpression creates a PostgreSQL expression to normalize accented characters
func buildPostgreSQLNormalizeExpression(fieldExpr string) string {
// Use a CASE statement to check if unaccent function exists before using it
// This prevents errors when the unaccent extension is not installed
return "CASE WHEN EXISTS (SELECT 1 FROM pg_proc WHERE proname = 'unaccent') " +
"THEN unaccent(" + fieldExpr + ") " +
"ELSE " + buildGenericNormalizeExpression(fieldExpr) + " END"
}
// buildGenericNormalizeExpression creates a database-agnostic expression to normalize common accented characters
func buildGenericNormalizeExpression(fieldExpr string) string {
// Chain REPLACE functions to handle the most common accented characters
// Focused on the most frequently used accents in Spanish, French, and Portuguese
// Ordered by frequency of use for better performance
normalized := fieldExpr
// Most common accented characters ordered by frequency
commonAccents := []struct {
from, to string
}{
// Spanish - most common
{"á", "a"}, {"é", "e"}, {"í", "i"}, {"ó", "o"}, {"ú", "u"}, {"ñ", "n"},
{"Á", "A"}, {"É", "E"}, {"Í", "I"}, {"Ó", "O"}, {"Ú", "U"}, {"Ñ", "N"},
// French - most common
{"è", "e"}, {"ê", "e"}, {"à", "a"}, {"ç", "c"},
{"È", "E"}, {"Ê", "E"}, {"À", "A"}, {"Ç", "C"},
// German umlauts and Portuguese - common
{"ä", "a"}, {"ö", "o"}, {"ü", "u"}, {"ã", "a"}, {"õ", "o"},
{"Ä", "A"}, {"Ö", "O"}, {"Ü", "U"}, {"Ã", "A"}, {"Õ", "O"},
}
for _, accent := range commonAccents {
normalized = "REPLACE(" + normalized + ", '" + accent.from + "', '" + accent.to + "')"
}
return normalized
}
// ItemNameAccentInsensitiveContains creates an accent-insensitive search predicate for the item name field.
func ItemNameAccentInsensitiveContains(value string) predicate.Item {
return AccentInsensitiveContains(item.FieldName, value)
}
// ItemDescriptionAccentInsensitiveContains creates an accent-insensitive search predicate for the item description field.
func ItemDescriptionAccentInsensitiveContains(value string) predicate.Item {
return AccentInsensitiveContains(item.FieldDescription, value)
}
// ItemSerialNumberAccentInsensitiveContains creates an accent-insensitive search predicate for the item serial number field.
func ItemSerialNumberAccentInsensitiveContains(value string) predicate.Item {
return AccentInsensitiveContains(item.FieldSerialNumber, value)
}
// ItemModelNumberAccentInsensitiveContains creates an accent-insensitive search predicate for the item model number field.
func ItemModelNumberAccentInsensitiveContains(value string) predicate.Item {
return AccentInsensitiveContains(item.FieldModelNumber, value)
}
// ItemManufacturerAccentInsensitiveContains creates an accent-insensitive search predicate for the item manufacturer field.
func ItemManufacturerAccentInsensitiveContains(value string) predicate.Item {
return AccentInsensitiveContains(item.FieldManufacturer, value)
}
// ItemNotesAccentInsensitiveContains creates an accent-insensitive search predicate for the item notes field.
func ItemNotesAccentInsensitiveContains(value string) predicate.Item {
return AccentInsensitiveContains(item.FieldNotes, value)
}

View File

@@ -0,0 +1,156 @@
package ent
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestBuildGenericNormalizeExpression(t *testing.T) {
tests := []struct {
name string
field string
expected string
}{
{
name: "Simple field name",
field: "name",
expected: "name", // Should be wrapped in many REPLACE functions
},
{
name: "Complex field name",
field: "description",
expected: "description",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := buildGenericNormalizeExpression(tt.field)
// Should contain the original field
assert.Contains(t, result, tt.field)
// Should contain REPLACE functions for accent normalization
assert.Contains(t, result, "REPLACE(")
// Should handle common accented characters
assert.Contains(t, result, "'á'", "Should handle Spanish á")
assert.Contains(t, result, "'é'", "Should handle Spanish é")
assert.Contains(t, result, "'ñ'", "Should handle Spanish ñ")
assert.Contains(t, result, "'ü'", "Should handle German ü")
// Should handle uppercase accents too
assert.Contains(t, result, "'Á'", "Should handle uppercase Spanish Á")
assert.Contains(t, result, "'É'", "Should handle uppercase Spanish É")
})
}
}
func TestSQLiteNormalizeExpression(t *testing.T) {
result := buildSQLiteNormalizeExpression("test_field")
// Should contain the field name and REPLACE functions
assert.Contains(t, result, "test_field")
assert.Contains(t, result, "REPLACE(")
// Check for some specific accent replacements (order doesn't matter)
assert.Contains(t, result, "'á'", "Should handle Spanish á")
assert.Contains(t, result, "'ó'", "Should handle Spanish ó")
}
func TestPostgreSQLNormalizeExpression(t *testing.T) {
result := buildPostgreSQLNormalizeExpression("test_field")
// Should contain unaccent function and CASE WHEN logic
assert.Contains(t, result, "unaccent(")
assert.Contains(t, result, "CASE WHEN EXISTS")
assert.Contains(t, result, "test_field")
}
func TestAccentInsensitivePredicateCreation(t *testing.T) {
tests := []struct {
name string
field string
searchValue string
description string
}{
{
name: "Normal search value",
field: "name",
searchValue: "electronica",
description: "Should create predicate for normal search",
},
{
name: "Accented search value",
field: "description",
searchValue: "electrónica",
description: "Should create predicate for accented search",
},
{
name: "Empty search value",
field: "name",
searchValue: "",
description: "Should handle empty search gracefully",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
predicate := AccentInsensitiveContains(tt.field, tt.searchValue)
assert.NotNil(t, predicate, tt.description)
})
}
}
func TestSpecificItemPredicates(t *testing.T) {
tests := []struct {
name string
predicateFunc func(string) interface{}
searchValue string
description string
}{
{
name: "ItemNameAccentInsensitiveContains",
predicateFunc: func(val string) interface{} { return ItemNameAccentInsensitiveContains(val) },
searchValue: "electronica",
description: "Should create accent-insensitive name search predicate",
},
{
name: "ItemDescriptionAccentInsensitiveContains",
predicateFunc: func(val string) interface{} { return ItemDescriptionAccentInsensitiveContains(val) },
searchValue: "descripcion",
description: "Should create accent-insensitive description search predicate",
},
{
name: "ItemManufacturerAccentInsensitiveContains",
predicateFunc: func(val string) interface{} { return ItemManufacturerAccentInsensitiveContains(val) },
searchValue: "compañia",
description: "Should create accent-insensitive manufacturer search predicate",
},
{
name: "ItemSerialNumberAccentInsensitiveContains",
predicateFunc: func(val string) interface{} { return ItemSerialNumberAccentInsensitiveContains(val) },
searchValue: "sn123",
description: "Should create accent-insensitive serial number search predicate",
},
{
name: "ItemModelNumberAccentInsensitiveContains",
predicateFunc: func(val string) interface{} { return ItemModelNumberAccentInsensitiveContains(val) },
searchValue: "model456",
description: "Should create accent-insensitive model number search predicate",
},
{
name: "ItemNotesAccentInsensitiveContains",
predicateFunc: func(val string) interface{} { return ItemNotesAccentInsensitiveContains(val) },
searchValue: "notas importantes",
description: "Should create accent-insensitive notes search predicate",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
predicate := tt.predicateFunc(tt.searchValue)
assert.NotNil(t, predicate, tt.description)
})
}
}

View File

@@ -185,6 +185,20 @@ func (iu *ItemUpdate) AddAssetID(i int) *ItemUpdate {
return iu
}
// SetSyncChildItemsLocations sets the "sync_child_items_locations" field.
func (iu *ItemUpdate) SetSyncChildItemsLocations(b bool) *ItemUpdate {
iu.mutation.SetSyncChildItemsLocations(b)
return iu
}
// SetNillableSyncChildItemsLocations sets the "sync_child_items_locations" field if the given value is not nil.
func (iu *ItemUpdate) SetNillableSyncChildItemsLocations(b *bool) *ItemUpdate {
if b != nil {
iu.SetSyncChildItemsLocations(*b)
}
return iu
}
// SetSerialNumber sets the "serial_number" field.
func (iu *ItemUpdate) SetSerialNumber(s string) *ItemUpdate {
iu.mutation.SetSerialNumber(s)
@@ -836,6 +850,9 @@ func (iu *ItemUpdate) sqlSave(ctx context.Context) (n int, err error) {
if value, ok := iu.mutation.AddedAssetID(); ok {
_spec.AddField(item.FieldAssetID, field.TypeInt, value)
}
if value, ok := iu.mutation.SyncChildItemsLocations(); ok {
_spec.SetField(item.FieldSyncChildItemsLocations, field.TypeBool, value)
}
if value, ok := iu.mutation.SerialNumber(); ok {
_spec.SetField(item.FieldSerialNumber, field.TypeString, value)
}
@@ -1393,6 +1410,20 @@ func (iuo *ItemUpdateOne) AddAssetID(i int) *ItemUpdateOne {
return iuo
}
// SetSyncChildItemsLocations sets the "sync_child_items_locations" field.
func (iuo *ItemUpdateOne) SetSyncChildItemsLocations(b bool) *ItemUpdateOne {
iuo.mutation.SetSyncChildItemsLocations(b)
return iuo
}
// SetNillableSyncChildItemsLocations sets the "sync_child_items_locations" field if the given value is not nil.
func (iuo *ItemUpdateOne) SetNillableSyncChildItemsLocations(b *bool) *ItemUpdateOne {
if b != nil {
iuo.SetSyncChildItemsLocations(*b)
}
return iuo
}
// SetSerialNumber sets the "serial_number" field.
func (iuo *ItemUpdateOne) SetSerialNumber(s string) *ItemUpdateOne {
iuo.mutation.SetSerialNumber(s)
@@ -2074,6 +2105,9 @@ func (iuo *ItemUpdateOne) sqlSave(ctx context.Context) (_node *Item, err error)
if value, ok := iuo.mutation.AddedAssetID(); ok {
_spec.AddField(item.FieldAssetID, field.TypeInt, value)
}
if value, ok := iuo.mutation.SyncChildItemsLocations(); ok {
_spec.SetField(item.FieldSyncChildItemsLocations, field.TypeBool, value)
}
if value, ok := iuo.mutation.SerialNumber(); ok {
_spec.SetField(item.FieldSerialNumber, field.TypeString, value)
}

View File

@@ -13,10 +13,13 @@ var (
{Name: "id", Type: field.TypeUUID},
{Name: "created_at", Type: field.TypeTime},
{Name: "updated_at", Type: field.TypeTime},
{Name: "type", Type: field.TypeEnum, Enums: []string{"photo", "manual", "warranty", "attachment", "receipt"}, Default: "attachment"},
{Name: "type", Type: field.TypeEnum, Enums: []string{"photo", "manual", "warranty", "attachment", "receipt", "thumbnail"}, Default: "attachment"},
{Name: "primary", Type: field.TypeBool, Default: false},
{Name: "document_attachments", Type: field.TypeUUID},
{Name: "item_attachments", Type: field.TypeUUID},
{Name: "title", Type: field.TypeString, Default: ""},
{Name: "path", Type: field.TypeString, Default: ""},
{Name: "mime_type", Type: field.TypeString, Default: "application/octet-stream"},
{Name: "attachment_thumbnail", Type: field.TypeUUID, Unique: true, Nullable: true},
{Name: "item_attachments", Type: field.TypeUUID, Nullable: true},
}
// AttachmentsTable holds the schema information for the "attachments" table.
AttachmentsTable = &schema.Table{
@@ -25,14 +28,14 @@ var (
PrimaryKey: []*schema.Column{AttachmentsColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "attachments_documents_attachments",
Columns: []*schema.Column{AttachmentsColumns[5]},
RefColumns: []*schema.Column{DocumentsColumns[0]},
OnDelete: schema.Cascade,
Symbol: "attachments_attachments_thumbnail",
Columns: []*schema.Column{AttachmentsColumns[8]},
RefColumns: []*schema.Column{AttachmentsColumns[0]},
OnDelete: schema.SetNull,
},
{
Symbol: "attachments_items_attachments",
Columns: []*schema.Column{AttachmentsColumns[6]},
Columns: []*schema.Column{AttachmentsColumns[9]},
RefColumns: []*schema.Column{ItemsColumns[0]},
OnDelete: schema.Cascade,
},
@@ -88,29 +91,6 @@ var (
},
},
}
// DocumentsColumns holds the columns for the "documents" table.
DocumentsColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID},
{Name: "created_at", Type: field.TypeTime},
{Name: "updated_at", Type: field.TypeTime},
{Name: "title", Type: field.TypeString, Size: 255},
{Name: "path", Type: field.TypeString, Size: 500},
{Name: "group_documents", Type: field.TypeUUID},
}
// DocumentsTable holds the schema information for the "documents" table.
DocumentsTable = &schema.Table{
Name: "documents",
Columns: DocumentsColumns,
PrimaryKey: []*schema.Column{DocumentsColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "documents_groups_documents",
Columns: []*schema.Column{DocumentsColumns[5]},
RefColumns: []*schema.Column{GroupsColumns[0]},
OnDelete: schema.Cascade,
},
},
}
// GroupsColumns holds the columns for the "groups" table.
GroupsColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID},
@@ -162,6 +142,7 @@ var (
{Name: "insured", Type: field.TypeBool, Default: false},
{Name: "archived", Type: field.TypeBool, Default: false},
{Name: "asset_id", Type: field.TypeInt, Default: 0},
{Name: "sync_child_items_locations", Type: field.TypeBool, Default: false},
{Name: "serial_number", Type: field.TypeString, Nullable: true, Size: 255},
{Name: "model_number", Type: field.TypeString, Nullable: true, Size: 255},
{Name: "manufacturer", Type: field.TypeString, Nullable: true, Size: 255},
@@ -187,19 +168,19 @@ var (
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "items_groups_items",
Columns: []*schema.Column{ItemsColumns[24]},
Columns: []*schema.Column{ItemsColumns[25]},
RefColumns: []*schema.Column{GroupsColumns[0]},
OnDelete: schema.Cascade,
},
{
Symbol: "items_items_children",
Columns: []*schema.Column{ItemsColumns[25]},
Columns: []*schema.Column{ItemsColumns[26]},
RefColumns: []*schema.Column{ItemsColumns[0]},
OnDelete: schema.SetNull,
},
{
Symbol: "items_locations_items",
Columns: []*schema.Column{ItemsColumns[26]},
Columns: []*schema.Column{ItemsColumns[27]},
RefColumns: []*schema.Column{LocationsColumns[0]},
OnDelete: schema.Cascade,
},
@@ -213,17 +194,17 @@ var (
{
Name: "item_manufacturer",
Unique: false,
Columns: []*schema.Column{ItemsColumns[13]},
Columns: []*schema.Column{ItemsColumns[14]},
},
{
Name: "item_model_number",
Unique: false,
Columns: []*schema.Column{ItemsColumns[12]},
Columns: []*schema.Column{ItemsColumns[13]},
},
{
Name: "item_serial_number",
Unique: false,
Columns: []*schema.Column{ItemsColumns[11]},
Columns: []*schema.Column{ItemsColumns[12]},
},
{
Name: "item_archived",
@@ -456,7 +437,6 @@ var (
AttachmentsTable,
AuthRolesTable,
AuthTokensTable,
DocumentsTable,
GroupsTable,
GroupInvitationTokensTable,
ItemsTable,
@@ -471,11 +451,10 @@ var (
)
func init() {
AttachmentsTable.ForeignKeys[0].RefTable = DocumentsTable
AttachmentsTable.ForeignKeys[0].RefTable = AttachmentsTable
AttachmentsTable.ForeignKeys[1].RefTable = ItemsTable
AuthRolesTable.ForeignKeys[0].RefTable = AuthTokensTable
AuthTokensTable.ForeignKeys[0].RefTable = UsersTable
DocumentsTable.ForeignKeys[0].RefTable = GroupsTable
GroupInvitationTokensTable.ForeignKeys[0].RefTable = GroupsTable
ItemsTable.ForeignKeys[0].RefTable = GroupsTable
ItemsTable.ForeignKeys[1].RefTable = ItemsTable

Some files were not shown because too many files have changed in this diff Show More