mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 17:14:50 +00:00
chore: improve moderation ux (#6035)
* feat: save project review queue filters * reduce unnecessary network calls + prepr * missed file * ui tweaks * add fucked up * add label + prepr * prepr * update legacy badge labels * globe * fix margin * be more reasonable * pending state * fix double review, prepr * small badge text
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
<template>
|
||||
<div class="shadow-card rounded-2xl border border-surface-5 bg-surface-3 p-4">
|
||||
<div class="shadow-card rounded-2xl border border-solid border-surface-5 bg-surface-3 p-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-4">
|
||||
<Avatar
|
||||
:src="queueEntry.project.icon_url"
|
||||
size="4rem"
|
||||
class="rounded-2xl border border-surface-5 bg-surface-4 !shadow-none"
|
||||
/>
|
||||
<NuxtLink
|
||||
:to="`/project/${queueEntry.project.slug}`"
|
||||
target="_blank"
|
||||
tabindex="-1"
|
||||
class="flex"
|
||||
>
|
||||
<Avatar
|
||||
:src="queueEntry.project.icon_url"
|
||||
size="4rem"
|
||||
class="rounded-2xl border border-surface-5 bg-surface-4 !shadow-none"
|
||||
/>
|
||||
</NuxtLink>
|
||||
<div class="flex flex-col gap-1.5">
|
||||
<div class="flex items-center gap-2">
|
||||
<NuxtLink
|
||||
@@ -22,11 +29,15 @@
|
||||
<component
|
||||
:is="getProjectTypeIcon(queueEntry.project.project_types[0] as any)"
|
||||
aria-hidden="true"
|
||||
class="h-4 w-4"
|
||||
class="size-4"
|
||||
/>
|
||||
<span class="text-sm font-medium text-secondary">
|
||||
{{
|
||||
queueEntry.project.project_types.map((t) => formatProjectType(t, true)).join(', ')
|
||||
queueEntry.project.project_types.length === 0
|
||||
? '???'
|
||||
: queueEntry.project.project_types
|
||||
.map((t) => formatProjectType(t, true))
|
||||
.join(', ')
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
@@ -35,37 +46,39 @@
|
||||
class="flex items-center gap-2 rounded-full border border-solid border-surface-5 bg-surface-4 px-2.5 py-1"
|
||||
>
|
||||
<span class="text-sm text-secondary">Requesting</span>
|
||||
<Badge :type="queueEntry.project.requested_status" class="status" />
|
||||
<Badge :type="queueEntry.project.requested_status" class="text-sm" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="queueEntry.owner" class="flex items-center gap-1">
|
||||
<Avatar
|
||||
:src="queueEntry.owner.user.avatar_url"
|
||||
size="1.5rem"
|
||||
circle
|
||||
class="border border-surface-5 bg-surface-4 !shadow-none"
|
||||
/>
|
||||
<div v-if="queueEntry.ownership?.kind === 'user'">
|
||||
<NuxtLink
|
||||
:to="`/user/${queueEntry.owner.user.username}`"
|
||||
:to="`/user/${queueEntry.ownership.id}`"
|
||||
target="_blank"
|
||||
class="text-sm font-medium text-secondary hover:underline"
|
||||
class="flex w-fit min-w-40 items-center gap-1 text-sm font-medium text-secondary hover:underline"
|
||||
>
|
||||
{{ queueEntry.owner.user.username }}
|
||||
<Avatar
|
||||
:src="queueEntry.ownership.icon_url"
|
||||
size="1.5rem"
|
||||
circle
|
||||
class="border border-surface-5 bg-surface-4 !shadow-none"
|
||||
/>
|
||||
{{ queueEntry.ownership.name }}
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div v-else-if="queueEntry.org" class="flex items-center gap-1">
|
||||
<div
|
||||
v-else-if="queueEntry.ownership?.kind === 'organization'"
|
||||
class="flex items-center gap-1"
|
||||
>
|
||||
<Avatar
|
||||
:src="queueEntry.org.icon_url"
|
||||
:src="queueEntry.ownership.icon_url"
|
||||
size="1.5rem"
|
||||
circle
|
||||
class="border border-surface-5 bg-surface-4 !shadow-none"
|
||||
/>
|
||||
<NuxtLink
|
||||
:to="`/organization/${queueEntry.org.slug}`"
|
||||
:to="`/organization/${queueEntry.ownership.id}`"
|
||||
target="_blank"
|
||||
class="text-sm font-medium text-secondary hover:underline"
|
||||
>
|
||||
{{ queueEntry.org.name }}
|
||||
{{ queueEntry.ownership.name }}
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
@@ -84,25 +97,20 @@
|
||||
</span>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<ButtonStyled circular color="orange">
|
||||
<button @click="openProjectForReview">
|
||||
<ScaleIcon class="size-5" />
|
||||
<ButtonStyled circular>
|
||||
<button v-tooltip="'Copy ID'" @click="copyId">
|
||||
<ClipboardCopyIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled circular>
|
||||
<OverflowMenu :options="quickActions" :dropdown-id="`${baseId}-quick-actions`">
|
||||
<template #default>
|
||||
<EllipsisVerticalIcon class="size-4" />
|
||||
</template>
|
||||
<template #copy-id>
|
||||
<ClipboardCopyIcon />
|
||||
<span class="hidden sm:inline">Copy ID</span>
|
||||
</template>
|
||||
<template #copy-link>
|
||||
<LinkIcon />
|
||||
<span class="hidden sm:inline">Copy link</span>
|
||||
</template>
|
||||
</OverflowMenu>
|
||||
<button v-tooltip="'Copy link'" @click="copyLink">
|
||||
<LinkIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled v-tooltip="'Begin review'" circular color="orange">
|
||||
<button @click="openProjectForReview">
|
||||
<ScaleIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,15 +119,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ClipboardCopyIcon, EllipsisVerticalIcon, LinkIcon, ScaleIcon } from '@modrinth/assets'
|
||||
import { ClipboardCopyIcon, LinkIcon, ScaleIcon } from '@modrinth/assets'
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
ButtonStyled,
|
||||
getProjectTypeIcon,
|
||||
injectNotificationManager,
|
||||
OverflowMenu,
|
||||
type OverflowMenuOption,
|
||||
useFormatDateTime,
|
||||
useRelativeTime,
|
||||
} from '@modrinth/ui'
|
||||
@@ -143,8 +149,6 @@ const formatDateTimeFull = useFormatDateTime({
|
||||
timeZone: 'UTC',
|
||||
})
|
||||
|
||||
const baseId = useId()
|
||||
|
||||
const props = defineProps<{
|
||||
queueEntry: ModerationProject
|
||||
}>()
|
||||
@@ -185,34 +189,27 @@ const formattedDate = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const quickActions: OverflowMenuOption[] = [
|
||||
{
|
||||
id: 'copy-link',
|
||||
action: () => {
|
||||
const base = window.location.origin
|
||||
const projectUrl = `${base}/project/${props.queueEntry.project.slug}`
|
||||
navigator.clipboard.writeText(projectUrl).then(() => {
|
||||
addNotification({
|
||||
type: 'success',
|
||||
title: 'Project link copied',
|
||||
text: 'The link to this project has been copied to your clipboard.',
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'copy-id',
|
||||
action: () => {
|
||||
navigator.clipboard.writeText(props.queueEntry.project.id).then(() => {
|
||||
addNotification({
|
||||
type: 'success',
|
||||
title: 'Project ID copied',
|
||||
text: 'The ID of this project has been copied to your clipboard.',
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
]
|
||||
function copyLink() {
|
||||
const base = window.location.origin
|
||||
const projectUrl = `${base}/project/${props.queueEntry.project.slug}`
|
||||
navigator.clipboard.writeText(projectUrl).then(() => {
|
||||
addNotification({
|
||||
type: 'success',
|
||||
title: 'Project link copied',
|
||||
text: 'The link to this project has been copied to your clipboard.',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function copyId() {
|
||||
navigator.clipboard.writeText(props.queueEntry.project.id).then(() => {
|
||||
addNotification({
|
||||
type: 'success',
|
||||
title: 'Project ID copied',
|
||||
text: 'The ID of this project has been copied to your clipboard.',
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function openProjectForReview() {
|
||||
emit('startFromProject', props.queueEntry.project.id)
|
||||
|
||||
Reference in New Issue
Block a user