Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bba45a1
Dump version 2.4.0
devpro Jul 19, 2026
62d4010
Add import books from amazon
devpro Jul 19, 2026
b497232
Add notes in books
devpro Jul 19, 2026
a935300
Add other types from amazon order file
devpro Jul 19, 2026
dbef502
Remove peristentstate from tv show detail page
devpro Jul 19, 2026
54130a3
Add ASIN in amazon imported items
devpro Jul 19, 2026
306127e
Implemented "Cover image URL" (CustomImageUrl) override for VideoGame…
devpro Jul 19, 2026
46f119f
Generic video game transaction import (PSN import)
devpro Jul 21, 2026
954cbf7
Add optional cover image URL to Car, House, and HealthProfile
devpro Jul 22, 2026
eb74ee8
Persist the selected tab on Watch Next and Wishlist in the URL
devpro Jul 22, 2026
33ff35a
Add ProductName to the shared OwnedVersionModel (Movie/TvShow/Book/Al…
devpro Jul 22, 2026
655f290
Add Collectible and Gear trackable item types
devpro Jul 22, 2026
7daf97f
Fix Collectible/Gear DI crash and rework cover image display
devpro Jul 22, 2026
2afead7
Use wide list thumbnails and a consistent separate banner card everyw…
devpro Jul 22, 2026
ba97320
UI fixes and new tests
devpro Jul 22, 2026
d57e708
Improve google books api calls
devpro Jul 22, 2026
ba4cfba
Add gear and collectible in amazon import
devpro Jul 22, 2026
ebf5061
Add reference unlink feature for admin
devpro Jul 22, 2026
cf94ca0
Add link to book ref
devpro Jul 23, 2026
764875f
Removing samples/angular folder
devpro Jul 23, 2026
6ffd0d5
Add Amazon product link
devpro Jul 23, 2026
4e86b6f
Remove the semicolon from comments
devpro Jul 23, 2026
269ce82
Fix Sonar findings: validation loops, string literals, nested ternari…
devpro Jul 23, 2026
031fe91
Improve amazon import on video game
devpro Jul 23, 2026
05ff55f
Improve image display for gear and collectible
devpro Jul 23, 2026
6af00b5
Fix tests
devpro Jul 23, 2026
3ae127f
Fix Author/Artist fields reverting after being cleared on Book/Album
devpro Jul 23, 2026
63bebaf
Add gear category
devpro Jul 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,48 @@ Existing data needs the one-off `scripts/migrate-is-owned-to-owned-versions.js`
then a `scripts/mongodb-create-index.js` re-run to replace the old `is_owned` index definitions.
Covered by the resource tests' owned-filter cases (including a full decimal/date round-trip in `MovieResourceTest`/`AlbumResourceTest`) and `OwnershipSmokeTest` (Playwright, end-to-end through the editor).

`VideoGamePlatformModel.ProductName` (free text) is the store's own specific product/edition text for that copy (e.g. "Grand Theft Auto V : Édition Premium"), distinct from the game's own `Title` -
added for the generic video game transaction import below, but it's a plain field on the shared model/entity/DTO, editable on `VideoGameDetail.razor` like any other copy detail regardless of how the platform entry was created.
It renders via a new `ExtraFields` render-fragment slot on the shared `OwnedVersionFields` component (`Components/Inventory/Shared/`), not by adding it to `IOwnedCopyDto`:
Movie/TvShow/Book/Album's `OwnedVersionDto` has no equivalent concept, so the interface every `OwnedVersionFields` caller shares stays free of a field only one of them needs.
The component's own Price/Acquired/Vendor/Reference columns switched from a fixed `col-md-3` to an unnumbered `col-md` (Bootstrap's equal-width auto layout) for this -
with no `ExtraFields` supplied they still fill one row identically to the old fixed split,
but a 5th `ExtraFields` column (VideoGame's Product field) joins the same row and every column re-shares the width automatically instead of wrapping to a second row on desktop,
while `col-6` still stacks two-per-row on mobile like the others.

### Bulk store/retailer transaction imports (Amazon, generic video game transactions)

`AmazonImportController`/`AmazonOrderPreviewService` (preview an uploaded order-history CSV, let the user pick a type and edit fields per row, then commit) was the first of this shape,
followed by `GenericVideoGameImportController`/`GenericVideoGameImportService` for a video-game-only transaction-history CSV (PSN's own GDPR export today; the format isn't PlayStation-specific -
`Vendor` is a per-row column, not hardcoded - so any store exporting the same shape would work).
Both follow `WatchNextController`/`WishlistController`'s split (controller in `Controllers/`, pure parsing/computation in `Domain/Services/`), not the older `WebApi/Import/` feature-folder shape.
The create/merge/dedup engine behind both (`ComputeCommitPlan`/`FindImportedReferences`, matching by normalized title via `TitleNormalizer`,
merging within the same commit batch too) started out Amazon-only (`AmazonImportMergeService`) but was already fully generic - it moved to `Domain/Services/OwnedItemImportMergeService.cs`
(and its return type to `Domain/Models/ImportCommitPlan.cs`, renamed off `AmazonImportPlan<TModel>`) once the video game importer needed the exact same engine, rather than duplicating it.
`AmazonImportMergeService` kept only what's genuinely Amazon-specific: `FormatOrderReference` (ASIN + order id) and `BuildAmazonProvenanceNotes`.

**Gotcha, confirmed against a real PSN export:** a transaction/order id pair is *not* reliably unique per line the way Amazon's ASIN is.
A single PSN transaction can bundle several different products under one shared Transaction Id/Order Id (confirmed with a real export:
one transaction contained three separate "Far Cry 4" DLC packs, each its own CSV line, distinguishable only by Product Name).
`GenericVideoGameImportService.FormatReference` originally built the owned-copy `Reference` (and dedup key) from transaction id + order id alone,
the same class of bug `AmazonImportMergeService.FormatOrderReference` already avoids by including the ASIN -
without a per-product disambiguator, the second and third bundled lines collided with the first's reference and were silently skipped as "already imported" duplicates,
so only 1 of the 3 platform entries actually got created from a 3-line selection.
Fixed by appending the row's own Product Name (falling back to the title when blank) to the reference text, mirroring the ASIN's role for Amazon.
`GenericVideoGameImportPreviewRow.RowId` had the identical problem (plain `TransactionId`, colliding across the same bundled lines) and got the same fix.
Covered by `GenericVideoGameImportServiceTest.FormatReference_Disambiguates_WhenTwoLinesShareTheSameTransactionAndOrder`
and `GenericVideoGameImportResourceTest.PreviewThenCommit_ImportsAllThreeLines_WhenTheyShareOneTransactionAndOrderButDifferentProducts`.

**`VideoGamesCreated`/`VideoGamesMergedInto` count distinct video games, not selected rows - this undercounts rows on purpose, not a bug.**
Several selected rows sharing a normalized title consolidate into one item within a single commit batch (`ComputeCommitPlan`'s existing same-batch-merge behavior),
which is correct but means `Created + MergedInto` can come out lower than the number of rows the user selected,
which read as a discrepancy on first use of the real 104-row PSN export (98 selected, "1 created, 0 merged, 2 already imported" summed to only 3 - actually the *bundling* bug above,
but the created/merged-vs-selected gap is real and independent of it).
`ImportCommitPlan<TModel>.OwnedCopiesAdded`/`GenericVideoGameImportCommitResultDto.RowsImported` is the true per-row count (`RowsImported + VideoGamesSkipped` always equals the number of rows submitted),
and `SkippedRowTitles` lists exactly which selected rows were skipped as already-imported duplicates -
together they let `GenericVideoGameImportPage.razor` show a reconciling "X of Y selected rows imported" line plus a named list of anything actually skipped,
so the user can trust nothing was silently dropped instead of having to guess from the per-item counts alone.

### Child entities (1-to-many owned by another entity)

`CarHistory` (owned by `Car`) and `Episode` (owned by `TvShow`) are separate top-level collections referencing their parent by id (`car_id`, `tv_show_id`), not embedded arrays.
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<PropertyGroup>
<!-- edit this value to change the current MAJOR.MINOR.PATCH version -->
<VersionPrefix>2.3.0</VersionPrefix>
<VersionPrefix>2.4.0</VersionPrefix>
</PropertyGroup>

<Choose>
Expand Down
8 changes: 8 additions & 0 deletions docs/prerender-flash-fix.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ Two real options, and I have a clear preference:
The detail pages persist a single bounded DTO and are fine to keep as-is.
2. Raise the limit via .AddHubOptions(o => o.MaximumReceiveMessageSize = 256 * 1024) — one line, keeps the no-refetch behavior, but the payload still grows with your collection and the cliff just moves further out.

**Update**: "the detail pages persist a single bounded DTO" turned out not to hold for TvShowDetail.
`TvShowReferenceModel.Episodes` is embedded (see CLAUDE.md's "Reference data" section) and unbounded per show,
so `[PersistentState]`-serializing `Reference` plus the raw `Episodes` list hit the exact same 32 KB SignalR ceiling for shows with many seasons/episodes.
`[PersistentState]` was reverted from `TvShowDetail.razor`
(back to plain private fields `_show`/`_reference`/`_episodes`, `OnParametersSetAsync` always calls `LoadAsync`, no restore-skip path) for the same reason it was dropped from Watch Next/Wishlist above.
The `_loaded`/`_loading` flash fix from "Fix loading flash" stays — it isn't part of the persisted-state mechanism and never caused this issue.
Movie/Book/Album/VideoGame/Car/House/HealthProfile/Playlist detail pages keep `[PersistentState]` since their persisted DTOs stay genuinely bounded (no embedded unbounded list like `Episodes`).

Sources:
[dotnet/aspnetcore#65101](https://github.com/dotnet/aspnetcore/issues/65101),
[Blazor SignalR guidance — message size](https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/signalr),
Expand Down
14 changes: 0 additions & 14 deletions samples/angular/.editorconfig

This file was deleted.

57 changes: 0 additions & 57 deletions samples/angular/.eslintrc.json

This file was deleted.

55 changes: 0 additions & 55 deletions samples/angular/.gitignore

This file was deleted.

66 changes: 0 additions & 66 deletions samples/angular/README.md

This file was deleted.

Loading
Loading