138 lines
4.1 KiB
Plaintext
138 lines
4.1 KiB
Plaintext
@inherits LocalizableComponentBase
|
|||
|
|
|
||
|
|
@* The reports moderators handle (/clientapi/moderator/reports): from someone here (never said who) or from another
|
||
|
|
server, about an account and some of its posts; resolved here. *@
|
||
|
|
<div class="flex flex-col gap-3 w-full" data-reports>
|
||
|
|
<DToggle LabelText="@Localizer["Show the resolved ones"]" Value="resolved" ValueChanged="ShowResolved" ValueExpression="() => resolved" />
|
||
|
|
|
||
|
|
@if (IsLoading)
|
||
|
|
{
|
||
|
|
<p class="flex w-full items-center justify-center gap-2">
|
||
|
|
<DLoading Variant="DLoadingVariant.Dots" LabelText="@Localizer["loading"]" />
|
||
|
|
@Localizer["loading"]
|
||
|
|
</p>
|
||
|
|
}
|
||
|
|
else if (reports.Count == 0)
|
||
|
|
{
|
||
|
|
<p class="text-sm opacity-70">@(resolved ? Localizer["No resolved report."] : Localizer["No open report."])</p>
|
||
|
|
}
|
||
|
|
|
||
|
|
@foreach (var report in reports)
|
||
|
|
{
|
||
|
|
<article class="flex flex-col gap-2 p-3 rounded-xl neo-raised neo-xs" data-report-id="@report.ID">
|
||
|
|
<div class="flex flex-wrap items-center gap-2">
|
||
|
|
<DBadge Size="DSize.Sm" Variant="DBadgeVariant.Soft" Color="DColor.Warning">@CategoryName(report.Category)</DBadge>
|
||
|
|
@if (report.Forwarded)
|
||
|
|
{
|
||
|
|
<DBadge Size="DSize.Sm" Variant="DBadgeVariant.Soft">@Localizer["Forwarded"]</DBadge>
|
||
|
|
}
|
||
|
|
<span class="text-xs opacity-70" title="@report.CreatedAt.ToLocalTime().ToString(SUtility.dateTimeFormat)">
|
||
|
|
@report.CreatedAt.GetPassedTime(Localizer)
|
||
|
|
</span>
|
||
|
|
<span class="flex-1"></span>
|
||
|
|
@if (!report.IsResolved)
|
||
|
|
{
|
||
|
|
<DButton Size="DSize.Sm" Color="DColor.Success" Disabled="@(IsDefaultDisabled || busy.Contains(report.ID))" OnClick="() => Resolve(report)"
|
||
|
|
data-report-resolve>
|
||
|
|
<i class="ion-md-checkmark"></i><span>@Localizer["Resolve"]</span>
|
||
|
|
</DButton>
|
||
|
|
}
|
||
|
|
else if (report.ResolvedAt is { } resolvedAt)
|
||
|
|
{
|
||
|
|
<span class="text-xs opacity-70">@Localizer["Resolved {0}", resolvedAt.GetPassedTime(Localizer)]</span>
|
||
|
|
}
|
||
|
|
</div>
|
||
|
|
<p class="text-sm">
|
||
|
|
<b>@Localizer["About"]</b>
|
||
|
|
@if (report.TargetAccountId is { Length: > 0 } targetId)
|
||
|
|
{
|
||
|
|
<a class="link link-hover break-all" href="@($"account/{Uri.EscapeDataString(targetId)}")">@report.TargetActorURI</a>
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
<span class="break-all">@report.TargetActorURI</span>
|
||
|
|
}
|
||
|
|
</p>
|
||
|
|
<p class="text-sm">
|
||
|
|
<b>@Localizer["From"]</b>
|
||
|
|
<span class="break-all">@(report.Reporter == "local" ? Localizer["someone here"] : report.Reporter)</span>
|
||
|
|
</p>
|
||
|
|
@if (report.Comment is { Length: > 0 } comment)
|
||
|
|
{
|
||
|
|
<p class="text-sm whitespace-pre-line rounded-lg neo-inset neo-2xs p-2">@comment</p>
|
||
|
|
}
|
||
|
|
@if (report.PostIds.Count > 0 || report.ObjectURIs.Count > 0)
|
||
|
|
{
|
||
|
|
<div class="flex flex-wrap gap-2 text-xs">
|
||
|
|
@foreach (var postId in report.PostIds)
|
||
|
|
{
|
||
|
|
<a class="link" href="@($"expand/{Uri.EscapeDataString(postId)}")">@Localizer["Post {0}", postId]</a>
|
||
|
|
}
|
||
|
|
@* a report from another server names posts by their ids there when we hold none of them *@
|
||
|
|
@if (report.PostIds.Count == 0)
|
||
|
|
{
|
||
|
|
@foreach (var uri in report.ObjectURIs)
|
||
|
|
{
|
||
|
|
<span class="break-all opacity-70">@uri</span>
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
</article>
|
||
|
|
}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
@code {
|
||
|
|
[Inject] AdminService AdminService { get; set; }
|
||
|
|
|
||
|
|
List<ViewReport> reports = [];
|
||
|
|
bool resolved;
|
||
|
|
HashSet<string> busy = [];
|
||
|
|
|
||
|
|
protected override async Task OnInitializedAsync()
|
||
|
|
{
|
||
|
|
if (CascadingState.IsOffline)
|
||
|
|
{
|
||
|
|
WhenOnline(LoadData);
|
||
|
|
StartOnlinePolling();
|
||
|
|
IsLoading = false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
await LoadData();
|
||
|
|
IsLoading = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
async Task LoadData() => reports = await AdminService.Reports(resolved);
|
||
|
|
|
||
|
|
async Task ShowResolved(bool value)
|
||
|
|
{
|
||
|
|
resolved = value;
|
||
|
|
IsLoading = true;
|
||
|
|
await LoadData();
|
||
|
|
IsLoading = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
string CategoryName(string category) => category switch
|
||
|
|
{
|
||
|
|
"spam" => Localizer["Spam"],
|
||
|
|
"legal" => Localizer["Illegal"],
|
||
|
|
"violation" => Localizer["Breaks the rules"],
|
||
|
|
_ => Localizer["Other"]
|
||
|
|
};
|
||
|
|
|
||
|
|
async Task Resolve(ViewReport report)
|
||
|
|
{
|
||
|
|
busy.Add(report.ID);
|
||
|
|
var result = await AdminService.Resolve(report.ID);
|
||
|
|
busy.Remove(report.ID);
|
||
|
|
if (result.IsInvalid)
|
||
|
|
{
|
||
|
|
Toast.AddResponseError(result);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
reports.Remove(report);
|
||
|
|
Toast.AddResponseSuccess(Localizer["Report resolved."]);
|
||
|
|
}
|
||
|
|
}
|