Link invite trace accounts to admin user profiles
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import InviteDeliveryChoice from '../../ui/InviteDeliveryChoice'
|
import InviteDeliveryChoice from '../../ui/InviteDeliveryChoice'
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { useEffect, useMemo, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
@@ -918,6 +919,14 @@ export default function AdminInviteManagementPage() {
|
|||||||
return invites
|
return invites
|
||||||
}, [inviteView, invites])
|
}, [inviteView, invites])
|
||||||
|
|
||||||
|
const traceUserIds = useMemo(() => new Map(users.map(user => [user.username.trim().toLowerCase(), user.id])), [users])
|
||||||
|
const traceAccountLink = (username: string, className?: string) => {
|
||||||
|
const id = traceUserIds.get(username.trim().toLowerCase())
|
||||||
|
return id != null
|
||||||
|
? <Link className={`invite-trace-account-link ${className || ''}`} href={`/users/${id}`} title={`Manage ${username}'s account`}>{username}</Link>
|
||||||
|
: <span className={className}>{username}</span>
|
||||||
|
}
|
||||||
|
|
||||||
const inviteTraceRows = useMemo(() => {
|
const inviteTraceRows = useMemo(() => {
|
||||||
const inviteByCode = new Map<string, Invite>()
|
const inviteByCode = new Map<string, Invite>()
|
||||||
invites.forEach((invite) => {
|
invites.forEach((invite) => {
|
||||||
@@ -2276,14 +2285,14 @@ export default function AdminInviteManagementPage() {
|
|||||||
>
|
>
|
||||||
<div className="invite-trace-node-main">
|
<div className="invite-trace-node-main">
|
||||||
<div className="invite-trace-node-title">
|
<div className="invite-trace-node-title">
|
||||||
<span className="invite-trace-user">{row.username}</span>
|
{traceAccountLink(row.username, 'invite-trace-user')}
|
||||||
<span className={`small-pill ${row.role === 'admin' ? '' : 'is-muted'}`}>{row.role}</span>
|
<span className={`small-pill ${row.role === 'admin' ? '' : 'is-muted'}`}>{row.role}</span>
|
||||||
<span className="small-pill">{row.authProvider}</span>
|
<span className="small-pill">{row.authProvider}</span>
|
||||||
{row.isCycle && <span className="small-pill is-muted">cycle</span>}
|
{row.isCycle && <span className="small-pill is-muted">cycle</span>}
|
||||||
</div>
|
</div>
|
||||||
<p className={`invite-trace-node-arrow ${isInviteTraceRowInvited(row) ? '' : 'is-root'}`}>
|
<p className={`invite-trace-node-arrow ${isInviteTraceRowInvited(row) ? '' : 'is-root'}`}>
|
||||||
{row.inviterUsername
|
{row.inviterUsername
|
||||||
? `\u2190 Invited by ${row.inviterUsername}`
|
? <>← Invited by {traceAccountLink(row.inviterUsername)}</>
|
||||||
: row.inviteCode
|
: row.inviteCode
|
||||||
? `\u2190 Invited via code ${row.inviteCode}`
|
? `\u2190 Invited via code ${row.inviteCode}`
|
||||||
: 'Direct/root account'}
|
: 'Direct/root account'}
|
||||||
@@ -2319,7 +2328,7 @@ export default function AdminInviteManagementPage() {
|
|||||||
<div key={`${row.username}-${row.level}-${row.inviteCode || 'direct'}`} className="invite-trace-row">
|
<div key={`${row.username}-${row.level}-${row.inviteCode || 'direct'}`} className="invite-trace-row">
|
||||||
<div className="invite-trace-row-main" style={{ paddingLeft: `${row.level * 18}px` }}>
|
<div className="invite-trace-row-main" style={{ paddingLeft: `${row.level * 18}px` }}>
|
||||||
<span className="invite-trace-branch" aria-hidden="true" />
|
<span className="invite-trace-branch" aria-hidden="true" />
|
||||||
<span className="invite-trace-user">{row.username}</span>
|
{traceAccountLink(row.username, 'invite-trace-user')}
|
||||||
<span className={`small-pill ${row.role === 'admin' ? '' : 'is-muted'}`}>{row.role}</span>
|
<span className={`small-pill ${row.role === 'admin' ? '' : 'is-muted'}`}>{row.role}</span>
|
||||||
<span className="small-pill">{row.authProvider}</span>
|
<span className="small-pill">{row.authProvider}</span>
|
||||||
{row.isCycle && <span className="small-pill is-muted">cycle</span>}
|
{row.isCycle && <span className="small-pill is-muted">cycle</span>}
|
||||||
@@ -2327,7 +2336,7 @@ export default function AdminInviteManagementPage() {
|
|||||||
<div className="invite-trace-row-meta">
|
<div className="invite-trace-row-meta">
|
||||||
<span className="invite-trace-meta-item">
|
<span className="invite-trace-meta-item">
|
||||||
<span className="label">Invited by</span>
|
<span className="label">Invited by</span>
|
||||||
<strong>{row.inviterUsername || 'Root/direct'}</strong>
|
<strong>{row.inviterUsername ? traceAccountLink(row.inviterUsername) : 'Root/direct'}</strong>
|
||||||
</span>
|
</span>
|
||||||
<span className="invite-trace-meta-item">
|
<span className="invite-trace-meta-item">
|
||||||
<span className="label">Via code</span>
|
<span className="label">Via code</span>
|
||||||
|
|||||||
@@ -5684,6 +5684,18 @@ textarea {
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.invite-trace-account-link {
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-color: currentColor;
|
||||||
|
text-underline-offset: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invite-trace-account-link:focus-visible {
|
||||||
|
outline: 2px solid currentColor;
|
||||||
|
outline-offset: 4px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
.invite-trace-graph {
|
.invite-trace-graph {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
|
|||||||
Reference in New Issue
Block a user