PronounsPage/pages/admin/abuseReports.vue
2025-01-14 18:08:25 -08:00

160 lines
5.2 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { useNuxtApp, useFetch } from 'nuxt/app';
import useConfig from '~/composables/useConfig.ts';
import useSimpleHead from '~/composables/useSimpleHead.ts';
definePageMeta({
path: '/admin/abuse-reports',
});
const { $translator: translator } = useNuxtApp();
useSimpleHead({
title: `${translator.translate('admin.header')} • Abuse reports`,
}, translator);
const { data: abuseReports } = await useFetch<any[]>('/api/admin/reports', { lazy: true, default: () => [] });
const config = useConfig();
const filterAutomatic = ref();
const filterKeyword = ref();
const filterIsHandled = ref(false);
const filterLocale = ref(config.locale);
const keywords = computed(() => {
const keywords = new Set();
for (const report of abuseReports.value) {
if (!report.isAutomatic || report.comment.indexOf(' (') < 0) {
continue;
}
for (const keyword of report.comment.split(', ')) {
keywords.add(keyword.substring(0, keyword.indexOf(' (')));
}
}
return [...keywords].sort();
});
const abuseReportsActiveCount = computed(() => {
return abuseReports.value ? abuseReports.value.filter((r) => !r.isHandled).length : '';
});
const filteredAbuseReports = computed(() => {
if (abuseReports.value === undefined) {
return undefined;
}
return abuseReports.value.filter((r) => {
if (filterAutomatic.value === true && r.isAutomatic !== 1) {
return false;
}
if (filterAutomatic.value === false && r.isAutomatic !== 0) {
return false;
}
if (filterKeyword.value && r.comment) {
let found = false;
for (const keyword of r.comment.split(', ')) {
if (keyword.startsWith(`${filterKeyword.value} (`)) {
found = true;
}
}
if (!found) {
return false;
}
}
if (filterIsHandled.value === true && r.isHandled !== 1) {
return false;
}
if (filterIsHandled.value === false && r.isHandled !== 0) {
return false;
}
if (filterLocale.value && r.profiles && !r.profiles.split(',').includes(filterLocale.value)) {
return false;
}
return true;
});
});
</script>
<template>
<Page>
<NotFound v-if="!$isGranted('users') && !$isGranted('community')" />
<div v-else>
<p>
<nuxt-link to="/admin">
<Icon v="user-cog" />
<T>admin.header</T>
</nuxt-link>
</p>
<h2>
<Icon v="siren-on" />
Abuse reports
({{ abuseReportsActiveCount }})
</h2>
<form class="row mt-3">
<div class="col">
<select v-model="filterAutomatic" class="form-select">
<option :value="undefined">
All report types
</option>
<option :value="true">
Only automatic keywords
</option>
<option :value="false">
Only user reports
</option>
</select>
</div>
<div class="col">
<select v-model="filterKeyword" class="form-select">
<option :value="undefined">
All automatic keywords
</option>
<option v-for="keyword in keywords" :value="keyword">
{{ keyword }}
</option>
</select>
</div>
<div class="col">
<select v-model="filterLocale" class="form-select">
<option :value="undefined">
All language versions
</option>
<option v-for="locale in $locales" :value="locale.code">
{{ locale.fullName }}
</option>
</select>
</div>
<div class="col">
<select v-model="filterIsHandled" class="form-select">
<option :value="undefined">
All report statuses
</option>
<option :value="true">
Only handled reports
</option>
<option :value="false">
Only open reports
</option>
</select>
</div>
</form>
<section>
<ModerationRules type="rulesUsers" emphasise />
<ModerationRules type="susRegexes" label="Keywords for automated triggers" />
<Loading :value="filteredAbuseReports">
<AbuseReports :abuse-reports="filteredAbuseReports" allow-resolving allow-queue />
</Loading>
</section>
</div>
</Page>
</template>