mirror of
https://github.com/HangarMC/Hangar.git
synced 2024-11-21 01:21:54 +08:00
Improvements to report and approval pages
This commit is contained in:
parent
be6c36da56
commit
f7a6ad553c
@ -15,26 +15,26 @@ const props = defineProps<{
|
||||
<template>
|
||||
<ul v-if="projects.length">
|
||||
<template v-for="project in projects" :key="project.projectId">
|
||||
<hr class="mb-3" />
|
||||
<hr />
|
||||
<li>
|
||||
<div class="flex">
|
||||
<div class="flex-grow">
|
||||
<div class="flex <md:flex-col items-center">
|
||||
<div class="basis-full md:basis-3/12">
|
||||
{{ i18n.t("projectApproval.description", [project.changeRequester, `${project.namespace.owner}/${project.namespace.slug}`]) }}
|
||||
<Link :to="`/${project.namespace.owner}/${project.namespace.slug}`" target="_blank">
|
||||
<IconMdiOpenInNew />
|
||||
</Link>
|
||||
</div>
|
||||
<div class="flex-shrink">
|
||||
<VisibilityChangerModal :prop-visibility="project.visibility" type="project" :post-url="`projects/visibility/${project.projectId}`" />
|
||||
<div class="basis-full md:basis-6/12 flex-grow">
|
||||
<Markdown :raw="project.comment" />
|
||||
</div>
|
||||
<div class="basis-full">
|
||||
<Markdown :raw="project.comment" class="mb-3" />
|
||||
<div class="">
|
||||
<VisibilityChangerModal :prop-visibility="project.visibility" type="project" :post-url="`projects/visibility/${project.projectId}`" />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<Alert v-else type="danger">
|
||||
<Alert v-else type="info">
|
||||
{{ i18n.t("projectApproval.noProjects") }}
|
||||
</Alert>
|
||||
</template>
|
||||
|
@ -89,13 +89,13 @@ function requiresConfirmation(): boolean {
|
||||
<template>
|
||||
<div v-if="project.visibility !== Visibility.PUBLIC" class="mb-4">
|
||||
<Alert v-if="project.visibility === Visibility.NEEDS_CHANGES" type="danger">
|
||||
<div class="flex">
|
||||
<div class="flex-grow text-bold">{{ i18n.t("visibility.notice." + project.visibility) }}</div>
|
||||
<div v-if="hasPerms(NamedPermission.EDIT_PAGE)" class="flex-shrink">
|
||||
<div>
|
||||
<div class="text-bold">{{ i18n.t("visibility.notice." + project.visibility) }}</div>
|
||||
<Markdown :raw="project.lastVisibilityChangeComment || 'Unknown'" class="mt-2" inline />
|
||||
<div v-if="hasPerms(NamedPermission.EDIT_PAGE)">
|
||||
<Button @click="sendForApproval">{{ i18n.t("project.sendForApproval") }}</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Markdown :raw="project.lastVisibilityChangeComment || 'Unknown'" class="mt-2" inline />
|
||||
</Alert>
|
||||
<Alert v-else-if="project.visibility === Visibility.SOFT_DELETE" type="danger">
|
||||
{{ i18n.t("visibility.notice." + project.visibility, [project.lastVisibilityChangeUserName]) }}
|
||||
|
@ -77,7 +77,7 @@
|
||||
"user": {
|
||||
"profile": "Profile",
|
||||
"notifications": "Notifications",
|
||||
"flags": "Flags",
|
||||
"flags": "Reports",
|
||||
"settings": "Account settings",
|
||||
"apiKeys": "API keys",
|
||||
"projectApprovals": "Project approvals",
|
||||
@ -660,7 +660,7 @@
|
||||
"visibility": {
|
||||
"notice": {
|
||||
"new": "This project will not be shown to others until a version has been uploaded.",
|
||||
"needsChanges": "This project requires changes",
|
||||
"needsChanges": "This project requires changes:",
|
||||
"needsApproval": "You have sent the project for review",
|
||||
"softDelete": "Project deleted by {0}"
|
||||
},
|
||||
@ -727,8 +727,8 @@
|
||||
"continue": "Continue"
|
||||
},
|
||||
"flags": {
|
||||
"header": "Flags for",
|
||||
"noFlags": "No flags found",
|
||||
"header": "Reports for",
|
||||
"noFlags": "No reports found",
|
||||
"resolved": "Yes, by {0} on {1}",
|
||||
"notResolved": "No"
|
||||
},
|
||||
@ -747,9 +747,9 @@
|
||||
"downloads": "Downloads",
|
||||
"totalDownloads": "Total Downloads",
|
||||
"unsafeDownloads": "Unsafe Downloads",
|
||||
"flags": "Flags",
|
||||
"openedFlags": "Opened Flags",
|
||||
"closedFlags": "Closed Flags"
|
||||
"flags": "Reports",
|
||||
"openedFlags": "Opened Reports",
|
||||
"closedFlags": "Closed Reports"
|
||||
},
|
||||
"health": {
|
||||
"title": "Hangar Health Report",
|
||||
@ -835,10 +835,8 @@
|
||||
"success": "Updated platform versions"
|
||||
},
|
||||
"flagReview": {
|
||||
"title": "Flags",
|
||||
"noFlags": "There are no flags to review.",
|
||||
"msgUser": "Message user",
|
||||
"msgProjectOwner": "Message owner",
|
||||
"title": "Reports",
|
||||
"noFlags": "There are no reports to review.",
|
||||
"markResolved": "Mark resolved",
|
||||
"line1": "{0} reported {1} on {2}",
|
||||
"line2": "Reason: {0}",
|
||||
@ -847,7 +845,7 @@
|
||||
"userActivity": {
|
||||
"title": "{0}'s Activity",
|
||||
"reviews": "Reviews",
|
||||
"flags": "Flags",
|
||||
"flags": "Reports",
|
||||
"reviewApproved": "Review Approved",
|
||||
"flagResolved": "Flag Resolved",
|
||||
"error": {
|
||||
|
@ -10,28 +10,31 @@ import { useHead } from "@vueuse/head";
|
||||
import { useSeo } from "~/composables/useSeo";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
interface ApprovalProjects {
|
||||
needsApproval: ProjectApproval[];
|
||||
waitingProjects: ProjectApproval[];
|
||||
}
|
||||
|
||||
const ctx = useContext();
|
||||
const i18n = useI18n();
|
||||
const route = useRoute();
|
||||
const data = await useInternalApi<{ needsApproval: ProjectApproval[]; waitingProjects: ProjectApproval[] }>("admin/approval/projects").catch((e) =>
|
||||
const data: ApprovalProjects = (await useInternalApi<ApprovalProjects>("admin/approval/projects").catch((e) =>
|
||||
handleRequestError(e, ctx, i18n)
|
||||
);
|
||||
)) as ApprovalProjects;
|
||||
|
||||
useHead(useSeo(i18n.t("projectApproval.title"), null, route, null));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<Card>
|
||||
<template #header>{{ i18n.t("projectApproval.awaitingChanges") }}</template>
|
||||
|
||||
<AdminProjectList :projects="data.waitingProjects" />
|
||||
</Card>
|
||||
<div class="space-y-3">
|
||||
<Card>
|
||||
<template #header>{{ i18n.t("projectApproval.needsApproval") }}</template>
|
||||
|
||||
<AdminProjectList :projects="data.needsApproval" />
|
||||
</Card>
|
||||
<Card>
|
||||
<template #header>{{ i18n.t("projectApproval.awaitingChanges") }}</template>
|
||||
<AdminProjectList :projects="data.waitingProjects" />
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -13,6 +13,7 @@ import Tag from "~/components/Tag.vue";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { useSeo } from "~/composables/useSeo";
|
||||
import { useRoute } from "vue-router";
|
||||
import Button from "~/lib/components/design/Button.vue";
|
||||
|
||||
const i18n = useI18n();
|
||||
const ctx = useContext();
|
||||
@ -113,8 +114,10 @@ function getCount(entry: ReviewQueueEntry, ..._actions: ReviewAction[]) {
|
||||
</template>
|
||||
<template #item_startBtn="{ item }">
|
||||
<Link :to="{ name: 'user-project-versions-version-platform-reviews', params: getRouteParams(item) }" nuxt>
|
||||
<IconMdiPlay></IconMdiPlay>
|
||||
{{ i18n.t("version.page.reviewStart") }}
|
||||
<Button>
|
||||
<IconMdiPlay />
|
||||
{{ i18n.t("version.page.reviewStart") }}
|
||||
</Button>
|
||||
</Link>
|
||||
</template>
|
||||
</SortableTable>
|
||||
|
@ -50,25 +50,27 @@ function resolve(flag: Flag) {
|
||||
<template>
|
||||
<PageTitle>{{ i18n.t("flagReview.title") }}</PageTitle>
|
||||
<template v-if="flags.length > 0">
|
||||
<Card v-for="flag in flags" :key="flag.id" class="flex gap-2 items-center">
|
||||
<UserAvatar :username="flag.reportedByName"></UserAvatar>
|
||||
<div class="flex flex-col flex-grow">
|
||||
<h2>
|
||||
{{
|
||||
i18n.t("flagReview.line1", [flag.reportedByName, `${flag.projectNamespace.owner}/${flag.projectNamespace.slug}`, i18n.d(flag.createdAt, "time")])
|
||||
}}
|
||||
<router-link :to="`/${flag.projectNamespace.owner}/${flag.projectNamespace.slug}`" target="_blank">
|
||||
<icon-mdi-open-in-new class="inline ml-1"></icon-mdi-open-in-new>
|
||||
</router-link>
|
||||
</h2>
|
||||
<small>{{ i18n.t("flagReview.line2", [i18n.t(flag.reason)]) }}</small>
|
||||
<small>{{ i18n.t("flagReview.line3", [flag.comment]) }}</small>
|
||||
</div>
|
||||
<Link fix-href="$util.forumUrl(flag.reportedByName)">{{ i18n.t("flagReview.msgUser") }}</Link>
|
||||
<Link fix-href="$util.forumUrl(flag.projectNamespace.owner)">{{ i18n.t("flagReview.msgProjectOwner") }}</Link>
|
||||
<VisibilityChangerModal :prop-visibility="flag.projectVisibility" type="project" :post-url="`projects/visibility/${flag.projectId}`" />
|
||||
<Button :disabled="loading[flag.id]" @click="resolve(flag)">{{ i18n.t("flagReview.markResolved") }}</Button>
|
||||
</Card>
|
||||
<div class="space-y-2">
|
||||
<Card v-for="flag in flags" :key="flag.id" class="flex space-x-1 items-center">
|
||||
<UserAvatar :username="flag.reportedByName" size="sm"></UserAvatar>
|
||||
<div class="flex flex-col flex-grow">
|
||||
<h2>
|
||||
{{
|
||||
i18n.t("flagReview.line1", [flag.reportedByName, `${flag.projectNamespace.owner}/${flag.projectNamespace.slug}`, i18n.d(flag.createdAt, "time")])
|
||||
}}
|
||||
<router-link :to="`/${flag.projectNamespace.owner}/${flag.projectNamespace.slug}`" target="_blank">
|
||||
<icon-mdi-open-in-new class="inline ml-1"></icon-mdi-open-in-new>
|
||||
</router-link>
|
||||
</h2>
|
||||
<small>{{ i18n.t("flagReview.line2", [i18n.t(flag.reason)]) }}</small>
|
||||
<small>{{ i18n.t("flagReview.line3", [flag.comment]) }}</small>
|
||||
</div>
|
||||
<!-- todo: send notification to repository owner when visibility is changed -->
|
||||
<VisibilityChangerModal :prop-visibility="flag.projectVisibility" type="project" :post-url="`projects/visibility/${flag.projectId}`" />
|
||||
<!-- todo: add ability to send custom notification to reporter when resolved -->
|
||||
<Button :disabled="loading[flag.id]" @click="resolve(flag)">{{ i18n.t("flagReview.markResolved") }}</Button>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else>
|
||||
{{ i18n.t("flagReview.noFlags") }}
|
||||
|
Loading…
Reference in New Issue
Block a user