This commit is contained in:
Calum H. (IMB11)
2026-06-26 17:09:23 +01:00
parent 417c6964f6
commit 4986bc194d
13 changed files with 99 additions and 216 deletions
@@ -54,7 +54,6 @@ export const DEFAULT_FEATURE_FLAGS = validateValues({
showModeratorProjectMemberUi: false,
showModeratorPrivateMessageHighlight: true,
archonApiStaging: false,
showHostingAccessInstanceAuditLog: false,
versionDevInfoCollapsed: true,
alwaysShowVersionDevInfo: false,
} as const)
@@ -9,74 +9,22 @@ import { useQueryClient } from '@tanstack/vue-query'
const client = injectModrinthClient()
const { server, serverId } = injectModrinthServerContext()
const queryClient = useQueryClient()
const flags = useFeatureFlags()
const ACTION_LOG_PAGE_SIZE = 200
const ACTION_LOG_SORT_DIRECTION = 'desc'
const actionLogDateFilter = defaultActionLogDateFilter()
await Promise.allSettled([
queryClient.ensureQueryData({
try {
await queryClient.ensureQueryData({
queryKey: ['servers', 'users', 'v1', serverId],
queryFn: () => client.archon.server_users_v1.list(serverId),
staleTime: 30_000,
}),
queryClient.ensureQueryData({
queryKey: ['servers', 'v1', 'detail', serverId],
queryFn: () => client.archon.servers_v1.get(serverId),
staleTime: 30_000,
}),
queryClient.ensureInfiniteQueryData({
queryKey: [
'servers',
'action-log',
'v1',
'infinite',
serverId,
null,
actionLogDateFilter.min_datetime,
actionLogDateFilter.max_datetime,
ACTION_LOG_SORT_DIRECTION,
],
queryFn: ({ pageParam = 0 }) => {
const offset = typeof pageParam === 'number' ? pageParam : 0
return client.archon.actions_v1.list(serverId, {
limit: ACTION_LOG_PAGE_SIZE,
offset,
order: ACTION_LOG_SORT_DIRECTION,
...actionLogDateFilter,
})
},
getNextPageParam: (lastPage) =>
typeof lastPage.next_offset === 'number' ? lastPage.next_offset : undefined,
initialPageParam: 0,
staleTime: 30_000,
}),
])
})
} catch {
// Let mounted layouts' useQuery surface errors; do not fail route setup.
}
useHead({
title: computed(() => `Access - ${server.value?.name ?? 'Server'} - Modrinth`),
})
function defaultActionLogDateFilter() {
const endDate = new Date()
const startDate = new Date(endDate)
startDate.setDate(startDate.getDate() - 6)
return {
min_datetime: startOfDay(startDate).toISOString(),
max_datetime: endOfDay(endDate).toISOString(),
}
}
function startOfDay(date: Date) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate())
}
function endOfDay(date: Date) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999)
}
</script>
<template>
<ServersManageAccessPage :show-audit-log-instances="flags.showHostingAccessInstanceAuditLog" />
<ServersManageAccessPage />
</template>
@@ -96,9 +96,13 @@ async function loadContentSummary(
index: number,
): Promise<ContentSummary> {
try {
const content = await client.archon.content_v1.getAddons(serverId, world.id, {
addons: true,
updates: false,
const content = await queryClient.fetchQuery({
queryKey: ['content', 'list', 'v1', serverId, world.id],
queryFn: () =>
client.archon.content_v1.getAddons(serverId, world.id, {
from_modpack: false,
}),
staleTime: 0,
})
return {
@@ -106,13 +110,35 @@ async function loadContentSummary(
loader: content.modloader ?? world.content?.modloader ?? null,
loaderVersion: content.modloader_version ?? world.content?.modloader_version ?? null,
linkedModpack: getLinkedModpack(content.modpack),
installedContentCount: content.addons?.length ?? 0,
installedContentCount: await getInstalledContentCount(world.id, content),
}
} catch {
return createDummyContentSummary(world, index)
}
}
async function getInstalledContentCount(
worldId: string,
content: Archon.Content.v1.Addons,
): Promise<number> {
const addonCount = content.addons?.length ?? 0
if (!content.modpack) return addonCount
try {
const modpackContent = await queryClient.fetchQuery({
queryKey: ['content', 'list', 'v1', serverId, worldId, 'modpack'],
queryFn: () =>
client.archon.content_v1.getAddons(serverId, worldId, {
from_modpack: true,
}),
staleTime: 0,
})
return addonCount + (modpackContent.addons?.length ?? 0)
} catch {
return addonCount
}
}
function toWorldSlot(world: Archon.Servers.v1.WorldFull, content: ContentSummary): WorldSlot {
return {
type: 'world',