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> <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"> <div class="flex gap-1">
<figure class="" v-if="report.reported.avatar"> <figure class="" v-if="report.reported.avatar">
<img <img
alt="" alt=""
:src="report.reported.avatar.url" :src="report.reported.avatar.url"
class="rounded-full" class="rounded-full"
width="48" width="24"
height="48" height="24"
/> />
</figure> </figure>
<AccountCircle v-else :size="48" /> <AccountCircle v-else :size="24" />
<div class=""> <div class="">
<p class="" v-if="report.reported.name">{{ report.reported.name }}</p> <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> </div>
<div class="reported_by"> <div class="p-2">
<div class=""> <div class="">
<span v-if="report.reporter.type === ActorType.APPLICATION"> <span v-if="report.reporter.type === ActorType.APPLICATION">
{{ {{
@ -26,6 +38,14 @@
}) })
}} }}
</span> </span>
<span
v-if="
report.reporter.preferredUsername === 'anonymous' &&
!report.reporter.domain
"
>
{{ t("Reported by someone anonymously") }}
</span>
<span v-else> <span v-else>
{{ {{
t("Reported by {reporter}", { t("Reported by {reporter}", {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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