fix: random 404s (#6138)

* fix: random 404s when navigating from user, org, or collection page to project

* more

* revert server

* clean names

* prepr
This commit is contained in:
Prospector
2026-05-19 11:11:48 -07:00
committed by GitHub
parent f106dc580f
commit 302b60d89c
45 changed files with 127 additions and 123 deletions
@@ -233,7 +233,7 @@ const visibleNags = computed<Nag[]>(() => {
link: { link: {
path: 'moderation', path: 'moderation',
title: messages.visitModerationPage, title: messages.visitModerationPage,
shouldShow: () => props.routeName !== 'type-id-moderation', shouldShow: () => props.routeName !== 'type-project-moderation',
}, },
}) })
} }
@@ -739,8 +739,8 @@ async function navigateToNextUnlockedProject(): Promise<boolean> {
} else { } else {
// Fallback: use project ID (will trigger middleware redirect) // Fallback: use project ID (will trigger middleware redirect)
navigateTo({ navigateTo({
name: 'type-id', name: 'type-project',
params: { type: 'project', id: next.projectId }, params: { type: 'project', project: next.projectId },
state: { showChecklist: true }, state: { showChecklist: true },
}) })
} }
@@ -1067,8 +1067,8 @@ async function skipToNextProject() {
} else { } else {
// Fallback: use project ID // Fallback: use project ID
navigateTo({ navigateTo({
name: 'type-id', name: 'type-project',
params: { type: 'project', id }, params: { type: 'project', project: id },
state: { showChecklist: true }, state: { showChecklist: true },
}) })
} }
@@ -2127,8 +2127,8 @@ async function endChecklist(status?: string) {
} else { } else {
// Fallback: use project ID // Fallback: use project ID
navigateTo({ navigateTo({
name: 'type-id', name: 'type-project',
params: { type: 'project', id }, params: { type: 'project', project: id },
state: { showChecklist: true }, state: { showChecklist: true },
}) })
} }
+1 -1
View File
@@ -1148,7 +1148,7 @@ const isDiscovering = computed(
) )
const isDiscoveringSubpage = computed( const isDiscoveringSubpage = computed(
() => route.name && route.name.startsWith('type-id') && !route.query.sid, () => route.name && route.name.startsWith('type-project') && !route.query.sid,
) )
const isRussia = computed(() => country.value === 'ru') const isRussia = computed(() => country.value === 'ru')
@@ -485,7 +485,7 @@
v-if="!isServerProject" v-if="!isServerProject"
size="large" size="large"
:color=" :color="
(auth.user && currentMember) || route.name === 'type-id-version-version' (auth.user && currentMember) || route.name === 'type-project-version-version'
? `standard` ? `standard`
: `brand` : `brand`
" "
@@ -507,7 +507,7 @@
v-else v-else
size="large" size="large"
:color=" :color="
(auth.user && currentMember) || route.name === 'type-id-version-version' (auth.user && currentMember) || route.name === 'type-project-version-version'
? `standard` ? `standard`
: `brand` : `brand`
" "
@@ -529,7 +529,7 @@
size="large" size="large"
circular circular
:color=" :color="
route.name === 'type-id-version-version' || (auth.user && currentMember) route.name === 'type-project-version-version' || (auth.user && currentMember)
? `standard` ? `standard`
: `brand` : `brand`
" "
@@ -547,7 +547,7 @@
size="large" size="large"
circular circular
:color=" :color="
route.name === 'type-id-version-version' || (auth.user && currentMember) route.name === 'type-project-version-version' || (auth.user && currentMember)
? `standard` ? `standard`
: `brand` : `brand`
" "
@@ -1136,7 +1136,7 @@ import { useModerationQueue } from '~/services/moderation-queue.ts'
import { getReportPath, reportProject } from '~/utils/report-helpers.ts' import { getReportPath, reportProject } from '~/utils/report-helpers.ts'
definePageMeta({ definePageMeta({
key: (route) => `${route.params.id}`, key: (route) => `${route.params.project}`,
}) })
const data = useNuxtApp() const data = useNuxtApp()
@@ -1151,6 +1151,9 @@ const { addNotification } = notifications
const auth = await useAuth() const auth = await useAuth()
const user = await useUser() const user = await useUser()
// Route param for initial lookup (middleware caches by both slug and ID)
const routeProjectId = useRouteId('project')
const { createProjectDownloadUrl } = useCdnDownloadContext() const { createProjectDownloadUrl } = useCdnDownloadContext()
const downloadReason = ref('standalone') const downloadReason = ref('standalone')
@@ -1637,7 +1640,7 @@ const collections = computed(() =>
) )
if ( if (
!route.params.id || !routeProjectId ||
!( !(
tags.value.projectTypes.find((x) => x.id === route.params.type) || tags.value.projectTypes.find((x) => x.id === route.params.type) ||
route.params.type === 'project' route.params.type === 'project'
@@ -1650,17 +1653,14 @@ if (
}) })
} }
// Route param for initial lookup (middleware caches by both slug and ID)
const routeProjectId = computed(() => route.params.id)
// Use DI client for TanStack Query // Use DI client for TanStack Query
const client = injectModrinthClient() const client = injectModrinthClient()
const queryClient = useQueryClient() const queryClient = useQueryClient()
// V2 Project - hits middleware cache (uses route param for lookup) // V2 Project - hits middleware cache (uses route param for lookup)
const { data: projectRaw, error: projectV2Error } = useQuery({ const { data: projectRaw, error: projectV2Error } = useQuery({
queryKey: computed(() => ['project', 'v2', routeProjectId.value]), queryKey: computed(() => ['project', 'v2', routeProjectId]),
queryFn: () => client.labrinth.projects_v2.get(routeProjectId.value), queryFn: () => client.labrinth.projects_v2.get(routeProjectId),
staleTime: STALE_TIME, staleTime: STALE_TIME,
}) })
@@ -1709,8 +1709,8 @@ const {
error: _projectV3Error, error: _projectV3Error,
isPending: projectV3Pending, isPending: projectV3Pending,
} = useQuery({ } = useQuery({
queryKey: computed(() => ['project', 'v3', routeProjectId.value]), queryKey: computed(() => ['project', 'v3', routeProjectId]),
queryFn: () => client.labrinth.projects_v3.get(routeProjectId.value), queryFn: () => client.labrinth.projects_v3.get(routeProjectId),
staleTime: STALE_TIME, staleTime: STALE_TIME,
}) })
@@ -1870,7 +1870,7 @@ const { data: organizationRaw } = useQuery({
// Return null when the project no longer belongs to an organization. // Return null when the project no longer belongs to an organization.
const organization = computed(() => (projectRaw.value?.organization ? organizationRaw.value : null)) const organization = computed(() => (projectRaw.value?.organization ? organizationRaw.value : null))
const isSettings = computed(() => route.name.startsWith('type-id-settings')) const isSettings = computed(() => route.name.startsWith('type-project-settings'))
// Transform versionsV3 to be same shape as versionsV2 for compatibility in project pages // Transform versionsV3 to be same shape as versionsV2 for compatibility in project pages
const versionsRaw = computed(() => { const versionsRaw = computed(() => {
@@ -1914,7 +1914,7 @@ const hasVersions = computed(() => (project.value?.versions?.length ?? 0) > 0)
async function updateProjectRoute() { async function updateProjectRoute() {
if ( if (
project.value && project.value &&
route.params.id !== project.value.slug && routeProjectId !== project.value.slug &&
!flags.value.disablePrettyProjectUrlRedirects !flags.value.disablePrettyProjectUrlRedirects
) { ) {
await navigateTo( await navigateTo(
@@ -1933,9 +1933,9 @@ async function updateProjectRoute() {
} }
async function invalidateProject() { async function invalidateProject() {
await queryClient.invalidateQueries({ queryKey: ['project', 'v2', routeProjectId.value] }) await queryClient.invalidateQueries({ queryKey: ['project', 'v2', routeProjectId] })
await queryClient.invalidateQueries({ queryKey: ['project', 'v3', routeProjectId.value] }) await queryClient.invalidateQueries({ queryKey: ['project', 'v3', routeProjectId] })
if (routeProjectId.value !== projectId.value) { if (routeProjectId !== projectId.value) {
await queryClient.invalidateQueries({ queryKey: ['project', 'v2', projectId.value] }) await queryClient.invalidateQueries({ queryKey: ['project', 'v2', projectId.value] })
await queryClient.invalidateQueries({ queryKey: ['project', 'v3', projectId.value] }) await queryClient.invalidateQueries({ queryKey: ['project', 'v3', projectId.value] })
} }
@@ -1953,16 +1953,16 @@ const patchProjectMutation = useMutation({
onMutate: async ({ projectId, data }) => { onMutate: async ({ projectId, data }) => {
// Cancel outgoing refetches for both slug-based and ID-based cache keys // Cancel outgoing refetches for both slug-based and ID-based cache keys
// The query may be keyed by slug (routeProjectId) but we also have the actual UUID (projectId) // The query may be keyed by slug (routeProjectId) but we also have the actual UUID (projectId)
await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId.value] }) await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId] })
if (routeProjectId.value !== projectId) { if (routeProjectId !== projectId) {
await queryClient.cancelQueries({ queryKey: ['project', 'v2', projectId] }) await queryClient.cancelQueries({ queryKey: ['project', 'v2', projectId] })
} }
// Snapshot previous value from the active query (uses route param as key) // Snapshot previous value from the active query (uses route param as key)
const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId.value]) const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId])
// Optimistic update on the active query key // Optimistic update on the active query key
queryClient.setQueryData(['project', 'v2', routeProjectId.value], (old) => { queryClient.setQueryData(['project', 'v2', routeProjectId], (old) => {
if (!old) return old if (!old) return old
return { ...old, ...data } return { ...old, ...data }
}) })
@@ -1973,7 +1973,7 @@ const patchProjectMutation = useMutation({
onError: (err, _variables, context) => { onError: (err, _variables, context) => {
// Rollback on error using the active query key // Rollback on error using the active query key
if (context?.previousProject) { if (context?.previousProject) {
queryClient.setQueryData(['project', 'v2', routeProjectId.value], context.previousProject) queryClient.setQueryData(['project', 'v2', routeProjectId], context.previousProject)
} }
addNotification({ addNotification({
title: formatMessage(commonMessages.errorNotificationTitle), title: formatMessage(commonMessages.errorNotificationTitle),
@@ -1995,16 +1995,16 @@ const patchStatusMutation = useMutation({
onMutate: async ({ projectId, status }) => { onMutate: async ({ projectId, status }) => {
// Cancel outgoing refetches for both slug-based and ID-based cache keys // Cancel outgoing refetches for both slug-based and ID-based cache keys
await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId.value] }) await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId] })
if (routeProjectId.value !== projectId) { if (routeProjectId !== projectId) {
await queryClient.cancelQueries({ queryKey: ['project', 'v2', projectId] }) await queryClient.cancelQueries({ queryKey: ['project', 'v2', projectId] })
} }
// Snapshot previous value from the active query (uses route param as key) // Snapshot previous value from the active query (uses route param as key)
const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId.value]) const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId])
// Optimistic update on the active query key // Optimistic update on the active query key
queryClient.setQueryData(['project', 'v2', routeProjectId.value], (old) => { queryClient.setQueryData(['project', 'v2', routeProjectId], (old) => {
if (!old) return old if (!old) return old
return { ...old, status } return { ...old, status }
}) })
@@ -2015,7 +2015,7 @@ const patchStatusMutation = useMutation({
onError: (err, _variables, context) => { onError: (err, _variables, context) => {
// Rollback on error using the active query key // Rollback on error using the active query key
if (context?.previousProject) { if (context?.previousProject) {
queryClient.setQueryData(['project', 'v2', routeProjectId.value], context.previousProject) queryClient.setQueryData(['project', 'v2', routeProjectId], context.previousProject)
} }
addNotification({ addNotification({
title: formatMessage(commonMessages.errorNotificationTitle), title: formatMessage(commonMessages.errorNotificationTitle),
@@ -2121,11 +2121,11 @@ const createGalleryItemMutation = useMutation({
}, },
onMutate: async ({ title, description, featured, ordering }) => { onMutate: async ({ title, description, featured, ordering }) => {
await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId.value] }) await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId] })
const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId.value]) const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId])
queryClient.setQueryData(['project', 'v2', routeProjectId.value], (old) => { queryClient.setQueryData(['project', 'v2', routeProjectId], (old) => {
if (!old) return old if (!old) return old
const newItem = { const newItem = {
url: '', url: '',
@@ -2147,7 +2147,7 @@ const createGalleryItemMutation = useMutation({
onError: (err, _variables, context) => { onError: (err, _variables, context) => {
if (context?.previousProject) { if (context?.previousProject) {
queryClient.setQueryData(['project', 'v2', routeProjectId.value], context.previousProject) queryClient.setQueryData(['project', 'v2', routeProjectId], context.previousProject)
} }
addNotification({ addNotification({
title: formatMessage(commonMessages.errorNotificationTitle), title: formatMessage(commonMessages.errorNotificationTitle),
@@ -2172,11 +2172,11 @@ const editGalleryItemMutation = useMutation({
}, },
onMutate: async ({ imageUrl, title, description, featured, ordering }) => { onMutate: async ({ imageUrl, title, description, featured, ordering }) => {
await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId.value] }) await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId] })
const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId.value]) const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId])
queryClient.setQueryData(['project', 'v2', routeProjectId.value], (old) => { queryClient.setQueryData(['project', 'v2', routeProjectId], (old) => {
if (!old) return old if (!old) return old
return { return {
...old, ...old,
@@ -2200,7 +2200,7 @@ const editGalleryItemMutation = useMutation({
onError: (err, _variables, context) => { onError: (err, _variables, context) => {
if (context?.previousProject) { if (context?.previousProject) {
queryClient.setQueryData(['project', 'v2', routeProjectId.value], context.previousProject) queryClient.setQueryData(['project', 'v2', routeProjectId], context.previousProject)
} }
addNotification({ addNotification({
title: formatMessage(commonMessages.errorNotificationTitle), title: formatMessage(commonMessages.errorNotificationTitle),
@@ -2220,11 +2220,11 @@ const deleteGalleryItemMutation = useMutation({
}, },
onMutate: async ({ imageUrl }) => { onMutate: async ({ imageUrl }) => {
await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId.value] }) await queryClient.cancelQueries({ queryKey: ['project', 'v2', routeProjectId] })
const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId.value]) const previousProject = queryClient.getQueryData(['project', 'v2', routeProjectId])
queryClient.setQueryData(['project', 'v2', routeProjectId.value], (old) => { queryClient.setQueryData(['project', 'v2', routeProjectId], (old) => {
if (!old) return old if (!old) return old
return { return {
...old, ...old,
@@ -2237,7 +2237,7 @@ const deleteGalleryItemMutation = useMutation({
onError: (err, _variables, context) => { onError: (err, _variables, context) => {
if (context?.previousProject) { if (context?.previousProject) {
queryClient.setQueryData(['project', 'v2', routeProjectId.value], context.previousProject) queryClient.setQueryData(['project', 'v2', routeProjectId], context.previousProject)
} }
addNotification({ addNotification({
title: formatMessage(commonMessages.errorNotificationTitle), title: formatMessage(commonMessages.errorNotificationTitle),
@@ -2372,7 +2372,7 @@ useHead({
], ],
}) })
if (!route.name.startsWith('type-id-settings')) { if (!route.name.startsWith('type-project-settings')) {
useSeoMeta({ useSeoMeta({
title: () => title.value, title: () => title.value,
description: () => description.value, description: () => description.value,
@@ -47,10 +47,8 @@ const navItems = computed(() => {
projectV3.value?.project_types?.some((type) => ['mod', 'modpack'].includes(type)) && projectV3.value?.project_types?.some((type) => ['mod', 'modpack'].includes(type)) &&
isStaff(currentMember.value?.user) isStaff(currentMember.value?.user)
const hasPermissionsPage = computed( const hasPermissionsPage = computed(() =>
() => projectV3.value?.project_types?.some((type) => ['modpack'].includes(type)),
flags.value.modpackPermissionsPage &&
projectV3.value?.project_types?.some((type) => ['modpack'].includes(type)),
) )
const items = [ const items = [
@@ -360,7 +360,6 @@ const formatDateTimeShort = useFormatDateTime({
minute: 'numeric', minute: 'numeric',
}) })
const route = useRoute()
const vintl = useVIntl() const vintl = useVIntl()
const { formatMessage } = vintl const { formatMessage } = vintl
@@ -373,13 +372,15 @@ const messages = defineMessages({
}, },
}) })
const chargeId = useRouteId('charge')
const { const {
data: user, data: user,
error: userError, error: userError,
suspense: userSuspense, suspense: userSuspense,
} = useQuery({ } = useQuery({
queryKey: ['user', route.params.id], queryKey: ['user', chargeId],
queryFn: () => labrinth.users_v2.get(route.params.id), queryFn: () => labrinth.users_v2.get(chargeId),
}) })
onServerPrefetch(userSuspense) onServerPrefetch(userSuspense)
@@ -529,8 +529,8 @@ const returnLink = computed(() => {
return null return null
}) })
const collectionId = computed(() => route.params.id) const collectionId = useRouteId('collection')
const isFollowingCollection = computed(() => collectionId.value === 'following') const isFollowingCollection = computed(() => collectionId === 'following')
// Static collection for "following" page // Static collection for "following" page
const followingCollection = computed(() => const followingCollection = computed(() =>
@@ -555,15 +555,15 @@ const {
error: collectionError, error: collectionError,
isPending: collectionIsPending, isPending: collectionIsPending,
} = useQuery({ } = useQuery({
queryKey: computed(() => ['collection', collectionId.value]), queryKey: computed(() => ['collection', collectionId]),
queryFn: () => api.labrinth.collections.get(collectionId.value), queryFn: () => api.labrinth.collections.get(collectionId),
enabled: computed(() => !!collectionId.value && !isFollowingCollection.value), enabled: computed(() => !!collectionId && !isFollowingCollection.value),
}) })
watch( watch(
collectionError, collectionError,
(error) => { (error) => {
if (error && collectionId.value && !isFollowingCollection.value) { if (error && collectionId && !isFollowingCollection.value) {
const status = error.statusCode ?? error.status ?? 404 const status = error.statusCode ?? error.status ?? 404
showError({ showError({
fatal: true, fatal: true,
@@ -1,7 +1,7 @@
<template> <template>
<ReportView <ReportView
:auth="auth" :auth="auth"
:report-id="route.params.id" :report-id="reportId"
:breadcrumbs-stack="[ :breadcrumbs-stack="[
{ href: '/dashboard/reports', label: formatMessage(messages.activeReportsTitle) }, { href: '/dashboard/reports', label: formatMessage(messages.activeReportsTitle) },
]" ]"
@@ -25,10 +25,10 @@ const messages = defineMessages({
}, },
}) })
const route = useNativeRoute()
const auth = await useAuth() const auth = await useAuth()
const reportId = useRouteId('report')
useHead({ useHead({
title: () => `${formatMessage(messages.reportTitle, { id: route.params.id })} - Modrinth`, title: () => `${formatMessage(messages.reportTitle, { id: reportId })} - Modrinth`,
}) })
</script> </script>
+4 -4
View File
@@ -529,10 +529,10 @@ async function moderateAllInFilter() {
} }
navigateTo({ navigateTo({
name: 'type-id', name: 'type-project',
params: { params: {
type: 'project', type: 'project',
id: targetProject.project.slug, project: targetProject.project.slug,
}, },
state: { state: {
showChecklist: true, showChecklist: true,
@@ -566,10 +566,10 @@ async function startFromProject(projectId: string) {
} }
navigateTo({ navigateTo({
name: 'type-id', name: 'type-project',
params: { params: {
type: 'project', type: 'project',
id: targetProject.project.slug, project: targetProject.project.slug,
}, },
state: { state: {
showChecklist: true, showChecklist: true,
@@ -7,8 +7,7 @@ import ModerationReportCard from '~/components/ui/moderation/ModerationReportCar
import { enrichReportBatch } from '~/helpers/moderation.ts' import { enrichReportBatch } from '~/helpers/moderation.ts'
const client = injectModrinthClient() const client = injectModrinthClient()
const { params } = useRoute() const reportId = String(useRouteId('report'))
const reportId = params.id as string
const { data: report } = useQuery({ const { data: report } = useQuery({
queryKey: computed(() => ['report', reportId]), queryKey: computed(() => ['report', reportId]),
@@ -9,13 +9,12 @@ import MaliciousSummaryModal, {
} from '~/components/ui/moderation/MaliciousSummaryModal.vue' } from '~/components/ui/moderation/MaliciousSummaryModal.vue'
import ModerationTechRevCard from '~/components/ui/moderation/ModerationTechRevCard.vue' import ModerationTechRevCard from '~/components/ui/moderation/ModerationTechRevCard.vue'
const route = useRoute()
const client = injectModrinthClient() const client = injectModrinthClient()
const queryClient = useQueryClient() const queryClient = useQueryClient()
const projectId = computed(() => route.params.id as string) const projectId = String(useRouteId('project'))
useHead({ title: () => `Tech review - ${projectId.value} - Modrinth` }) useHead({ title: () => `Tech review - ${projectId} - Modrinth` })
const CACHE_TTL = 24 * 60 * 60 * 1000 const CACHE_TTL = 24 * 60 * 60 * 1000
const CACHE_KEY_PREFIX = 'tech_review_source_' const CACHE_KEY_PREFIX = 'tech_review_source_'
@@ -151,7 +150,7 @@ const {
} = useQuery({ } = useQuery({
queryKey: ['tech-review-project-report', projectId], queryKey: ['tech-review-project-report', projectId],
queryFn: async () => { queryFn: async () => {
return await client.labrinth.tech_review_internal.getProjectReport(projectId.value) return await client.labrinth.tech_review_internal.getProjectReport(projectId)
}, },
retry: false, retry: false,
}) })
@@ -163,7 +162,7 @@ const {
} = useQuery({ } = useQuery({
queryKey: ['project', projectId], queryKey: ['project', projectId],
queryFn: async () => { queryFn: async () => {
return await client.labrinth.projects_v3.get(projectId.value) return await client.labrinth.projects_v3.get(projectId)
}, },
retry: false, retry: false,
}) })
@@ -171,14 +170,14 @@ const {
const { data: organizationData, isLoading: isLoadingOrg } = useQuery({ const { data: organizationData, isLoading: isLoadingOrg } = useQuery({
queryKey: ['project-organization', projectId], queryKey: ['project-organization', projectId],
queryFn: async () => { queryFn: async () => {
return await client.labrinth.projects_v3.getOrganization(projectId.value) return await client.labrinth.projects_v3.getOrganization(projectId)
}, },
}) })
const { data: membersData, isLoading: isLoadingMembers } = useQuery({ const { data: membersData, isLoading: isLoadingMembers } = useQuery({
queryKey: ['project-members', projectId], queryKey: ['project-members', projectId],
queryFn: async () => { queryFn: async () => {
return await client.labrinth.projects_v3.getMembers(projectId.value) return await client.labrinth.projects_v3.getMembers(projectId)
}, },
enabled: computed(() => !organizationData.value && !isLoadingOrg.value), enabled: computed(() => !organizationData.value && !isLoadingOrg.value),
}) })
@@ -265,7 +264,7 @@ function handleShowMaliciousSummary(unsafeFiles: UnsafeFile[]) {
} }
function refetch() { function refetch() {
queryClient.invalidateQueries({ queryKey: ['tech-review-project-report', projectId.value] }) queryClient.invalidateQueries({ queryKey: ['tech-review-project-report', projectId] })
} }
</script> </script>
@@ -348,7 +348,7 @@ const tags = useGeneratedState()
const config = useRuntimeConfig() const config = useRuntimeConfig()
const modal_creation = useTemplateRef('modal_creation') const modal_creation = useTemplateRef('modal_creation')
const orgId = useRouteId() const orgId = useRouteId('organization')
if (route.path.includes('settings')) { if (route.path.includes('settings')) {
useSeoMeta({ useSeoMeta({
@@ -85,7 +85,7 @@ const showPreviewImage = (files) => {
} }
} }
const orgId = useRouteId() const orgId = useRouteId('orgId')
const save = async () => { const save = async () => {
// Save field changes via useSavable // Save field changes via useSavable
@@ -685,13 +685,15 @@ const messages = defineMessages({
const client = injectModrinthClient() const client = injectModrinthClient()
const userId = useRouteId('user')
const { const {
data: user, data: user,
error: userError, error: userError,
suspense: userSuspense, suspense: userSuspense,
} = useQuery({ } = useQuery({
queryKey: computed(() => ['user', route.params.id]), queryKey: computed(() => ['user', userId]),
queryFn: () => client.labrinth.users_v2.get(route.params.id), queryFn: () => client.labrinth.users_v2.get(userId),
}) })
watch( watch(
@@ -710,9 +712,9 @@ watch(
) )
const { data: projects, suspense: projectsSuspense } = useQuery({ const { data: projects, suspense: projectsSuspense } = useQuery({
queryKey: computed(() => ['user', route.params.id, 'projects']), queryKey: computed(() => ['user', userId, 'projects']),
queryFn: async () => { queryFn: async () => {
const projects = await client.labrinth.users_v2.getProjects(route.params.id) const projects = await client.labrinth.users_v2.getProjects(userId)
for (const project of projects) { for (const project of projects) {
project.categories = project.categories.concat(project.loaders) project.categories = project.categories.concat(project.loaders)
project.project_type = data.$getProjectTypeForUrl( project.project_type = data.$getProjectTypeForUrl(
@@ -726,13 +728,13 @@ const { data: projects, suspense: projectsSuspense } = useQuery({
}) })
const { data: organizations, suspense: orgsSuspense } = useQuery({ const { data: organizations, suspense: orgsSuspense } = useQuery({
queryKey: computed(() => ['user', route.params.id, 'organizations']), queryKey: computed(() => ['user', userId, 'organizations']),
queryFn: () => client.labrinth.users_v2.getOrganizations(route.params.id), queryFn: () => client.labrinth.users_v2.getOrganizations(userId),
}) })
const { data: collections, suspense: collectionsSuspense } = useQuery({ const { data: collections, suspense: collectionsSuspense } = useQuery({
queryKey: computed(() => ['user', route.params.id, 'collections']), queryKey: computed(() => ['user', userId, 'collections']),
queryFn: () => client.labrinth.users_v2.getCollections(route.params.id), queryFn: () => client.labrinth.users_v2.getCollections(userId),
}) })
onServerPrefetch(async () => { onServerPrefetch(async () => {
@@ -865,7 +867,7 @@ const isAdminViewing = computed(() => isAdmin(auth.value.user))
async function toggleAffiliate(id) { async function toggleAffiliate(id) {
await client.labrinth.users_v2.patch(id, { badges: user.value.badges ^ (1 << 7) }) await client.labrinth.users_v2.patch(id, { badges: user.value.badges ^ (1 << 7) })
queryClient.invalidateQueries({ queryKey: ['user', route.params.id] }) queryClient.invalidateQueries({ queryKey: ['user', userId] })
} }
const navLinks = computed(() => [ const navLinks = computed(() => [
+1 -1
View File
@@ -225,7 +225,7 @@ Example:
link: { link: {
path: 'settings/description', path: 'settings/description',
title: messages.editDescriptionTitle, title: messages.editDescriptionTitle,
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-description', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-description',
}, },
} }
``` ```
+8 -7
View File
@@ -23,7 +23,7 @@ export const coreNags: Nag[] = [
id: 'nags.moderation.title', id: 'nags.moderation.title',
defaultMessage: 'Visit moderation thread', defaultMessage: 'Visit moderation thread',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-moderation', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-moderation',
}, },
}, },
{ {
@@ -45,7 +45,7 @@ export const coreNags: Nag[] = [
id: 'nags.versions.title', id: 'nags.versions.title',
defaultMessage: 'Visit versions page', defaultMessage: 'Visit versions page',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-versions', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-versions',
}, },
}, },
{ {
@@ -67,7 +67,8 @@ export const coreNags: Nag[] = [
id: 'nags.settings.description.title', id: 'nags.settings.description.title',
defaultMessage: 'Visit description settings', defaultMessage: 'Visit description settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-description', shouldShow: (context: NagContext) =>
context.currentRoute !== 'type-project-settings-description',
}, },
}, },
{ {
@@ -89,7 +90,7 @@ export const coreNags: Nag[] = [
id: 'nags.settings.title', id: 'nags.settings.title',
defaultMessage: 'Visit general settings', defaultMessage: 'Visit general settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings',
}, },
}, },
{ {
@@ -132,7 +133,7 @@ export const coreNags: Nag[] = [
id: 'nags.gallery.title', id: 'nags.gallery.title',
defaultMessage: 'Visit gallery page', defaultMessage: 'Visit gallery page',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-gallery', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-gallery',
}, },
}, },
{ {
@@ -158,7 +159,7 @@ export const coreNags: Nag[] = [
id: 'nags.gallery.title', id: 'nags.gallery.title',
defaultMessage: 'Visit gallery page', defaultMessage: 'Visit gallery page',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-gallery', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-gallery',
}, },
}, },
{ {
@@ -190,7 +191,7 @@ export const coreNags: Nag[] = [
id: 'nags.settings.license.title', id: 'nags.settings.license.title',
defaultMessage: 'Visit license settings', defaultMessage: 'Visit license settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-license', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-license',
}, },
}, },
] ]
@@ -146,7 +146,8 @@ export const descriptionNags: Nag[] = [
id: 'nags.edit-description.title', id: 'nags.edit-description.title',
defaultMessage: 'Edit description', defaultMessage: 'Edit description',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-description', shouldShow: (context: NagContext) =>
context.currentRoute !== 'type-project-settings-description',
}, },
}, },
{ {
@@ -182,7 +183,8 @@ export const descriptionNags: Nag[] = [
id: 'nags.edit-description.title', id: 'nags.edit-description.title',
defaultMessage: 'Edit description', defaultMessage: 'Edit description',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-description', shouldShow: (context: NagContext) =>
context.currentRoute !== 'type-project-settings-description',
}, },
}, },
{ {
@@ -217,7 +219,7 @@ export const descriptionNags: Nag[] = [
id: 'nags.edit-summary.title', id: 'nags.edit-summary.title',
defaultMessage: 'Edit summary', defaultMessage: 'Edit summary',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings',
}, },
}, },
{ {
@@ -255,7 +257,7 @@ export const descriptionNags: Nag[] = [
id: 'nags.edit-summary.title', id: 'nags.edit-summary.title',
defaultMessage: 'Edit summary', defaultMessage: 'Edit summary',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings',
}, },
}, },
{ {
@@ -280,7 +282,7 @@ export const descriptionNags: Nag[] = [
id: 'nags.edit-title.title', id: 'nags.edit-title.title',
defaultMessage: 'Edit title', defaultMessage: 'Edit title',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings',
}, },
}, },
{ {
@@ -313,7 +315,7 @@ export const descriptionNags: Nag[] = [
id: 'nags.edit-title.title', id: 'nags.edit-title.title',
defaultMessage: 'Edit title', defaultMessage: 'Edit title',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings',
}, },
}, },
{ {
@@ -339,7 +341,7 @@ export const descriptionNags: Nag[] = [
id: 'nags.edit-summary.title', id: 'nags.edit-summary.title',
defaultMessage: 'Edit summary', defaultMessage: 'Edit summary',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings',
}, },
}, },
{ {
@@ -365,7 +367,8 @@ export const descriptionNags: Nag[] = [
id: 'nags.edit-description.title', id: 'nags.edit-description.title',
defaultMessage: 'Edit description', defaultMessage: 'Edit description',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-description', shouldShow: (context: NagContext) =>
context.currentRoute !== 'type-project-settings-description',
}, },
}, },
{ {
@@ -390,7 +393,8 @@ export const descriptionNags: Nag[] = [
id: 'nags.edit-description.title', id: 'nags.edit-description.title',
defaultMessage: 'Edit description', defaultMessage: 'Edit description',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-description', shouldShow: (context: NagContext) =>
context.currentRoute !== 'type-project-settings-description',
}, },
}, },
] ]
+7 -7
View File
@@ -99,7 +99,7 @@ export const linksNags: Nag[] = [
id: 'nags.settings.links.title', id: 'nags.settings.links.title',
defaultMessage: 'Visit links settings', defaultMessage: 'Visit links settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-links', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-links',
}, },
}, },
{ {
@@ -126,7 +126,7 @@ export const linksNags: Nag[] = [
id: 'nags.settings.links.title', id: 'nags.settings.links.title',
defaultMessage: 'Visit links settings', defaultMessage: 'Visit links settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-links', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-links',
}, },
}, },
{ {
@@ -150,7 +150,7 @@ export const linksNags: Nag[] = [
id: 'nags.settings.links.title', id: 'nags.settings.links.title',
defaultMessage: 'Visit links settings', defaultMessage: 'Visit links settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-links', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-links',
}, },
}, },
{ {
@@ -178,7 +178,7 @@ export const linksNags: Nag[] = [
id: 'nags.visit-links-settings.title', id: 'nags.visit-links-settings.title',
defaultMessage: 'Visit links settings', defaultMessage: 'Visit links settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-links', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-links',
}, },
}, },
{ {
@@ -205,7 +205,7 @@ export const linksNags: Nag[] = [
id: 'nags.visit-links-settings.title', id: 'nags.visit-links-settings.title',
defaultMessage: 'Visit links settings', defaultMessage: 'Visit links settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-links', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-links',
}, },
}, },
{ {
@@ -299,7 +299,7 @@ export const linksNags: Nag[] = [
id: 'nags.edit-license.title', id: 'nags.edit-license.title',
defaultMessage: 'Edit license', defaultMessage: 'Edit license',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings',
}, },
}, },
{ {
@@ -373,7 +373,7 @@ export const linksNags: Nag[] = [
id: 'nags.visit-links-settings.title', id: 'nags.visit-links-settings.title',
defaultMessage: 'Visit links settings', defaultMessage: 'Visit links settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-links', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-links',
}, },
}, },
] ]
@@ -22,7 +22,7 @@ export const serverProjectsNags: Nag[] = [
id: 'nags.server.title', id: 'nags.server.title',
defaultMessage: 'Visit server settings', defaultMessage: 'Visit server settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-server', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-server',
}, },
}, },
{ {
@@ -45,7 +45,7 @@ export const serverProjectsNags: Nag[] = [
id: 'nags.server.title', id: 'nags.server.title',
defaultMessage: 'Visit server settings', defaultMessage: 'Visit server settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-server', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-server',
}, },
}, },
{ {
@@ -68,7 +68,7 @@ export const serverProjectsNags: Nag[] = [
id: 'nags.server.title', id: 'nags.server.title',
defaultMessage: 'Visit server settings', defaultMessage: 'Visit server settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-server', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-server',
}, },
}, },
{ {
@@ -97,7 +97,7 @@ export const serverProjectsNags: Nag[] = [
id: 'nags.server.title', id: 'nags.server.title',
defaultMessage: 'Visit server settings', defaultMessage: 'Visit server settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-server', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-server',
}, },
}, },
] ]
+5 -5
View File
@@ -44,7 +44,7 @@ export const tagsNags: Nag[] = [
id: 'nags.settings.tags.title', id: 'nags.settings.tags.title',
defaultMessage: 'Visit tag settings', defaultMessage: 'Visit tag settings',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-tags', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-tags',
}, },
}, },
{ {
@@ -84,7 +84,7 @@ export const tagsNags: Nag[] = [
id: 'nags.edit-tags.title', id: 'nags.edit-tags.title',
defaultMessage: 'Edit tags', defaultMessage: 'Edit tags',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-tags', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-tags',
}, },
}, },
{ {
@@ -123,7 +123,7 @@ export const tagsNags: Nag[] = [
id: 'nags.edit-tags.title', id: 'nags.edit-tags.title',
defaultMessage: 'Edit tags', defaultMessage: 'Edit tags',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-tags', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-tags',
}, },
}, },
{ {
@@ -172,7 +172,7 @@ export const tagsNags: Nag[] = [
id: 'nags.edit-tags.title', id: 'nags.edit-tags.title',
defaultMessage: 'Edit tags', defaultMessage: 'Edit tags',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-tags', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-tags',
}, },
}, },
{ {
@@ -219,7 +219,7 @@ export const tagsNags: Nag[] = [
id: 'nags.edit-tags.title', id: 'nags.edit-tags.title',
defaultMessage: 'Edit tags', defaultMessage: 'Edit tags',
}), }),
shouldShow: (context: NagContext) => context.currentRoute !== 'type-id-settings-tags', shouldShow: (context: NagContext) => context.currentRoute !== 'type-project-settings-tags',
}, },
}, },
] ]