feat(shard): admin write plane, help-page queue, and public champion board
Wire up the three uo-link sidecar surfaces that weren't integrated yet. Champion spawns - Ingest champ.update/champ.remove into a new shard_champs table (served from our own store, like online/houses); public /site/champs board with a nav link, live via the existing SSE feed (champ.* added to the public allowlist). Staff write plane (admin + moderator) - kick / ban / unban / broadcast via /admin/shard/*; actor is stamped server-side from the session, never the browser. Sidecar status codes mapped (403 disabled/ protected, 404 unknown, 503/504 transient). admin.audit events are logged and surfaced at /admin/shard/audit. - New admin "In-Game Ops" view (/admin/shard-ops), plus per-account Kick/Ban/Unban on the user-detail and character views (ShardAccountActions, self-gated to staff). Help-page (support) queue - Ingest page.new/updated/closed into a new shard_pages table; respond/close via /admin/shard/pages/*. Champ board and page queue are snapshotted from the sidecar's /champs and /pages on every WS (re)connect (guarded so a failed call never wipes local state). Verified live end-to-end against MariaDB + the Rust sidecar + ServUO; unit tests cover ingest routing (shardIngest.champsPages.test.js). Swagger regenerated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0114TpmrNW4wNXsHq5CR72jQ
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Loading, ErrorState } from './PageState.jsx'
|
||||
import ShardAccountActions from './ShardAccountActions.jsx'
|
||||
|
||||
// Shared game-account linking + character roster, used by both the player portal
|
||||
// (/player) and the staff account page (/admin/account). `scope` is the api
|
||||
@@ -107,7 +108,7 @@ function AccountRoster({ scope, account, charTo }) {
|
||||
)
|
||||
}
|
||||
|
||||
export default function GameAccounts({ scope, charTo, readOnly = false }) {
|
||||
export default function GameAccounts({ scope, charTo, readOnly = false, moderation = false }) {
|
||||
const [accounts, setAccounts] = useState(null)
|
||||
const [error, setError] = useState('')
|
||||
|
||||
@@ -156,6 +157,7 @@ export default function GameAccounts({ scope, charTo, readOnly = false }) {
|
||||
<div className="sans" style={{ color: 'var(--accent)', fontSize: '0.7rem', letterSpacing: '0.12em', textTransform: 'uppercase', marginBottom: 12 }}>
|
||||
{a.account}
|
||||
</div>
|
||||
{moderation && <ShardAccountActions account={a.account} style={{ marginBottom: 12 }} />}
|
||||
<AccountRoster scope={scope} account={a.account} charTo={charTo} />
|
||||
</section>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user