Improve reports

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2022-10-25 19:01:43 +02:00
parent cce0406db5
commit 389fa843e3
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
7 changed files with 487 additions and 432 deletions

View file

@ -1,23 +1,35 @@
<template>
<div class="dark:bg-zinc-700 p-2 rounded" v-if="report">
<div
class="bg-mbz-yellow-alt-50 hover:bg-mbz-yellow-alt-100 dark:bg-zinc-700 hover:dark:bg-zinc-600 rounded"
v-if="report"
>
<div class="flex justify-between gap-1 border-b p-2">
<div class="flex gap-1">
<figure class="" v-if="report.reported.avatar">
<img
alt=""
:src="report.reported.avatar.url"
class="rounded-full"
width="48"
height="48"
width="24"
height="24"
/>
</figure>
<AccountCircle v-else :size="48" />
<AccountCircle v-else :size="24" />
<div class="">
<p class="" v-if="report.reported.name">{{ report.reported.name }}</p>
<p class="">@{{ usernameWithDomain(report.reported) }}</p>
<p class="text-zinc-700 dark:text-zinc-100 text-sm">
@{{ usernameWithDomain(report.reported) }}
</p>
</div>
</div>
<div>
<p v-if="report.reported.suspended" class="text-red-700 font-bold">
{{ t("Suspended") }}
</p>
</div>
</div>
<div class="reported_by">
<div class="p-2">
<div class="">
<span v-if="report.reporter.type === ActorType.APPLICATION">
{{
@ -26,6 +38,14 @@
})
}}
</span>
<span
v-if="
report.reporter.preferredUsername === 'anonymous' &&
!report.reporter.domain
"
>
{{ t("Reported by someone anonymously") }}
</span>
<span v-else>
{{
t("Reported by {reporter}", {

View file

@ -90,6 +90,7 @@ import { computed, ref } from "vue";
import { useI18n } from "vue-i18n";
import { IComment } from "../../types/comment.model";
import { usernameWithDomain } from "@/types/actor";
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
const props = withDefaults(
defineProps<{

View file

@ -14,9 +14,11 @@ export const REPORTS = gql`
id
reported {
...ActorFragment
suspended
}
reporter {
...ActorFragment
suspended
}
event {
id

View file

@ -915,35 +915,41 @@ const toggleFollowNotify = () => {
});
};
const reportGroup = async (content: string, forward: boolean) => {
isReportModalActive.value = false;
reportModalRef.value.close();
const {
mutate: createReportMutation,
onError: onCreateReportError,
onDone: oneCreateReportDone,
onDone: onCreateReportDone,
} = useCreateReport();
const reportGroup = (content: string, forward: boolean) => {
isReportModalActive.value = false;
console.debug("report group", {
reportedId: group.value?.id ?? "",
content,
forward,
});
createReportMutation({
reportedId: group.value?.id ?? "",
content,
forward,
});
};
oneCreateReportDone(() => {
notifier?.success(t("Group {groupTitle} reported", { groupTitle }));
onCreateReportDone(() => {
notifier?.success(
t("Group {groupTitle} reported", { groupTitle: groupTitle.value })
);
});
onCreateReportError((error: any) => {
console.error(error);
notifier?.error(
t("Error while reporting group {groupTitle}", {
groupTitle,
groupTitle: groupTitle.value,
})
);
});
};
const triggerShare = (): void => {
if (navigator.share) {
@ -1032,8 +1038,8 @@ const physicalAddress = computed((): Address | null => {
return new Address(group.value?.physicalAddress);
});
const ableToReport = computed((): boolean | undefined => {
return anonymousReportsConfig.value?.allowed;
const ableToReport = computed((): boolean => {
return anonymousReportsConfig.value?.allowed === true;
});
const organizedEvents = computed((): Paginate<IEvent> => {

View file

@ -14,14 +14,25 @@
/>
<section v-if="actionLogs.total > 0 && actionLogs.elements.length > 0">
<ul>
<li v-for="log in actionLogs.elements" :key="log.id">
<div class="box">
<li
v-for="log in actionLogs.elements"
:key="log.id"
class="bg-mbz-yellow-alt-50 hover:bg-mbz-yellow-alt-100 dark:bg-zinc-700 hover:dark:bg-zinc-600 rounded p-2 my-1"
>
<div class="flex gap-1">
<div class="flex gap-1">
<figure class="" v-if="log.actor?.avatar">
<img
class="image"
:src="log.actor.avatar.url"
:alt="log.actor.avatar.alt || ''"
v-if="log.actor.avatar"
alt=""
:src="log.actor.avatar?.url"
class="rounded-full"
width="36"
height="36"
/>
</figure>
<AccountCircle v-else :size="36" />
</div>
<div>
<i18n-t
v-if="log.action === ActionLogAction.REPORT_UPDATE_CLOSED"
tag="span"
@ -29,15 +40,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #report>
<router-link
class="underline"
:to="{
name: RouteName.REPORT,
params: { reportId: log.object.id },
@ -57,15 +70,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #report>
<router-link
class="underline"
:to="{
name: RouteName.REPORT,
params: { reportId: log.object.id },
@ -79,21 +94,25 @@
</template>
</i18n-t>
<i18n-t
v-else-if="log.action === ActionLogAction.REPORT_UPDATE_RESOLVED"
v-else-if="
log.action === ActionLogAction.REPORT_UPDATE_RESOLVED
"
tag="span"
keypath="{moderator} marked {report} as resolved"
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #report>
<router-link
class="underline"
:to="{
name: RouteName.REPORT,
params: { reportId: log.object.id },
@ -113,15 +132,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #report>
<router-link
class="underline"
v-if="log.object.report"
:to="{
name: RouteName.REPORT,
@ -143,11 +164,12 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #title>
@ -164,15 +186,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #profile>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.object.id },
@ -191,15 +215,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #profile>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.object.id },
@ -218,15 +244,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #profile>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_GROUP_PROFILE,
params: { id: log.object.id },
@ -245,15 +273,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #profile>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_GROUP_PROFILE,
params: { id: log.object.id },
@ -269,15 +299,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #user>
<router-link
class="underline"
v-if="log.object.confirmedAt"
:to="{
name: RouteName.ADMIN_USER_PROFILE,
@ -300,15 +332,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #event>
<router-link
class="underline"
v-if="log.object.event && log.object.event.uuid"
:to="{
name: RouteName.EVENT,
@ -320,6 +354,7 @@
</template>
<template #author>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.object.actor.id },
@ -337,15 +372,17 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
<template #author>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.object.actor.id },
@ -363,17 +400,19 @@
>
<template #moderator>
<router-link
class="underline"
:to="{
name: RouteName.ADMIN_PROFILE,
params: { id: log.actor.id },
}"
>@{{ log.actor.preferredUsername }}</router-link
>{{ displayName(log.actor) }}</router-link
>
</template>
</i18n-t>
<br />
<small>{{ formatDateTimeString(log.insertedAt) }}</small>
</div>
</div>
</li>
</ul>
<o-pagination
@ -399,7 +438,7 @@ import { IActionLog } from "@/types/report.model";
import { LOGS } from "@/graphql/report";
import { ActionLogAction } from "@/types/enums";
import RouteName from "../../router/name";
import { displayNameAndUsername } from "../../types/actor";
import { displayNameAndUsername, displayName } from "../../types/actor";
import { Paginate } from "@/types/paginate";
import { useQuery } from "@vue/apollo-composable";
import { integerTransformer, useRouteQuery } from "vue-use-route-query";
@ -407,6 +446,7 @@ import { useHead } from "@vueuse/head";
import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { formatDateTimeString } from "@/filters/datetime";
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
const LOGS_PER_PAGE = 10;
@ -436,10 +476,6 @@ img.image {
vertical-align: text-bottom;
}
a {
text-decoration: none;
}
section ul li {
margin: 0.5rem auto;
}

View file

@ -119,7 +119,10 @@ const { result: reportsResult } = useQuery<{ reports: Paginate<IReport> }>(
status: status.value,
limit: REPORT_PAGE_LIMIT,
domain: filterDomain.value,
})
}),
{
fetchPolicy: "cache-and-network",
}
);
const reports = computed(

View file

@ -136,8 +136,9 @@
</tr>
<tr v-if="report.event && report.comments.length > 0">
<td>{{ t("Event") }}</td>
<td>
<td class="flex gap-2 items-center">
<router-link
class="underline"
:to="{
name: RouteName.EVENT,
params: { uuid: report.event.uuid },
@ -145,41 +146,32 @@
>
{{ report.event.title }}
</router-link>
<span>
<!-- <o-button-->
<!-- tag="router-link"-->
<!-- variant="primary"-->
<!-- :to="{ name: RouteName.EDIT_EVENT, params: {eventId: report.event.uuid } }"-->
<!-- icon-left="pencil"-->
<!-- size="small">{{ t('Edit') }}</o-button>-->
<o-button
variant="danger"
@click="confirmEventDelete()"
icon-left="delete"
size="small"
>{{ t("Delete") }}</o-button
>
</span>
</td>
</tr>
</tbody>
</table>
</section>
<section>
<h2>{{ t("Report reason") }}</h2>
<div class="dark:bg-zinc-700 p-2 rounded my-2">
<section class="bg-white dark:bg-zinc-700 rounded px-2 pt-1 pb-2 my-3">
<h2 class="mb-1">{{ t("Report reason") }}</h2>
<div class="">
<div class="flex gap-1">
<figure class="" v-if="report.reported.avatar">
<img
alt=""
:src="report.reported.avatar.url"
class="rounded-full"
width="48"
height="48"
width="36"
height="36"
/>
</figure>
<AccountCircle v-else :size="48" />
<AccountCircle v-else :size="36" />
<div class="">
<p class="" v-if="report.reported.name">
{{ report.reported.name }}
@ -196,15 +188,12 @@
</div>
</section>
<section class="" v-if="report.event && report.comments.length === 0">
<h2>{{ t("Reported content") }}</h2>
<EventCard :event="report.event" mode="row" class="my-2" />
<!-- <o-button-->
<!-- tag="router-link"-->
<!-- variant="primary"-->
<!-- :to="{ name: RouteName.EDIT_EVENT, params: {eventId: report.event.uuid } }"-->
<!-- icon-left="pencil"-->
<!-- size="small">{{ t('Edit') }}</o-button>-->
<section
class="bg-white dark:bg-zinc-700 rounded px-2 pt-1 pb-2 my-3"
v-if="report.event && report.comments.length === 0"
>
<h2 class="mb-1">{{ t("Reported content") }}</h2>
<EventCard :event="report.event" mode="row" class="my-2 max-w-4xl" />
<o-button
variant="danger"
@click="confirmEventDelete()"
@ -214,32 +203,35 @@
>
</section>
<div v-if="report.comments.length > 0">
<section
class="bg-white dark:bg-zinc-700 rounded px-2 pt-1 pb-2 my-3"
v-if="report.comments.length > 0"
>
<h2 class="mb-1">{{ t("Reported content") }}</h2>
<ul v-for="comment in report.comments" :key="comment.id">
<li>
<div class="" v-if="comment">
<article class="flex gap-1">
<div class="">
<figure class="" v-if="comment.actor && comment.actor.avatar">
<article>
<div class="flex gap-1">
<figure class="" v-if="comment.actor?.avatar">
<img
:src="comment.actor.avatar.url"
alt=""
width="48"
height="48"
:src="comment.actor.avatar?.url"
class="rounded-full"
width="36"
height="36"
/>
</figure>
<AccountCircle :size="48" v-else />
<AccountCircle v-else :size="36" />
<div>
<div v-if="comment.actor">
<p>{{ comment.actor.name }}</p>
<p>@{{ comment.actor.preferredUsername }}</p>
</div>
<div class="">
<div class="prose dark:prose-invert">
<span v-if="comment.actor">
<strong>{{ comment.actor.name }}</strong>
<small>@{{ comment.actor.preferredUsername }}</small>
</span>
<span v-else>{{ t("Unknown actor") }}</span>
<br />
<p v-html="comment.text" />
</div>
</div>
<div class="prose dark:prose-invert" v-html="comment.text" />
<o-button
variant="danger"
@click="confirmCommentDelete(comment)"
@ -247,17 +239,16 @@
size="small"
>{{ t("Delete") }}</o-button
>
</div>
</article>
</div>
</li>
</ul>
</div>
</section>
<section>
<h2>{{ t("Notes") }}</h2>
<section class="bg-white dark:bg-zinc-700 rounded px-2 pt-1 pb-2 my-3">
<h2 class="mb-1">{{ t("Notes") }}</h2>
<div
class="box note"
class=""
v-for="note in report.notes"
:id="`note-${note.id}`"
:key="note.id"
@ -536,8 +527,4 @@ tbody td img.image,
text-decoration: none;
color: inherit;
}
td > a {
text-decoration: none;
}
</style>