R5 the server's own settings in decePub: instance, rules, announcements, relays, media limits, the staff's log, About
Build / Build (push) Successful in 1m5s
Build / Build (push) Successful in 1m5s
Administration's Pleroma placeholders give way to real sections: Instance (title, descriptions, contact, thumbnail, privacy policy, terms, the weekly activity), Rules, Announcements, Relays, Media limits and the Moderation log, next to Reports, blocked servers (now published or obfuscated), statistics and backups; moderators see Reports and the log. Every save sends the whole settings form built from the latest read, since PrivaPub replaces what it carries. /about shows the server's documents to anyone. The report dialog picks the rules a violation breaks, and reports show them. Announcements show above the feed tabs, dismissed and reacted to, live from the user stream. Login names the server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpVCoDeM1qUTRp4fXQdfof
This commit is contained in:
1 parent
b8d7858acb
commit
4c88980374
33 files changed
+3743
-239
No files matched your search
@@ -1,7 +1,9 @@
|
||||
@inherits LocalizableComponentBase
|
||||
|
||||
@* Reports an account, and the post it was opened from, to the persona's server's moderators (/api/v1/reports).
|
||||
Forwarded, a remote account's server gets the report too, from PrivaPub's own actor: it never names the persona. *@
|
||||
Forwarded, a remote account's server gets the report too, from PrivaPub's own actor: it never names the persona. A
|
||||
violation names the server's rules it breaks (/api/v1/instance/rules, sent as rule_ids); it is offered only while the
|
||||
server has rules. *@
|
||||
<DModal Placement="DModalPlacement.ResponsiveBottom" IsOpen="true" IsOpenChanged="Closed" CloseText="@Localizer["Close"]" data-report-dialog>
|
||||
<Heading>@Localizer["Report {0}", Account.Name]</Heading>
|
||||
<ChildContent>
|
||||
@@ -11,8 +13,31 @@
|
||||
<DSelect TValue="ReportCategory" @bind-Value="form.Category" data-report-category>
|
||||
<option value="@ReportCategory.Spam">@Localizer[nameof(ReportCategory.Spam)]</option>
|
||||
<option value="@ReportCategory.Legal">@Localizer[nameof(ReportCategory.Legal)]</option>
|
||||
@if (choices.Count > 0)
|
||||
{
|
||||
<option value="@ReportCategory.Violation">@Localizer[nameof(ReportCategory.Violation)]</option>
|
||||
}
|
||||
<option value="@ReportCategory.Other">@Localizer[nameof(ReportCategory.Other)]</option>
|
||||
</DSelect>
|
||||
@if (form.Category is ReportCategory.Violation)
|
||||
{
|
||||
<fieldset class="flex flex-col gap-1 pointer-coarse:gap-2" data-report-rules>
|
||||
<legend class="text-sm mb-1">@Localizer["Which of the server's rules does it break?"]</legend>
|
||||
@foreach (var choice in choices)
|
||||
{
|
||||
<label class="flex items-start gap-2 cursor-pointer pointer-coarse:py-2">
|
||||
<DCheckbox @bind-Value="choice.Picked" class="mt-0.5 flex-none" data-report-rule="@choice.Rule.Id" />
|
||||
<span class="flex flex-col min-w-0">
|
||||
<span class="text-sm break-words">@choice.Rule.Text</span>
|
||||
@if (choice.Rule.Hint is { Length: > 0 } hint)
|
||||
{
|
||||
<span class="text-xs opacity-70 break-words">@hint</span>
|
||||
}
|
||||
</span>
|
||||
</label>
|
||||
}
|
||||
</fieldset>
|
||||
}
|
||||
<DTextarea TValue="string" @bind-Value="form.Comment" Immediate="true" rows="3" autocomplete="off" maxlength="@ReportForm.CommentLength"
|
||||
placeholder="@Localizer["What is wrong with it?"]" data-report-comment />
|
||||
@if (Host is { } host)
|
||||
@@ -30,6 +55,7 @@
|
||||
|
||||
@code {
|
||||
[Inject] AccountService AccountService { get; set; }
|
||||
[Inject] AboutService AboutService { get; set; }
|
||||
|
||||
[Parameter, EditorRequired] public Account Account { get; set; }
|
||||
/// <summary>The post it was opened from, sent with the report.</summary>
|
||||
@@ -39,17 +65,41 @@
|
||||
ReportForm form = new();
|
||||
bool isSending;
|
||||
string error;
|
||||
// the server's rules, each ticked or not, for a violation
|
||||
List<RuleChoice> choices = [];
|
||||
|
||||
// the account's own server, for a remote account
|
||||
string Host => Account.Acct?.Split('@') is [_, { Length: > 0 } host] ? host : null;
|
||||
|
||||
protected override void OnInitialized() => IsLoading = false;
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (CascadingState.IsOffline)
|
||||
{
|
||||
WhenOnline(LoadData);
|
||||
StartOnlinePolling();
|
||||
IsLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
await LoadData();
|
||||
IsLoading = false;
|
||||
}
|
||||
|
||||
async Task LoadData() => choices = [.. (await AboutService.Rules()).Select(rule => new RuleChoice { Rule = rule })];
|
||||
|
||||
async Task Send()
|
||||
{
|
||||
isSending = true;
|
||||
error = null;
|
||||
var result = await AccountService.Report(Account.Id, Post is null ? [] : [Post.Id], form.Comment, form.Category, Host is not null && form.Forward);
|
||||
var ruleIds = form.Category is ReportCategory.Violation ? choices.Where(c => c.Picked).Select(c => c.Rule.Id).ToList() : [];
|
||||
if (form.Category is ReportCategory.Violation && ruleIds.Count == 0)
|
||||
{
|
||||
error = Localizer["Tick the rules it breaks."];
|
||||
return;
|
||||
}
|
||||
|
||||
isSending = true;
|
||||
var result = await AccountService.Report(Account.Id, Post is null ? [] : [Post.Id], form.Comment, form.Category, ruleIds,
|
||||
Host is not null && form.Forward);
|
||||
isSending = false;
|
||||
if (result.IsInvalid)
|
||||
{
|
||||
@@ -62,4 +112,10 @@
|
||||
}
|
||||
|
||||
Task Closed(bool open) => open ? Task.CompletedTask : OnClosed.InvokeAsync();
|
||||
|
||||
sealed class RuleChoice
|
||||
{
|
||||
public InstanceRule Rule { get; init; }
|
||||
public bool Picked { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user