- fix(studio): stop markBatchDone infinite recursion so batches complete
- refactor(api): merge api-response into api and drop the duplicate module
- refactor(media): extract shared media loader and URL validator
- refactor(ui): extract shared LoadingSpinner for site and admin groups
- refactor(dates): consolidate raw date formatting into formatDate util
- refactor(logs): share a single generic log-list loader across tables
- refactor(theme): merge both ColorField components and reuse contrast helpers
- refactor(import): extract shared ImportErrorBanner and SearchInput
- chore(): remove dead theme-editor-tabs after inlining tab components
- New buildDutchLanguage() function translates only 'nl' language
- Proper error handling with specific messages for network errors
- Safe template literal usage, guarded .find() for Dutch language
- Consistent with existing buildAllLanguages pattern
Remove unused admin-helpers.test.ts (dead code)
- Add retries for furnidata fetch (3 attempts, 1s delay)
- Better error messages for user (distinguish 502/400/other)
- Client-side: show detailed error from SSE stream when available
- Remove unused admin-helpers.test.ts
The flush after every 400-item chunk was running expensive operations
(reconcileOfferIds, rebuildCatalog, verifySpriteIds, rcon updates) which
caused the import to hang after ~800 items. Now only the final chunk
triggers the full consolidation. Also raised the per-request limit from
500 to 5000 items.
- Add 'Clone all missing' button for clone sources with confirmation dialog
- Show per-item status badges: nitro, furnidata, catalog entry
- Add status filters: missing furnidata, missing catalog entry
- Add ETA and percentage to batch progress bar
- Add retry button for failed items after batch import
- Auto-translate all languages after clone-all completes
- Fix statusFilter 'all' bug that incorrectly filtered imported items
- Bulk-load FurnitureData + catalog references for O(1) per-item checks
Wrap next/link in a shared Link component that ships prefetch=false by
default, so no route is ever prefetched (viewport or hover) anymore, and
drop the DNS prefetch hint. Removes hidden background requests that were
the source of intermittent issues.
The maintenance "Fix alles" now has a checkbox to include or skip the
duplicate catalog_pages merge, so admins can choose whether to run it.
removeDuplicates takes an includePages flag and fixEverything threads it
through to the action.
Furni imports can now choose whether to translate (per import) and which
languages to build, instead of always rebuilding all 13 FurnitureData_<lang>
files. The studio header also has a global switch that persists the
furnidata_translate_enabled setting, seeding the per-import default.
The maintenance "Fix alles" now collapses catalog_pages that share the same
caption_save + parent_id into a single survivor (moving catalog_items and
reparenting child pages before deleting duplicates), so the catalog tree
never renders double links. The duplicate-page count is also surfaced in the
health panel.
- Move /admin/import/* tools under /admin/studio/* and add studio nav, layout and tabs
- Add shared catalog maintenance panel plus a /admin/studio/maintenance tab
- Make furnidata reconciliation overwrite conflicting entries with the
DB-authoritative items_base classname/id (surfaced via fixedConflicts)
- Add furnidata_translate_enabled setting to skip the heavy localized
furnidata build during import (manual build-languages still forces it)
- Update staff smoke contract test for the studio hub
- Add EMULATOR_MODE=api option with HTTP transport mirroring RCON payload
- buildLocalizedFurniDataFiles now falls back to LibreTranslate for customs (incl. pl/ru/ar/ja)
- Remove Organiseer import button from studio and Reorganize Catalog from import page
- Delete organize API route and PUT handler; remove organizeCatalogAll from catalog-repair.ts
- Increase imported-furni list perPage from 50 to 500
organizeCatalogAll no longer pulls every items_base row into the catalog.
It now touches only items whose catalog entry lives on a page under the
Imported Furniture parent (re-homing/re-pricing onto line/category
sub-pages). Items are never newly added. Button renamed to 'Organiseer
import'.
Add a fully automatic "Organize all" action in the Studio that organizes
the entire database into catalog pages:
- Create a dedicated sub-page per furniture line (e.g. weebz, habbox) from
FurnitureData.json, falling back to the auto-detected category.
- Add missing purchasable items to the catalog on their line/category page.
- Re-home and re-price existing catalog entries onto their correct page.
- Pages are created automatically when missing; no manual selection needed.
Includes the organizeCatalogAll service, a POST /api/admin/import/furni/organize
endpoint, and the Studio button.
- Add /api/admin/import/furni?action=live-reconcile POST endpoint that reconciles FurnitureData.json with items_base without triggering RCON hotel reload
- Add 'notImported' status filter in studio to show all non-imported furniture items
- Useful for verifying imports and seeing what's missing after furniture import