refactor: removing useAsyncData for tanstack query (#5262)
* refactor: most places with useAsyncData replaced with tanstack query * refactor report list and report view * refactor organization page to use tanstack query * fix types * refactor collection page and include proper loading state * fix followed projects proper loading state * fix 404 handling * fix organization loading and 404 states * pnpm prepr * refactor: remove useAsyncData on newsletter button * refactor: remove useAsyncData on auth globals fetch * refactor: settings/billing/index.vue to useQuery instead of useAsyncData * refactor: user page to remove useAsyncData * pnpm prepr * fix reports pages * fix notifications page * fix billing page cannot read properties of null and prop warnings * fix refresh causing 404 by removing useBaseFetch and use api-client * fix stale data after removing organization from project * pnpm prepr * fix news erroring in build * fix: project page loads header only after content * fix: user page tanstack problems (start on migrating away from useBaseFetch) * fix: start swapping useBaseFetch usages to api-client * Revert "fix: start swapping useBaseFetch usages to api-client" This reverts commit 3df3fab11d535159132b1288dd7cacc38282b553. * fix: remove debug logging * fix: lint --------- Co-authored-by: Calum H. <calum@modrinth.com> Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
This commit is contained in:
@@ -1,19 +1,39 @@
|
||||
<script setup lang="ts">
|
||||
import { CheckIcon, MailIcon } from '@modrinth/assets'
|
||||
import { ButtonStyled } from '@modrinth/ui'
|
||||
import { ref } from 'vue'
|
||||
import { ButtonStyled, defineMessages, injectModrinthClient, useVIntl } from '@modrinth/ui'
|
||||
import { useQuery, useQueryClient } from '@tanstack/vue-query'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import { useBaseFetch } from '~/composables/fetch.js'
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const auth = await useAuth()
|
||||
const messages = defineMessages({
|
||||
tooltipSubscribe: {
|
||||
id: 'ui.newsletter-button.tooltip',
|
||||
defaultMessage: 'Subscribe to the Modrinth newsletter',
|
||||
},
|
||||
subscribe: {
|
||||
id: 'ui.newsletter-button.subscribe',
|
||||
defaultMessage: 'Subscribe',
|
||||
},
|
||||
subscribed: {
|
||||
id: 'ui.newsletter-button.subscribed',
|
||||
defaultMessage: 'Subscribed!',
|
||||
},
|
||||
})
|
||||
|
||||
const auth = (await useAuth()) as unknown as {
|
||||
value: { user: { id: string; username: string; email: string; created: string } }
|
||||
}
|
||||
const client = injectModrinthClient()
|
||||
const queryClient = useQueryClient()
|
||||
const showSubscriptionConfirmation = ref(false)
|
||||
const showSubscribeButton = useAsyncData(
|
||||
async () => {
|
||||
|
||||
const { data: showSubscribeButton, isSuccess } = useQuery({
|
||||
queryKey: computed(() => ['newsletter', 'subscribed', auth.value?.user?.id]),
|
||||
queryFn: async () => {
|
||||
if (auth.value?.user) {
|
||||
try {
|
||||
const { subscribed } = await useBaseFetch('auth/email/subscribe', {
|
||||
method: 'GET',
|
||||
})
|
||||
const { subscribed } = await client.labrinth.auth_internal.getNewsletterStatus()
|
||||
return !subscribed
|
||||
} catch {
|
||||
return true
|
||||
@@ -22,36 +42,31 @@ const showSubscribeButton = useAsyncData(
|
||||
return false
|
||||
}
|
||||
},
|
||||
{ watch: [auth], server: false },
|
||||
)
|
||||
enabled: computed(() => !!auth.value?.user),
|
||||
})
|
||||
|
||||
async function subscribe() {
|
||||
try {
|
||||
await useBaseFetch('auth/email/subscribe', {
|
||||
method: 'POST',
|
||||
})
|
||||
await client.labrinth.auth_internal.subscribeNewsletter()
|
||||
showSubscriptionConfirmation.value = true
|
||||
} catch {
|
||||
// Ignored
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
showSubscriptionConfirmation.value = false
|
||||
showSubscribeButton.status.value = 'success'
|
||||
showSubscribeButton.data.value = false
|
||||
queryClient.setQueryData(['newsletter', 'subscribed', auth.value?.user?.id], false)
|
||||
}, 2500)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ButtonStyled
|
||||
v-if="showSubscribeButton.status.value === 'success' && showSubscribeButton.data.value"
|
||||
color="brand"
|
||||
type="outlined"
|
||||
>
|
||||
<button v-tooltip="`Subscribe to the Modrinth newsletter`" @click="subscribe">
|
||||
<template v-if="!showSubscriptionConfirmation"> <MailIcon /> Subscribe </template>
|
||||
<template v-else> <CheckIcon /> Subscribed! </template>
|
||||
<ButtonStyled v-if="isSuccess && showSubscribeButton" color="brand" type="outlined">
|
||||
<button v-tooltip="formatMessage(messages.tooltipSubscribe)" @click="subscribe">
|
||||
<template v-if="!showSubscriptionConfirmation">
|
||||
<MailIcon /> {{ formatMessage(messages.subscribe) }}
|
||||
</template>
|
||||
<template v-else> <CheckIcon /> {{ formatMessage(messages.subscribed) }} </template>
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</template>
|
||||
|
||||
@@ -44,8 +44,11 @@
|
||||
import { MessageIcon } from '@modrinth/assets'
|
||||
import { Admonition, ButtonStyled, defineMessages, useVIntl } from '@modrinth/ui'
|
||||
import { capitalizeString } from '@modrinth/utils'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
import { computed, watch } from 'vue'
|
||||
|
||||
import { useBaseFetch } from '~/composables/fetch.js'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const messages = defineMessages({
|
||||
@@ -121,10 +124,10 @@ const apiEndpoint = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const { data: limits } = await useAsyncData<UserLimits | undefined>(
|
||||
`limits-${props.type}`,
|
||||
() => useBaseFetch(apiEndpoint.value, { apiVersion: 3 }) as Promise<UserLimits>,
|
||||
)
|
||||
const { data: limits } = useQuery({
|
||||
queryKey: computed(() => ['limits', props.type]),
|
||||
queryFn: () => useBaseFetch(apiEndpoint.value, { apiVersion: 3 }) as Promise<UserLimits>,
|
||||
})
|
||||
|
||||
const typeName = computed<{ singular: string; plural: string }>(() => {
|
||||
switch (props.type) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="report">
|
||||
<div v-if="report" class="report">
|
||||
<div v-if="report.item_type === 'project'" class="item-info">
|
||||
<nuxt-link
|
||||
v-if="report.project"
|
||||
:to="`/${$getProjectTypeForUrl(report.project.project_type, report.project.loaders)}/${
|
||||
report.project.slug
|
||||
}`"
|
||||
@@ -38,27 +39,29 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="report.item_type === 'version'" class="item-info">
|
||||
<nuxt-link
|
||||
:to="`/project/${report.project.slug}/version/${report.version.id}`"
|
||||
class="iconified-link"
|
||||
>
|
||||
<div class="backed-svg" :class="{ raised: raised }">
|
||||
<VersionIcon />
|
||||
</div>
|
||||
<span class="title">{{ report.version.name }}</span>
|
||||
</nuxt-link>
|
||||
of
|
||||
<nuxt-link :to="`/project/${report.project.slug}`" class="iconified-stacked-link">
|
||||
<Avatar :src="report.project.icon_url" size="xs" no-shadow :raised="raised" />
|
||||
<div class="stacked">
|
||||
<span class="title">{{ report.project.title }}</span>
|
||||
<span>{{
|
||||
formatProjectType(
|
||||
getProjectTypeForUrl(report.project.project_type, report.project.loaders),
|
||||
)
|
||||
}}</span>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
<template v-if="report.version && report.project">
|
||||
<nuxt-link
|
||||
:to="`/project/${report.project.slug}/version/${report.version.id}`"
|
||||
class="iconified-link"
|
||||
>
|
||||
<div class="backed-svg" :class="{ raised: raised }">
|
||||
<VersionIcon />
|
||||
</div>
|
||||
<span class="title">{{ report.version.name }}</span>
|
||||
</nuxt-link>
|
||||
of
|
||||
<nuxt-link :to="`/project/${report.project.slug}`" class="iconified-stacked-link">
|
||||
<Avatar :src="report.project.icon_url" size="xs" no-shadow :raised="raised" />
|
||||
<div class="stacked">
|
||||
<span class="title">{{ report.project.title }}</span>
|
||||
<span>{{
|
||||
formatProjectType(
|
||||
getProjectTypeForUrl(report.project.project_type, report.project.loaders),
|
||||
)
|
||||
}}</span>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
</template>
|
||||
</div>
|
||||
<div v-else class="item-info">
|
||||
<div class="backed-svg" :class="{ raised: raised }">
|
||||
@@ -79,7 +82,7 @@
|
||||
:link="`/${moderation ? 'moderation' : 'dashboard'}/report/${report.id}`"
|
||||
:auth="auth"
|
||||
/>
|
||||
<div class="reporter-info">
|
||||
<div v-if="report.reporterUser" class="reporter-info">
|
||||
<ReportIcon class="inline-svg" />
|
||||
Reported by
|
||||
<span v-if="auth.user.id === report.reporterUser.id">you</span>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<h2>Report details</h2>
|
||||
<ReportInfo :report="report" :show-thread="false" :show-message="false" :auth="auth" />
|
||||
</section>
|
||||
<section class="universal-card">
|
||||
<section v-if="report && thread" class="universal-card">
|
||||
<h2>Messages</h2>
|
||||
<ConversationThread
|
||||
:thread="thread"
|
||||
@@ -21,9 +21,13 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useQuery, useQueryClient } from '@tanstack/vue-query'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import Breadcrumbs from '~/components/ui/Breadcrumbs.vue'
|
||||
import ReportInfo from '~/components/ui/report/ReportInfo.vue'
|
||||
import ConversationThread from '~/components/ui/thread/ConversationThread.vue'
|
||||
import { useBaseFetch } from '~/composables/fetch.js'
|
||||
import { addReportMessage } from '~/helpers/threads.js'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -41,74 +45,90 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const report = ref(null)
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
await fetchReport().then((result) => {
|
||||
report.value = result
|
||||
// Fetch raw report
|
||||
const { data: rawReport } = useQuery({
|
||||
queryKey: computed(() => ['report', props.reportId]),
|
||||
queryFn: async () => {
|
||||
const data = await useBaseFetch(`report/${props.reportId}`)
|
||||
data.item_id = data.item_id.replace(/"/g, '')
|
||||
return data
|
||||
},
|
||||
})
|
||||
|
||||
const { data: rawThread } = await useAsyncData(`thread/${report.value.thread_id}`, () =>
|
||||
useBaseFetch(`thread/${report.value.thread_id}`),
|
||||
// Compute user IDs needed
|
||||
const userIds = computed(() => {
|
||||
if (!rawReport.value) return []
|
||||
const ids = [rawReport.value.reporter]
|
||||
if (rawReport.value.item_type === 'user') {
|
||||
ids.push(rawReport.value.item_id)
|
||||
}
|
||||
return ids
|
||||
})
|
||||
|
||||
// Fetch users
|
||||
const { data: users } = useQuery({
|
||||
queryKey: computed(() => ['users', userIds.value]),
|
||||
queryFn: () => useBaseFetch(`users?ids=${encodeURIComponent(JSON.stringify(userIds.value))}`),
|
||||
enabled: computed(() => userIds.value.length > 0),
|
||||
})
|
||||
|
||||
// Version ID if applicable
|
||||
const versionId = computed(() =>
|
||||
rawReport.value?.item_type === 'version' ? rawReport.value.item_id : null,
|
||||
)
|
||||
|
||||
// Fetch version
|
||||
const { data: version } = useQuery({
|
||||
queryKey: computed(() => ['version', versionId.value]),
|
||||
queryFn: () => useBaseFetch(`version/${versionId.value}`),
|
||||
enabled: computed(() => !!versionId.value),
|
||||
})
|
||||
|
||||
// Project ID
|
||||
const projectId = computed(() => {
|
||||
if (version.value) return version.value.project_id
|
||||
if (rawReport.value?.item_type === 'project') return rawReport.value.item_id
|
||||
return null
|
||||
})
|
||||
|
||||
// Fetch project
|
||||
const { data: project } = useQuery({
|
||||
queryKey: computed(() => ['project', projectId.value]),
|
||||
queryFn: () => useBaseFetch(`project/${projectId.value}`),
|
||||
enabled: computed(() => !!projectId.value),
|
||||
})
|
||||
|
||||
// Assemble the full report object
|
||||
const report = computed(() => {
|
||||
if (!rawReport.value) return null
|
||||
return {
|
||||
...rawReport.value,
|
||||
project: project.value ?? null,
|
||||
version: version.value ?? null,
|
||||
reporterUser: (users.value || []).find((user) => user.id === rawReport.value.reporter),
|
||||
user:
|
||||
rawReport.value.item_type === 'user'
|
||||
? (users.value || []).find((user) => user.id === rawReport.value.item_id)
|
||||
: undefined,
|
||||
}
|
||||
})
|
||||
|
||||
// Fetch thread
|
||||
const { data: rawThread } = useQuery({
|
||||
queryKey: computed(() => ['thread', report.value?.thread_id]),
|
||||
queryFn: () => useBaseFetch(`thread/${report.value.thread_id}`),
|
||||
enabled: computed(() => !!report.value?.thread_id),
|
||||
})
|
||||
|
||||
const thread = computed(() =>
|
||||
rawThread.value && report.value ? addReportMessage(rawThread.value, report.value) : null,
|
||||
)
|
||||
const thread = computed(() => addReportMessage(rawThread.value, report.value))
|
||||
|
||||
async function updateThread(newThread) {
|
||||
rawThread.value = newThread
|
||||
report.value = await fetchReport()
|
||||
}
|
||||
|
||||
async function fetchReport() {
|
||||
const { data: rawReport } = await useAsyncData(`report/${props.reportId}`, () =>
|
||||
useBaseFetch(`report/${props.reportId}`),
|
||||
)
|
||||
rawReport.value.item_id = rawReport.value.item_id.replace(/"/g, '')
|
||||
|
||||
const userIds = []
|
||||
userIds.push(rawReport.value.reporter)
|
||||
if (rawReport.value.item_type === 'user') {
|
||||
userIds.push(rawReport.value.item_id)
|
||||
}
|
||||
|
||||
const versionId = rawReport.value.item_type === 'version' ? rawReport.value.item_id : null
|
||||
|
||||
let users = []
|
||||
if (userIds.length > 0) {
|
||||
const { data: usersVal } = await useAsyncData(`users?ids=${JSON.stringify(userIds)}`, () =>
|
||||
useBaseFetch(`users?ids=${encodeURIComponent(JSON.stringify(userIds))}`),
|
||||
)
|
||||
users = usersVal.value
|
||||
}
|
||||
|
||||
let version = null
|
||||
if (versionId) {
|
||||
const { data: versionVal } = await useAsyncData(`version/${versionId}`, () =>
|
||||
useBaseFetch(`version/${versionId}`),
|
||||
)
|
||||
version = versionVal.value
|
||||
}
|
||||
|
||||
const projectId = version
|
||||
? version.project_id
|
||||
: rawReport.value.item_type === 'project'
|
||||
? rawReport.value.item_id
|
||||
: null
|
||||
|
||||
let project = null
|
||||
if (projectId) {
|
||||
const { data: projectVal } = await useAsyncData(`project/${projectId}`, () =>
|
||||
useBaseFetch(`project/${projectId}`),
|
||||
)
|
||||
project = projectVal.value
|
||||
}
|
||||
|
||||
const reportData = rawReport.value
|
||||
reportData.project = project
|
||||
reportData.version = version
|
||||
reportData.reporterUser = users.find((user) => user.id === rawReport.value.reporter)
|
||||
if (rawReport.value.item_type === 'user') {
|
||||
reportData.user = users.find((user) => user.id === rawReport.value.item_id)
|
||||
}
|
||||
return reportData
|
||||
queryClient.setQueryData(['thread', report.value?.thread_id], newThread)
|
||||
await queryClient.invalidateQueries({ queryKey: ['report', props.reportId] })
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -21,12 +21,15 @@
|
||||
:auth="auth"
|
||||
class="universal-card recessed"
|
||||
/>
|
||||
<p v-if="reports.length === 0">You don't have any active reports.</p>
|
||||
<p v-if="filteredReports.length === 0">You don't have any active reports.</p>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Chips } from '@modrinth/ui'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
import ReportInfo from '~/components/ui/report/ReportInfo.vue'
|
||||
import { useBaseFetch } from '~/composables/fetch.js'
|
||||
import { addReportMessage } from '~/helpers/threads.js'
|
||||
import { asEncodedJsonArray, fetchSegmented } from '~/utils/fetch-helpers.ts'
|
||||
|
||||
@@ -43,77 +46,113 @@ const props = defineProps({
|
||||
|
||||
const viewMode = ref('open')
|
||||
const reasonFilter = ref('All')
|
||||
const reports = ref([])
|
||||
|
||||
const MAX_REPORTS = 1500
|
||||
|
||||
let { data: rawReports } = await useAsyncData('report', () =>
|
||||
useBaseFetch(`report?count=${MAX_REPORTS}`),
|
||||
)
|
||||
|
||||
rawReports = rawReports.value.map((report) => {
|
||||
report.item_id = report.item_id.replace(/"/g, '')
|
||||
return report
|
||||
const { data: rawReportsData } = useQuery({
|
||||
queryKey: ['reports', MAX_REPORTS],
|
||||
queryFn: () => useBaseFetch(`report?count=${MAX_REPORTS}`),
|
||||
placeholderData: [],
|
||||
})
|
||||
|
||||
const reporterUsers = rawReports.map((report) => report.reporter)
|
||||
const reportedUsers = rawReports
|
||||
.filter((report) => report.item_type === 'user')
|
||||
.map((report) => report.item_id)
|
||||
const versionReports = rawReports.filter((report) => report.item_type === 'version')
|
||||
const versionIds = [...new Set(versionReports.map((report) => report.item_id))]
|
||||
const userIds = [...new Set(reporterUsers.concat(reportedUsers))]
|
||||
const threadIds = [
|
||||
...new Set(rawReports.filter((report) => report.thread_id).map((report) => report.thread_id)),
|
||||
]
|
||||
const reasons = ['All', ...new Set(rawReports.map((report) => report.report_type))]
|
||||
const rawReports = computed(() =>
|
||||
rawReportsData.value.map((report) => ({
|
||||
...report,
|
||||
item_id: report.item_id.replace(/"/g, ''),
|
||||
})),
|
||||
)
|
||||
|
||||
const [{ data: users }, { data: versions }, { data: threads }] = await Promise.all([
|
||||
await useAsyncData(`users?ids=${JSON.stringify(userIds)}`, () =>
|
||||
fetchSegmented(userIds, (ids) => `users?ids=${asEncodedJsonArray(ids)}`),
|
||||
),
|
||||
await useAsyncData(`versions?ids=${JSON.stringify(versionIds)}`, () =>
|
||||
fetchSegmented(versionIds, (ids) => `versions?ids=${asEncodedJsonArray(ids)}`),
|
||||
),
|
||||
await useAsyncData(`threads?ids=${JSON.stringify(threadIds)}`, () =>
|
||||
fetchSegmented(threadIds, (ids) => `threads?ids=${asEncodedJsonArray(ids)}`),
|
||||
const reporterUsers = computed(() => rawReports.value.map((report) => report.reporter))
|
||||
const reportedUsers = computed(() =>
|
||||
rawReports.value.filter((report) => report.item_type === 'user').map((report) => report.item_id),
|
||||
)
|
||||
const versionReports = computed(() =>
|
||||
rawReports.value.filter((report) => report.item_type === 'version'),
|
||||
)
|
||||
const versionIds = computed(() => [
|
||||
...new Set(versionReports.value.map((report) => report.item_id)),
|
||||
])
|
||||
const userIds = computed(() => [...new Set(reporterUsers.value.concat(reportedUsers.value))])
|
||||
const threadIds = computed(() => [
|
||||
...new Set(
|
||||
rawReports.value.filter((report) => report.thread_id).map((report) => report.thread_id),
|
||||
),
|
||||
])
|
||||
const reasons = computed(() => [
|
||||
'All',
|
||||
...new Set(rawReports.value.map((report) => report.report_type)),
|
||||
])
|
||||
|
||||
const reportedProjects = rawReports
|
||||
.filter((report) => report.item_type === 'project')
|
||||
.map((report) => report.item_id)
|
||||
const versionProjects = versions.value.map((version) => version.project_id)
|
||||
const projectIds = [...new Set(reportedProjects.concat(versionProjects))]
|
||||
|
||||
const { data: projects } = await useAsyncData(`projects?ids=${JSON.stringify(projectIds)}`, () =>
|
||||
fetchSegmented(projectIds, (ids) => `projects?ids=${asEncodedJsonArray(ids)}`),
|
||||
)
|
||||
|
||||
reports.value = rawReports.map((report) => {
|
||||
report.reporterUser = users.value.find((user) => user.id === report.reporter)
|
||||
if (report.item_type === 'user') {
|
||||
report.user = users.value.find((user) => user.id === report.item_id)
|
||||
} else if (report.item_type === 'project') {
|
||||
report.project = projects.value.find((project) => project.id === report.item_id)
|
||||
} else if (report.item_type === 'version') {
|
||||
report.version = versions.value.find((version) => version.id === report.item_id)
|
||||
report.project = projects.value.find((project) => project.id === report.version.project_id)
|
||||
}
|
||||
if (report.thread_id) {
|
||||
report.thread = addReportMessage(
|
||||
threads.value.find((thread) => report.thread_id === thread.id),
|
||||
report,
|
||||
)
|
||||
}
|
||||
report.open = true
|
||||
return report
|
||||
const { data: users } = useQuery({
|
||||
queryKey: computed(() => ['users', userIds.value]),
|
||||
queryFn: () => fetchSegmented(userIds.value, (ids) => `users?ids=${asEncodedJsonArray(ids)}`),
|
||||
enabled: computed(() => userIds.value.length > 0),
|
||||
placeholderData: [],
|
||||
})
|
||||
|
||||
const { data: versions } = useQuery({
|
||||
queryKey: computed(() => ['versions', versionIds.value]),
|
||||
queryFn: () =>
|
||||
fetchSegmented(versionIds.value, (ids) => `versions?ids=${asEncodedJsonArray(ids)}`),
|
||||
enabled: computed(() => versionIds.value.length > 0),
|
||||
placeholderData: [],
|
||||
})
|
||||
|
||||
const { data: threads } = useQuery({
|
||||
queryKey: computed(() => ['threads', threadIds.value]),
|
||||
queryFn: () => fetchSegmented(threadIds.value, (ids) => `threads?ids=${asEncodedJsonArray(ids)}`),
|
||||
enabled: computed(() => threadIds.value.length > 0),
|
||||
placeholderData: [],
|
||||
})
|
||||
|
||||
const reportedProjects = computed(() =>
|
||||
rawReports.value
|
||||
.filter((report) => report.item_type === 'project')
|
||||
.map((report) => report.item_id),
|
||||
)
|
||||
const versionProjects = computed(() => versions.value.map((version) => version.project_id))
|
||||
const projectIds = computed(() => [
|
||||
...new Set(reportedProjects.value.concat(versionProjects.value)),
|
||||
])
|
||||
|
||||
const { data: projects } = useQuery({
|
||||
queryKey: computed(() => ['projects', projectIds.value]),
|
||||
queryFn: () =>
|
||||
fetchSegmented(projectIds.value, (ids) => `projects?ids=${asEncodedJsonArray(ids)}`),
|
||||
enabled: computed(() => projectIds.value.length > 0),
|
||||
placeholderData: [],
|
||||
})
|
||||
|
||||
const userMap = computed(() => new Map(users.value.map((u) => [u.id, u])))
|
||||
const versionMap = computed(() => new Map(versions.value.map((v) => [v.id, v])))
|
||||
const projectMap = computed(() => new Map(projects.value.map((p) => [p.id, p])))
|
||||
const threadMap = computed(() => new Map(threads.value.map((t) => [t.id, t])))
|
||||
|
||||
const reports = computed(() =>
|
||||
rawReports.value.map((report) => {
|
||||
const enrichedReport = { ...report }
|
||||
enrichedReport.reporterUser = userMap.value.get(report.reporter)
|
||||
if (report.item_type === 'user') {
|
||||
enrichedReport.user = userMap.value.get(report.item_id)
|
||||
} else if (report.item_type === 'project') {
|
||||
enrichedReport.project = projectMap.value.get(report.item_id)
|
||||
} else if (report.item_type === 'version') {
|
||||
enrichedReport.version = versionMap.value.get(report.item_id)
|
||||
enrichedReport.project = projectMap.value.get(enrichedReport.version?.project_id)
|
||||
}
|
||||
if (report.thread_id) {
|
||||
const thread = threadMap.value.get(report.thread_id)
|
||||
enrichedReport.thread = thread ? addReportMessage(thread, enrichedReport) : null
|
||||
}
|
||||
enrichedReport.open = true
|
||||
return enrichedReport
|
||||
}),
|
||||
)
|
||||
|
||||
const filteredReports = computed(() =>
|
||||
reports.value?.filter(
|
||||
(x) =>
|
||||
(props.moderation || x.reporterUser.id === props.auth.user.id) &&
|
||||
(props.moderation || x.reporterUser?.id === props.auth.user.id) &&
|
||||
(viewMode.value === 'open' ? x.open : !x.open) &&
|
||||
(reasonFilter.value === 'All' || reasonFilter.value === x.report_type),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user