Files
decePubClient/Pages/Administration.razor
T
thepraandClaude Opus 5.5 d33697e3fc R8 the Mastodon API made real in decePub: featured tags, notify, languages, recommendations, notes, suggestions, the direct stream
A profile shows the hashtags an account features as chips opening their feed; under another account's header is what the
persona keeps of it for itself alone: for one it follows, a bell (follow with notify), the languages of its posts that
reach the home feed (follow with languages[]) and Recommend (endorsements, private here), and for any account a private
note saved on blur or with Save. Settings edits the persona's featured hashtags (added by name or from those used lately,
10 at most) and its reading preferences (/clientapi/avatar/private/preferences), which CascadingState keeps per persona
and the card applies to sensitive media and content warnings. A hashtag's tab features it on the profile. Explore has Who
to follow (/api/v2/suggestions, dismissed for good after asking); Administration has Staff picks. The Direct tab follows
the direct stream's conversation events; status notifications show the post. The follows CSV carries notify and languages.

Verified: Release build, 0 errors (the 3 warnings were there before). Not run against PrivaPub or in the pasture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpVCoDeM1qUTRp4fXQdfof
2026-10-18 08:58:30 +02:00

204 lines
6.1 KiB
Plaintext

@page "/administration"
@attribute [Authorize(Policy = Policies.IsModerator)]
@inherits LocalizableComponentBase
<Title>@Localizer["Administration"]</Title>
@* Moderators handle reports, moderate accounts here and elsewhere (Accounts) and read the staff's log. Administrators
also change the logins and their personas (Users & personas), say what the server is (Instance), set its rules, write
its announcements, add its custom emoji, pick the accounts suggested to every persona (Staff picks), block servers for
everyone, choose its relays and media limits, read the
federation statistics, and back up and restore the server. PrivaPub checks the role on every call; the sections only follow it. Each section is
a collapse marked data-admin-section; its panel loads when the page opens. *@
<section class="block relative w-full h-full neo-inset neo-xs rounded-xl">
<div class="flex flex-col gap-4 p-4 md:p-5 w-full h-full absolute overflow-y-auto">
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="reports">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-flag text-xl"></i> <span>@Localizer["Reports"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<ReportsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="accounts">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-contacts text-xl"></i> <span>@Localizer["Accounts"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<AccountsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="log">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-list-box text-xl"></i> <span>@Localizer["Moderation log"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<ModerationLogPanel />
</div>
</ChildContent>
</DCollapse>
<AuthorizeView Policy="@Policies.IsAdmin">
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="users">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-people text-xl"></i> <span>@Localizer["Users & personas"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<UsersPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="instance">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-information-circle text-xl"></i> <span>@Localizer["Instance"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<InstancePanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="rules">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-book text-xl"></i> <span>@Localizer["Rules"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<RulesPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="announcements">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-megaphone text-xl"></i> <span>@Localizer["Announcements"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<AnnouncementsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="emoji">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-happy text-xl"></i> <span>@Localizer["Custom emoji"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<EmojiPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="staff-picks">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-star text-xl"></i> <span>@Localizer["Staff picks"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<StaffPicksPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="blocks">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-globe text-xl"></i> <span>@Localizer["Blocked servers"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<ServerBlocksPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="relays">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-radio text-xl"></i> <span>@Localizer["Relays"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<RelaysPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="media">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-images text-xl"></i> <span>@Localizer["Media limits"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<MediaLimitsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="statistics">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-stats text-xl"></i> <span>@Localizer["Statistics"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<StatisticsPanel />
</div>
</ChildContent>
</DCollapse>
<DCollapse Icon="DCollapseIcon.Arrow" data-admin-section="backups">
<Header>
<p class="inline-flex items-center gap-2">
<i class="ion-md-archive text-xl"></i> <span>@Localizer["Backups"]</span>
</p>
</Header>
<ChildContent>
<div class="block w-full p-3 md:p-4">
<BackupsPanel />
</div>
</ChildContent>
</DCollapse>
</AuthorizeView>
</div>
</section>