bud panels duplicate-add guard: server-side already_present flag + client-side error Brief w. FYI flash highlight on the existing entry — for each of the three #id_bud_btn panels (My Buds / post-share / gatekeeper-invite), the JSON response from add_bud / share_post / invite_gamer now carries {already_present, recipient_display, recipient_user_id}; bud-btn.js branches on already_present → calls new Brief.showDuplicateBanner({display_name, target_selector}) instead of the normal onSuccess append; banner title reads @<username> is already present, NVM dismisses, FYI dismisses AND eases in the .bud-duplicate-flash class (color: var(--terUser); text-shadow: 0 0 .5em var(--ninUser); transition: 600ms) onto the existing element (.bud-entry .bud-name / .post-recipient[data-user-id=…] / .gate-slot.filled[data-user-id=…]); gatekeeper "already present" = recipient is either GateSlot.FILLED + gamer OR has TableSeat OR has a pending RoomInvite (highlight target only set when seated — pending invites have no visible slot); .post-recipient chips + .gate-slot.filled cells gain data-user-id so the FYI selector can find them; my_buds.html now loads note.js via the {% block scripts %} pattern (Brief module is required by the duplicate banner path); bonus: latent test_jasmine.py bug fixed — "0 failures" in result.text matched "10 failures" / "20 failures" / etc, silently passing up to 99 failed specs; replaced w. re.search(r"(?<!\d)0 failures\b", …) (caught my new red specs, would've caught any prior Jasmine regression); 18 new ITs + 10 new Jasmine specs + 3 new FTs (one per panel) — TDD
Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -392,12 +392,16 @@ def share_post(request, post_id):
|
||||
# list exposes; doesn't widen the privacy surface beyond what the
|
||||
# post detail page already shows publicly.
|
||||
recipient_display = None
|
||||
recipient_user_id = None
|
||||
if recipient is not None:
|
||||
recipient_display = recipient.username or recipient.email
|
||||
recipient_user_id = str(recipient.id)
|
||||
return JsonResponse({
|
||||
"brief": brief.to_banner_dict() if brief is not None else None,
|
||||
"line_text": line_text,
|
||||
"recipient_display": recipient_display,
|
||||
"recipient_user_id": recipient_user_id,
|
||||
"already_present": is_reshare,
|
||||
})
|
||||
|
||||
messages.success(request, "An invite has been sent if that address is registered.")
|
||||
@@ -446,16 +450,28 @@ def add_bud(request):
|
||||
candidate = _resolve_recipient(request.POST.get("recipient"))
|
||||
|
||||
bud = None
|
||||
already_present = False
|
||||
recipient_display = None
|
||||
recipient_user_id = None
|
||||
if candidate is not None and candidate != request.user:
|
||||
if candidate not in request.user.buds.all():
|
||||
already_present = candidate in request.user.buds.all()
|
||||
if not already_present:
|
||||
request.user.buds.add(candidate)
|
||||
display = candidate.username or candidate.email
|
||||
bud = {
|
||||
"id": str(candidate.id),
|
||||
"username": candidate.username or candidate.email,
|
||||
"username": display,
|
||||
"email": candidate.email,
|
||||
}
|
||||
recipient_display = display
|
||||
recipient_user_id = str(candidate.id)
|
||||
|
||||
return JsonResponse({"bud": bud})
|
||||
return JsonResponse({
|
||||
"bud": bud,
|
||||
"already_present": already_present,
|
||||
"recipient_display": recipient_display,
|
||||
"recipient_user_id": recipient_user_id,
|
||||
})
|
||||
|
||||
|
||||
@login_required(login_url="/")
|
||||
|
||||
Reference in New Issue
Block a user