GH-64 feat: Admin GUI for parcel, locker & user management#218
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
- ParcelRepository#findPage(Page): CompletableFuture<PageResult<Parcel>> - ParcelRepositoryOrmLite#findPage: delegates to queryPage with identity builder - ParcelService#getAll(Page): CompletableFuture<PageResult<Parcel>> - ParcelServiceImpl#getAll: calls findPage, warms parcelsByUuid cache - GuiManager#getAllParcels(Page): delegates to parcelService.getAll - ParcelFindPageIntegrationTest: TDD test (skipped without Docker) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
…last-page termination Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
…y/destination invariants Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
…its) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
…BORT Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
…n delete dialogs Final-review fixes: - ParcelServiceImpl.delete(UUID)/deleteAll now also delete the parcel's ParcelContent rows, mirroring the collect/rollback cleanup paths. The admin delete and delete-all buttons previously orphaned content rows (an unbounded leak now that deletion is a one-click bulk operation). - AdminParcelEditGui/AdminLockerEditGui escape player-set parcel/locker names with MiniMessage.escapeTags before interpolating them into delete-confirmation dialog titles, closing a markup-injection vector (Dialog click events execute with the clicking admin's permissions). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive in-game Admin GUI for managing parcels, lockers, and users, backed by a new AdminParcelService and a refactored ParcelSendTask to prevent stale-snapshot overwrites. Feedback focuses on critical thread-safety violations in Bukkit, specifically firing events asynchronously in ParcelSendTask, handling callbacks asynchronously in AdminParcelEditGui, and populating GUI items asynchronously in AdminDestinationPickerGui. Additionally, the reviewer noted that the ability to view sent parcels is currently inaccessible due to showSent being hardcoded to false in AdminUserListGui.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Addresses PR review (gemini-code-assist): AdminUserInspectGui already had a showSent code path (getParcelsBySender) but it was unreachable — AdminUserListGui hardcoded showSent=false and there was no in-GUI control. The design doc requires inspecting a user's received AND sent parcels, so add a toggle button (slot 48) that flips the mode and reopens, backed by a new configurable adminToggleSentReceivedButton item. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmSMZXMtfG9F2HBtrPXU16
Review triage (gemini-code-assist)Thanks for the review. Verified each finding against the actual runtime threading model and the codebase; decisions below. ❌ Rejected —
|
|
Thanks for the detailed breakdown and verification, Jakubk15. Your analysis regarding the asynchronous nature of the Bukkit event and the thread-safety of the |
|
@claude review |
Closes #64.
Summary
Adds an Admin GUI (
/parcellockers admin, gated by the existingparcellockers.adminpermission) for full in-game management of parcels, lockers, and users, plus bulk actions.Text input and confirmations use the Paper Dialog API.
Safety invariants (per the feature requirements)
AdminParcelService#changeSizerejects a size change if the parcel's existing contents wouldn't fit the smaller capacity (SMALL=9 / MEDIUM=18 / LARGE=27 slots). The GUI routes every size change through the service; there is no direct-write path.create).In-transit parcel safety
ParcelSendTaskwas refactored to re-fetch parcel + delivery state at fire time (puredecide(...)→ DELIVER / RESCHEDULE / ABORT) instead of acting on the snapshot captured at schedule time, so admin edits to an in-transit parcel are honored rather than clobbered. The ABORT path cleans up and logs stray-delivery deletion failures.Supporting changes
LockerRepository#update+LockerManager#rename,ParcelContentRepository#update+ParcelContentManager#update,DeliveryRepository#update+DeliveryManager#update,ParcelRepository#findPage+ParcelService#getAll.GuiSettingsfields and 11 newAdminMessagesnotices (all user-facing text viaMessageConfig).Review fixes (from final whole-branch review)
ParcelService.delete/deleteAllnow also delete the parcel'sParcelContentrows (mirroring the collect/rollback cleanup), closing an orphaned-row leak that the new one-click delete/delete-all buttons would otherwise have made reachable at scale.escapeTags-escaped before interpolation into delete-confirmation dialog titles, closing a markup-injection vector (Dialog click events execute with the clicking admin's permissions).Testing
AdminParcelServiceTest— size-fit/capacity, priority delta-shift direction & now-clamp.ParcelSendTaskTest—decide(...)totality across parcel/delivery/time combinations.ParcelFindPageIntegrationTest,ParcelContentUpdateIntegrationTest(Testcontainers/MySQL, auto-skipped without Docker)../gradlew compileJava,./gradlew test, and./gradlew shadowJarall BUILD SUCCESSFUL.Known follow-ups (non-blocking, tracked in review notes)
🤖 Generated with Claude Code