Improve reports
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
cce0406db5
commit
389fa843e3
@ -1,23 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="dark:bg-zinc-700 p-2 rounded" v-if="report">
|
<div
|
||||||
<div class="flex gap-1">
|
class="bg-mbz-yellow-alt-50 hover:bg-mbz-yellow-alt-100 dark:bg-zinc-700 hover:dark:bg-zinc-600 rounded"
|
||||||
<figure class="" v-if="report.reported.avatar">
|
v-if="report"
|
||||||
<img
|
>
|
||||||
alt=""
|
<div class="flex justify-between gap-1 border-b p-2">
|
||||||
:src="report.reported.avatar.url"
|
<div class="flex gap-1">
|
||||||
class="rounded-full"
|
<figure class="" v-if="report.reported.avatar">
|
||||||
width="48"
|
<img
|
||||||
height="48"
|
alt=""
|
||||||
/>
|
:src="report.reported.avatar.url"
|
||||||
</figure>
|
class="rounded-full"
|
||||||
<AccountCircle v-else :size="48" />
|
width="24"
|
||||||
<div class="">
|
height="24"
|
||||||
<p class="" v-if="report.reported.name">{{ report.reported.name }}</p>
|
/>
|
||||||
<p class="">@{{ usernameWithDomain(report.reported) }}</p>
|
</figure>
|
||||||
|
<AccountCircle v-else :size="24" />
|
||||||
|
<div class="">
|
||||||
|
<p class="" v-if="report.reported.name">{{ report.reported.name }}</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}", {
|
||||||
|
@ -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<{
|
||||||
|
@ -14,9 +14,11 @@ export const REPORTS = gql`
|
|||||||
id
|
id
|
||||||
reported {
|
reported {
|
||||||
...ActorFragment
|
...ActorFragment
|
||||||
|
suspended
|
||||||
}
|
}
|
||||||
reporter {
|
reporter {
|
||||||
...ActorFragment
|
...ActorFragment
|
||||||
|
suspended
|
||||||
}
|
}
|
||||||
event {
|
event {
|
||||||
id
|
id
|
||||||
|
@ -915,36 +915,42 @@ const toggleFollowNotify = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const reportGroup = async (content: string, forward: boolean) => {
|
const {
|
||||||
isReportModalActive.value = false;
|
mutate: createReportMutation,
|
||||||
reportModalRef.value.close();
|
onError: onCreateReportError,
|
||||||
|
onDone: onCreateReportDone,
|
||||||
|
} = useCreateReport();
|
||||||
|
|
||||||
const {
|
const reportGroup = (content: string, forward: boolean) => {
|
||||||
mutate: createReportMutation,
|
isReportModalActive.value = false;
|
||||||
onError: onCreateReportError,
|
console.debug("report group", {
|
||||||
onDone: oneCreateReportDone,
|
reportedId: group.value?.id ?? "",
|
||||||
} = useCreateReport();
|
content,
|
||||||
|
forward,
|
||||||
|
});
|
||||||
|
|
||||||
createReportMutation({
|
createReportMutation({
|
||||||
reportedId: group.value?.id ?? "",
|
reportedId: group.value?.id ?? "",
|
||||||
content,
|
content,
|
||||||
forward,
|
forward,
|
||||||
});
|
});
|
||||||
|
|
||||||
oneCreateReportDone(() => {
|
|
||||||
notifier?.success(t("Group {groupTitle} reported", { groupTitle }));
|
|
||||||
});
|
|
||||||
|
|
||||||
onCreateReportError((error: any) => {
|
|
||||||
console.error(error);
|
|
||||||
notifier?.error(
|
|
||||||
t("Error while reporting group {groupTitle}", {
|
|
||||||
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.value,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const triggerShare = (): void => {
|
const triggerShare = (): void => {
|
||||||
if (navigator.share) {
|
if (navigator.share) {
|
||||||
navigator
|
navigator
|
||||||
@ -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> => {
|
||||||
|
@ -14,365 +14,404 @@
|
|||||||
/>
|
/>
|
||||||
<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"
|
||||||
<img
|
:key="log.id"
|
||||||
class="image"
|
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"
|
||||||
:src="log.actor.avatar.url"
|
>
|
||||||
:alt="log.actor.avatar.alt || ''"
|
<div class="flex gap-1">
|
||||||
v-if="log.actor.avatar"
|
<div class="flex gap-1">
|
||||||
/>
|
<figure class="" v-if="log.actor?.avatar">
|
||||||
<i18n-t
|
<img
|
||||||
v-if="log.action === ActionLogAction.REPORT_UPDATE_CLOSED"
|
alt=""
|
||||||
tag="span"
|
:src="log.actor.avatar?.url"
|
||||||
keypath="{moderator} closed {report}"
|
class="rounded-full"
|
||||||
>
|
width="36"
|
||||||
<template #moderator>
|
height="36"
|
||||||
<router-link
|
/>
|
||||||
:to="{
|
</figure>
|
||||||
name: RouteName.ADMIN_PROFILE,
|
<AccountCircle v-else :size="36" />
|
||||||
params: { id: log.actor.id },
|
</div>
|
||||||
}"
|
<div>
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #report>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.REPORT,
|
|
||||||
params: { reportId: log.object.id },
|
|
||||||
}"
|
|
||||||
>{{
|
|
||||||
$t("report #{report_number}", {
|
|
||||||
report_number: log.object.id,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<i18n-t
|
|
||||||
v-else-if="log.action === ActionLogAction.REPORT_UPDATE_OPENED"
|
|
||||||
tag="span"
|
|
||||||
keypath="{moderator} reopened {report}"
|
|
||||||
>
|
|
||||||
<template #moderator>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.actor.id },
|
|
||||||
}"
|
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #report>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.REPORT,
|
|
||||||
params: { reportId: log.object.id },
|
|
||||||
}"
|
|
||||||
>{{
|
|
||||||
$t("report #{report_number}", {
|
|
||||||
report_number: log.object.id,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<i18n-t
|
|
||||||
v-else-if="log.action === ActionLogAction.REPORT_UPDATE_RESOLVED"
|
|
||||||
tag="span"
|
|
||||||
keypath="{moderator} marked {report} as resolved"
|
|
||||||
>
|
|
||||||
<template #moderator>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.actor.id },
|
|
||||||
}"
|
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #report>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.REPORT,
|
|
||||||
params: { reportId: log.object.id },
|
|
||||||
}"
|
|
||||||
>{{
|
|
||||||
$t("report #{report_number}", {
|
|
||||||
report_number: log.object.id,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<i18n-t
|
|
||||||
v-else-if="log.action === ActionLogAction.NOTE_CREATION"
|
|
||||||
tag="span"
|
|
||||||
keypath="{moderator} added a note on {report}"
|
|
||||||
>
|
|
||||||
<template #moderator>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.actor.id },
|
|
||||||
}"
|
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #report>
|
|
||||||
<router-link
|
|
||||||
v-if="log.object.report"
|
|
||||||
:to="{
|
|
||||||
name: RouteName.REPORT,
|
|
||||||
params: { reportId: log.object.report.id },
|
|
||||||
}"
|
|
||||||
>{{
|
|
||||||
$t("report #{report_number}", {
|
|
||||||
report_number: log.object.report.id,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
</router-link>
|
|
||||||
<span v-else>{{ $t("a non-existent report") }}</span>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<i18n-t
|
|
||||||
v-else-if="log.action === ActionLogAction.EVENT_DELETION"
|
|
||||||
tag="span"
|
|
||||||
keypath='{moderator} deleted an event named "{title}"'
|
|
||||||
>
|
|
||||||
<template #moderator>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.actor.id },
|
|
||||||
}"
|
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #title>
|
|
||||||
<b>{{ log.object.title }}</b>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<i18n-t
|
|
||||||
v-else-if="
|
|
||||||
log.action === ActionLogAction.ACTOR_SUSPENSION &&
|
|
||||||
log.object.__typename == 'Person'
|
|
||||||
"
|
|
||||||
tag="span"
|
|
||||||
keypath="{moderator} suspended profile {profile}"
|
|
||||||
>
|
|
||||||
<template #moderator>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.actor.id },
|
|
||||||
}"
|
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #profile>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.object.id },
|
|
||||||
}"
|
|
||||||
>{{ displayNameAndUsername(log.object) }}
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<i18n-t
|
|
||||||
v-else-if="
|
|
||||||
log.action === ActionLogAction.ACTOR_UNSUSPENSION &&
|
|
||||||
log.object.__typename == 'Person'
|
|
||||||
"
|
|
||||||
tag="span"
|
|
||||||
keypath="{moderator} has unsuspended profile {profile}"
|
|
||||||
>
|
|
||||||
<template #moderator>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.actor.id },
|
|
||||||
}"
|
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #profile>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.object.id },
|
|
||||||
}"
|
|
||||||
>{{ displayNameAndUsername(log.object) }}
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<i18n-t
|
|
||||||
v-else-if="
|
|
||||||
log.action === ActionLogAction.ACTOR_SUSPENSION &&
|
|
||||||
log.object.__typename == 'Group'
|
|
||||||
"
|
|
||||||
tag="span"
|
|
||||||
keypath="{moderator} suspended group {profile}"
|
|
||||||
>
|
|
||||||
<template #moderator>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.actor.id },
|
|
||||||
}"
|
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #profile>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_GROUP_PROFILE,
|
|
||||||
params: { id: log.object.id },
|
|
||||||
}"
|
|
||||||
>{{ displayNameAndUsername(log.object) }}
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<i18n-t
|
|
||||||
v-else-if="
|
|
||||||
log.action === ActionLogAction.ACTOR_UNSUSPENSION &&
|
|
||||||
log.object.__typename == 'Group'
|
|
||||||
"
|
|
||||||
tag="span"
|
|
||||||
keypath="{moderator} has unsuspended group {profile}"
|
|
||||||
>
|
|
||||||
<template #moderator>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.actor.id },
|
|
||||||
}"
|
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #profile>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_GROUP_PROFILE,
|
|
||||||
params: { id: log.object.id },
|
|
||||||
}"
|
|
||||||
>{{ displayNameAndUsername(log.object) }}
|
|
||||||
</router-link>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<i18n-t
|
|
||||||
v-else-if="log.action === ActionLogAction.USER_DELETION"
|
|
||||||
tag="span"
|
|
||||||
keypath="{moderator} has deleted user {user}"
|
|
||||||
>
|
|
||||||
<template #moderator>
|
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.actor.id },
|
|
||||||
}"
|
|
||||||
>@{{ log.actor.preferredUsername }}</router-link
|
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template #user>
|
|
||||||
<router-link
|
|
||||||
v-if="log.object.confirmedAt"
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_USER_PROFILE,
|
|
||||||
params: { id: log.object.id },
|
|
||||||
}"
|
|
||||||
>{{ log.object.email }}
|
|
||||||
</router-link>
|
|
||||||
<b v-else>{{ log.object.email }}</b>
|
|
||||||
</template>
|
|
||||||
</i18n-t>
|
|
||||||
<span
|
|
||||||
v-else-if="
|
|
||||||
log.action === ActionLogAction.COMMENT_DELETION &&
|
|
||||||
log.object.event
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<i18n-t
|
<i18n-t
|
||||||
|
v-if="log.action === ActionLogAction.REPORT_UPDATE_CLOSED"
|
||||||
tag="span"
|
tag="span"
|
||||||
keypath="{moderator} has deleted a comment from {author} under the event {event}"
|
keypath="{moderator} closed {report}"
|
||||||
>
|
>
|
||||||
<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 #report>
|
||||||
<router-link
|
<router-link
|
||||||
v-if="log.object.event && log.object.event.uuid"
|
class="underline"
|
||||||
:to="{
|
:to="{
|
||||||
name: RouteName.EVENT,
|
name: RouteName.REPORT,
|
||||||
params: { uuid: log.object.event.uuid },
|
params: { reportId: log.object.id },
|
||||||
}"
|
}"
|
||||||
>{{ log.object.event.title }}
|
>{{
|
||||||
</router-link>
|
$t("report #{report_number}", {
|
||||||
<b v-else>{{ log.object.event.title }}</b>
|
report_number: log.object.id,
|
||||||
</template>
|
})
|
||||||
<template #author>
|
}}
|
||||||
<router-link
|
|
||||||
:to="{
|
|
||||||
name: RouteName.ADMIN_PROFILE,
|
|
||||||
params: { id: log.object.actor.id },
|
|
||||||
}"
|
|
||||||
>{{ displayNameAndUsername(log.object.actor) }}
|
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
<pre v-html="log.object.text" />
|
|
||||||
</span>
|
|
||||||
<span v-else-if="log.action === ActionLogAction.COMMENT_DELETION">
|
|
||||||
<i18n-t
|
<i18n-t
|
||||||
|
v-else-if="log.action === ActionLogAction.REPORT_UPDATE_OPENED"
|
||||||
tag="span"
|
tag="span"
|
||||||
keypath="{moderator} has deleted a comment from {author}"
|
keypath="{moderator} reopened {report}"
|
||||||
>
|
>
|
||||||
<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 #report>
|
||||||
<router-link
|
<router-link
|
||||||
|
class="underline"
|
||||||
:to="{
|
:to="{
|
||||||
name: RouteName.ADMIN_PROFILE,
|
name: RouteName.REPORT,
|
||||||
params: { id: log.object.actor.id },
|
params: { reportId: log.object.id },
|
||||||
}"
|
}"
|
||||||
>{{ displayNameAndUsername(log.object.actor) }}
|
>{{
|
||||||
|
$t("report #{report_number}", {
|
||||||
|
report_number: log.object.id,
|
||||||
|
})
|
||||||
|
}}
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
<pre v-html="log.object.text" />
|
<i18n-t
|
||||||
</span>
|
v-else-if="
|
||||||
<i18n-t
|
log.action === ActionLogAction.REPORT_UPDATE_RESOLVED
|
||||||
v-else
|
"
|
||||||
tag="span"
|
tag="span"
|
||||||
keypath="{moderator} has done an unknown action"
|
keypath="{moderator} marked {report} as resolved"
|
||||||
>
|
>
|
||||||
<template #moderator>
|
<template #moderator>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{
|
class="underline"
|
||||||
name: RouteName.ADMIN_PROFILE,
|
:to="{
|
||||||
params: { id: log.actor.id },
|
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 },
|
||||||
|
}"
|
||||||
|
>{{
|
||||||
|
$t("report #{report_number}", {
|
||||||
|
report_number: log.object.id,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<i18n-t
|
||||||
|
v-else-if="log.action === ActionLogAction.NOTE_CREATION"
|
||||||
|
tag="span"
|
||||||
|
keypath="{moderator} added a note on {report}"
|
||||||
|
>
|
||||||
|
<template #moderator>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayName(log.actor) }}</router-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #report>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
v-if="log.object.report"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.REPORT,
|
||||||
|
params: { reportId: log.object.report.id },
|
||||||
|
}"
|
||||||
|
>{{
|
||||||
|
$t("report #{report_number}", {
|
||||||
|
report_number: log.object.report.id,
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</router-link>
|
||||||
|
<span v-else>{{ $t("a non-existent report") }}</span>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<i18n-t
|
||||||
|
v-else-if="log.action === ActionLogAction.EVENT_DELETION"
|
||||||
|
tag="span"
|
||||||
|
keypath='{moderator} deleted an event named "{title}"'
|
||||||
|
>
|
||||||
|
<template #moderator>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayName(log.actor) }}</router-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #title>
|
||||||
|
<b>{{ log.object.title }}</b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<i18n-t
|
||||||
|
v-else-if="
|
||||||
|
log.action === ActionLogAction.ACTOR_SUSPENSION &&
|
||||||
|
log.object.__typename == 'Person'
|
||||||
|
"
|
||||||
|
tag="span"
|
||||||
|
keypath="{moderator} suspended profile {profile}"
|
||||||
|
>
|
||||||
|
<template #moderator>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayName(log.actor) }}</router-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #profile>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.object.id },
|
||||||
|
}"
|
||||||
|
>{{ displayNameAndUsername(log.object) }}
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<i18n-t
|
||||||
|
v-else-if="
|
||||||
|
log.action === ActionLogAction.ACTOR_UNSUSPENSION &&
|
||||||
|
log.object.__typename == 'Person'
|
||||||
|
"
|
||||||
|
tag="span"
|
||||||
|
keypath="{moderator} has unsuspended profile {profile}"
|
||||||
|
>
|
||||||
|
<template #moderator>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayName(log.actor) }}</router-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #profile>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.object.id },
|
||||||
|
}"
|
||||||
|
>{{ displayNameAndUsername(log.object) }}
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<i18n-t
|
||||||
|
v-else-if="
|
||||||
|
log.action === ActionLogAction.ACTOR_SUSPENSION &&
|
||||||
|
log.object.__typename == 'Group'
|
||||||
|
"
|
||||||
|
tag="span"
|
||||||
|
keypath="{moderator} suspended group {profile}"
|
||||||
|
>
|
||||||
|
<template #moderator>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayName(log.actor) }}</router-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #profile>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_GROUP_PROFILE,
|
||||||
|
params: { id: log.object.id },
|
||||||
|
}"
|
||||||
|
>{{ displayNameAndUsername(log.object) }}
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<i18n-t
|
||||||
|
v-else-if="
|
||||||
|
log.action === ActionLogAction.ACTOR_UNSUSPENSION &&
|
||||||
|
log.object.__typename == 'Group'
|
||||||
|
"
|
||||||
|
tag="span"
|
||||||
|
keypath="{moderator} has unsuspended group {profile}"
|
||||||
|
>
|
||||||
|
<template #moderator>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayName(log.actor) }}</router-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #profile>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_GROUP_PROFILE,
|
||||||
|
params: { id: log.object.id },
|
||||||
|
}"
|
||||||
|
>{{ displayNameAndUsername(log.object) }}
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<i18n-t
|
||||||
|
v-else-if="log.action === ActionLogAction.USER_DELETION"
|
||||||
|
tag="span"
|
||||||
|
keypath="{moderator} has deleted user {user}"
|
||||||
|
>
|
||||||
|
<template #moderator>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayName(log.actor) }}</router-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #user>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
v-if="log.object.confirmedAt"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_USER_PROFILE,
|
||||||
|
params: { id: log.object.id },
|
||||||
|
}"
|
||||||
|
>{{ log.object.email }}
|
||||||
|
</router-link>
|
||||||
|
<b v-else>{{ log.object.email }}</b>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<span
|
||||||
|
v-else-if="
|
||||||
|
log.action === ActionLogAction.COMMENT_DELETION &&
|
||||||
|
log.object.event
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<i18n-t
|
||||||
|
tag="span"
|
||||||
|
keypath="{moderator} has deleted a comment from {author} under the event {event}"
|
||||||
>
|
>
|
||||||
</template>
|
<template #moderator>
|
||||||
</i18n-t>
|
<router-link
|
||||||
<br />
|
class="underline"
|
||||||
<small>{{ formatDateTimeString(log.insertedAt) }}</small>
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ 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,
|
||||||
|
params: { uuid: log.object.event.uuid },
|
||||||
|
}"
|
||||||
|
>{{ log.object.event.title }}
|
||||||
|
</router-link>
|
||||||
|
<b v-else>{{ log.object.event.title }}</b>
|
||||||
|
</template>
|
||||||
|
<template #author>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.object.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayNameAndUsername(log.object.actor) }}
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<pre v-html="log.object.text" />
|
||||||
|
</span>
|
||||||
|
<span v-else-if="log.action === ActionLogAction.COMMENT_DELETION">
|
||||||
|
<i18n-t
|
||||||
|
tag="span"
|
||||||
|
keypath="{moderator} has deleted a comment from {author}"
|
||||||
|
>
|
||||||
|
<template #moderator>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayName(log.actor) }}</router-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
<template #author>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.object.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayNameAndUsername(log.object.actor) }}
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<pre v-html="log.object.text" />
|
||||||
|
</span>
|
||||||
|
<i18n-t
|
||||||
|
v-else
|
||||||
|
tag="span"
|
||||||
|
keypath="{moderator} has done an unknown action"
|
||||||
|
>
|
||||||
|
<template #moderator>
|
||||||
|
<router-link
|
||||||
|
class="underline"
|
||||||
|
:to="{
|
||||||
|
name: RouteName.ADMIN_PROFILE,
|
||||||
|
params: { id: log.actor.id },
|
||||||
|
}"
|
||||||
|
>{{ displayName(log.actor) }}</router-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
<br />
|
||||||
|
<small>{{ formatDateTimeString(log.insertedAt) }}</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
<!-- <o-button-->
|
variant="danger"
|
||||||
<!-- tag="router-link"-->
|
@click="confirmEventDelete()"
|
||||||
<!-- variant="primary"-->
|
icon-left="delete"
|
||||||
<!-- :to="{ name: RouteName.EDIT_EVENT, params: {eventId: report.event.uuid } }"-->
|
>{{ t("Delete") }}</o-button
|
||||||
<!-- 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>
|
</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,50 +203,52 @@
|
|||||||
>
|
>
|
||||||
</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>
|
||||||
<div class="">
|
<div v-if="comment.actor">
|
||||||
<div class="prose dark:prose-invert">
|
<p>{{ comment.actor.name }}</p>
|
||||||
<span v-if="comment.actor">
|
<p>@{{ comment.actor.preferredUsername }}</p>
|
||||||
<strong>{{ comment.actor.name }}</strong>
|
</div>
|
||||||
<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>
|
||||||
<o-button
|
|
||||||
variant="danger"
|
|
||||||
@click="confirmCommentDelete(comment)"
|
|
||||||
icon-left="delete"
|
|
||||||
size="small"
|
|
||||||
>{{ t("Delete") }}</o-button
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="prose dark:prose-invert" v-html="comment.text" />
|
||||||
|
<o-button
|
||||||
|
variant="danger"
|
||||||
|
@click="confirmCommentDelete(comment)"
|
||||||
|
icon-left="delete"
|
||||||
|
size="small"
|
||||||
|
>{{ t("Delete") }}</o-button
|
||||||
|
>
|
||||||
</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>
|
||||||
|
Loading…
Reference in New Issue
Block a user