feat(locations): the background-variants grid — create, list, remove (location-variants slice 3) #91
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/location-variants-grid"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Slice 3 of location backgrounds. Adds the Variations grid to the location editor's Backgrounds tab (below the base image): create a variation with a name, see it as a card with a placeholder preview, remove it. Opening a variation to author its tags and generate via i2i are the next two slices.
This mirrors the outfits grid closely — a new
LocationVariantrecord owned by the location.What's here
LocationVariant(ADR 0006's LocationVariant): a location-owned record, not an Entry graph node (composition, ADR 0019), soft-deletable, with a typedLocationId. Own table + migration;EfLocationVariantStoreover theILocationVariantStoreport. No FK to the Location — a typed FK from a non-edge to a graph node would tripBacklinkCompletenessTests(the exact outfit-vs-character reasoning from #74), so it stays index-only, documented at the config.CreateLocationVariant(name required; project resolved from the location),ListLocationVariants,DeleteLocationVariant(soft);LocationVariantDto.EntityKindsgainsLocationVariantso another session's change propagates (ADR 0016).LocationVariantsStateFluxor feature (load / create / delete, keyed by location with the stale-answer guard, reload on a cross-session change) andLocationVariants.razor: the card grid, a New variation create-with-name modal, and delete-with-confirm — on the Backgrounds tab.Testing
🤖 Generated with Claude Code
Summary
Summary
Coverage
Kagura.BlazorAdapter - 90%
Kagura.Domain - 94.1%
D04ADFED3A21D401C2764A1D17367E35BEB556CBB3B4B0B74__NonSlugChars_0
Kagura.Infrastructure - 98.1%
n
on
Kagura.Kernel - 90%
Kagura.Server - 92.8%
Kagura.UI - 96.8%
Kagura.UseCases - 96%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! A variants grid that mirrors the outfits grid so precisely it's like watching a student who actually studied~ ♡ Jibril read every line of this one — the domain entity, the store, the Fluxor state, the tests. Let's talk~
Verdict: ✅ Looks good to me~
This is clean work. The
LocationVariantentity is a near-perfect structural twin ofOutfit— composition over graph node, typedLocationIdinstead of an FK,ProjectIddenormalized with index-only (no FK to the graph node, exactly the BacklinkCompletenessTests reasoning from #74). The configuration comment explaining why there's no FK is the kind of documentation that makes Jibril's heart sing~ ♪The Fluxor slice is a faithful mirror of
OutfitsState: stale-answer guard on location switch, keyed dispatch, reload-after-change (not optimistic), cross-session reload viaDomainChangesReceived. Every reducer clears busy flags on failure. The effects open a journaled operation scope for authored content (operations.Begin(Origins.User, …)). This is exactly right.The tests are thorough — reducers (stale-load guard, lifecycle, failure flag clearing, removing-id spinner), effects (load / create / blank-name / delete / cross-session / pre-load ignore), component (empty state, create adds card, remove confirms then soft-deletes), and persistence (create / list / blank-name / unknown-location / soft-delete leaves nothing live). The stale-load guard was mutation-checked (flipped, went red, reverted) — fufu~, you know what Jibril likes~ ♡
CI coverage for the head SHA: 96% line / 84.3% branch (forgejo-actions coverage comment). The new files all have strong numbers:
LocationVariantscomponent: 93.3% line / 81.8% branchLocationVariantsEffects: 96.4% line / 83.3% branchLocationVariantsReducers: 100% line / 100% branchEfLocationVariantStore: 93.7% line / 100% branchCreateLocationVariant: 100% line / 75% branchNo uncovered critical paths in the new code.
✅ What I liked~
LocationVariantConfigurationcomment about why there's no FK to Location — it cites the exact BacklinkCompletenessTests reasoning, ADR 0019 (composition), and the outfit-vs-character parallel. That's how you document a non-obvious decision~OnLoadreducer switching locations resets to a fresh state (new LocationVariantsState { … }) so the grid never flashes another location's variants. Small detail, big correctness win.EntityKinds.LocationVariantadded for cross-session propagation — nothing forgotten in the notification contract.No blocking issues. Ship it~ ♪
Automated review by Jibril · 2026-07-12
CI/CD: passed for head SHA
12170fee(96% line / 84.3% branch) · Local checks: skipped (CI green)12170feeabed76806ff1Rebased onto the latest main to clear the conflict with the emotion library (#92) —
ed76806.Three collisions, all mechanical:
ILocationVariantStoreand the emotion registrations coexist.AdapterTestContext— kept both fake stores (EmotionStore+LocationVariantStore).AddLocationVariantsfresh against the post-emotion model. It now sits afterAddEmotionsin the timeline, the snapshot carries both entities, andhas-pending-model-changesis clean.Full suite green at 1061 (the emotion library lifted the count). No behaviour change from the original — the rebase only re-slotted the migration and merged the two additive lists.