feat(web): render outbound peering requests with subscriber list in admin panel
PendingApprovals now branches row rendering on direction. Inbound rows render exactly as before. Outbound rows show '<instance> — N users want us to peer' with an inline subscriber list (username + reason + target). ConfirmDialog descriptions branch on direction so admins see appropriate copy for outbound approve (initiate handshake on behalf of N users) vs outbound deny (notify requesting users).
This commit is contained in:
@@ -693,16 +693,44 @@ function PendingApprovals({ onCountChange }: { onCountChange?: (count: number) =
|
|||||||
<div className="text-xs text-txt-tertiary py-2">Loading...</div>
|
<div className="text-xs text-txt-tertiary py-2">Loading...</div>
|
||||||
)}
|
)}
|
||||||
{requests.map((req) => {
|
{requests.map((req) => {
|
||||||
const name = req.instanceName || new URL(req.origin).host;
|
const isOutbound = req.direction === 'outbound';
|
||||||
|
let name = req.instanceName || '';
|
||||||
|
if (!name) {
|
||||||
|
try {
|
||||||
|
name = new URL(req.origin).host;
|
||||||
|
} catch {
|
||||||
|
name = req.origin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const subCount = req.subscribers?.length ?? 0;
|
||||||
|
const titleText = isOutbound
|
||||||
|
? `${name} — ${subCount} ${subCount === 1 ? 'user wants' : 'users want'} us to peer`
|
||||||
|
: name;
|
||||||
return (
|
return (
|
||||||
<div key={req.id} className="bg-white/[0.02] rounded-md px-3 py-2.5">
|
<div key={req.id} className="bg-white/[0.02] rounded-md px-3 py-2.5">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<div className="text-sm font-medium text-txt-primary truncate">{name}</div>
|
<div className="text-sm font-medium text-txt-primary truncate">{titleText}</div>
|
||||||
<div className="text-[11px] text-txt-tertiary truncate">{req.origin}</div>
|
<div className="text-[11px] text-txt-tertiary truncate">{req.origin}</div>
|
||||||
<div className="text-[11px] text-txt-tertiary mt-0.5">
|
<div className="text-[11px] text-txt-tertiary mt-0.5">
|
||||||
Requested {formatRelativeTime(req.requestedAt)}
|
Requested {formatRelativeTime(req.requestedAt)}
|
||||||
</div>
|
</div>
|
||||||
|
{isOutbound && req.subscribers && req.subscribers.length > 0 && (
|
||||||
|
<div className="mt-1.5 space-y-0.5">
|
||||||
|
{req.subscribers.map((sub) => (
|
||||||
|
<div
|
||||||
|
key={`${sub.userId}:${sub.triggerReason}:${sub.triggerTarget}`}
|
||||||
|
className="text-[11px] text-txt-tertiary"
|
||||||
|
>
|
||||||
|
<span className="font-medium text-txt-secondary">{sub.username}</span>
|
||||||
|
{' — '}
|
||||||
|
{sub.triggerReason === 'friend_add' && `friend-add to ${sub.triggerTarget}`}
|
||||||
|
{sub.triggerReason === 'space_join' && `wants to join ${sub.triggerTarget}`}
|
||||||
|
{sub.triggerReason === 'direct_message' && `wants to DM ${sub.triggerTarget}`}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 shrink-0 ml-3">
|
<div className="flex items-center gap-2 shrink-0 ml-3">
|
||||||
<button
|
<button
|
||||||
@@ -740,22 +768,35 @@ function PendingApprovals({ onCountChange }: { onCountChange?: (count: number) =
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{confirmAction && (
|
{confirmAction && (() => {
|
||||||
<ConfirmDialog
|
const isOutbound = confirmAction.request.direction === 'outbound';
|
||||||
isOpen={true}
|
const targetName = confirmAction.request.instanceName || confirmAction.request.origin;
|
||||||
onClose={() => { if (!actionLoading) setConfirmAction(null); }}
|
const subCount = confirmAction.request.subscribers?.length ?? 0;
|
||||||
onConfirm={handleConfirm}
|
const description =
|
||||||
title={confirmAction.type === 'approve' ? 'Approve Peering Request' : 'Deny Peering Request'}
|
confirmAction.type === 'approve'
|
||||||
description={
|
? isOutbound
|
||||||
confirmAction.type === 'approve'
|
? `This will initiate a peering handshake with ${targetName} on behalf of the ${subCount} requesting ${subCount === 1 ? 'user' : 'users'}. The remote instance must be reachable.`
|
||||||
? `This will initiate a peering handshake with ${confirmAction.request.instanceName || confirmAction.request.origin}. The remote instance must be reachable.`
|
: `This will initiate a peering handshake with ${targetName}. The remote instance must be reachable.`
|
||||||
: `This will deny the request and block future auto-peering requests from ${confirmAction.request.instanceName || confirmAction.request.origin}. You can unblock them later from the rejected peers list.`
|
: isOutbound
|
||||||
}
|
? `This will deny the outbound peering request and notify the requesting ${subCount === 1 ? 'user' : 'users'}. They can re-trigger the request from their friend list.`
|
||||||
confirmLabel={confirmAction.type === 'approve' ? 'Approve' : 'Deny'}
|
: `This will deny the request and block future auto-peering requests from ${targetName}. You can unblock them later from the rejected peers list.`;
|
||||||
variant={confirmAction.type === 'approve' ? 'warning' : 'danger'}
|
const confirmLabel =
|
||||||
loading={!!actionLoading}
|
confirmAction.type === 'approve'
|
||||||
/>
|
? isOutbound ? 'Approve & Peer' : 'Approve'
|
||||||
)}
|
: isOutbound ? 'Deny & Notify' : 'Deny';
|
||||||
|
return (
|
||||||
|
<ConfirmDialog
|
||||||
|
isOpen={true}
|
||||||
|
onClose={() => { if (!actionLoading) setConfirmAction(null); }}
|
||||||
|
onConfirm={handleConfirm}
|
||||||
|
title={confirmAction.type === 'approve' ? 'Approve Peering Request' : 'Deny Peering Request'}
|
||||||
|
description={description}
|
||||||
|
confirmLabel={confirmLabel}
|
||||||
|
variant={confirmAction.type === 'approve' ? 'warning' : 'danger'}
|
||||||
|
loading={!!actionLoading}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user