From 4986bc194df8cf7e30af59c7d2a543d2d95ae090 Mon Sep 17 00:00:00 2001 From: "Calum H. (IMB11)" Date: Wed, 24 Jun 2026 14:55:10 +0100 Subject: [PATCH] fix: qa --- apps/frontend/src/composables/featureFlags.ts | 1 - .../src/pages/hosting/manage/[id]/access.vue | 66 ++------------ .../hosting/manage/[id]/instances/index.vue | 34 ++++++- .../src/components/base/FloatingActionBar.vue | 15 +++- .../components/FinalConfigStage.vue | 2 +- .../servers/access/AuditLogTable.vue | 88 ++----------------- .../server-header/ServerManageHeader.vue | 19 +--- .../SelectedProjectsFloatingBar.vue | 1 + .../pages/instance-general.vue | 12 +-- .../hosting/manage/[id]/access/access.vue | 9 +- .../hosting/manage/[id]/access/audit-log.ts | 6 +- .../wrapped/hosting/manage/[id]/index.vue | 28 ------ .../hosting/manage/[id]/instances/index.vue | 34 ++++++- 13 files changed, 99 insertions(+), 216 deletions(-) diff --git a/apps/frontend/src/composables/featureFlags.ts b/apps/frontend/src/composables/featureFlags.ts index ed8e142016..b7518ee4e8 100644 --- a/apps/frontend/src/composables/featureFlags.ts +++ b/apps/frontend/src/composables/featureFlags.ts @@ -54,7 +54,6 @@ export const DEFAULT_FEATURE_FLAGS = validateValues({ showModeratorProjectMemberUi: false, showModeratorPrivateMessageHighlight: true, archonApiStaging: false, - showHostingAccessInstanceAuditLog: false, versionDevInfoCollapsed: true, alwaysShowVersionDevInfo: false, } as const) diff --git a/apps/frontend/src/pages/hosting/manage/[id]/access.vue b/apps/frontend/src/pages/hosting/manage/[id]/access.vue index fd935bbf79..dc84da549b 100644 --- a/apps/frontend/src/pages/hosting/manage/[id]/access.vue +++ b/apps/frontend/src/pages/hosting/manage/[id]/access.vue @@ -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) -} diff --git a/apps/frontend/src/pages/hosting/manage/[id]/instances/index.vue b/apps/frontend/src/pages/hosting/manage/[id]/instances/index.vue index ef42befd9a..36fd8a190c 100644 --- a/apps/frontend/src/pages/hosting/manage/[id]/instances/index.vue +++ b/apps/frontend/src/pages/hosting/manage/[id]/instances/index.vue @@ -96,9 +96,13 @@ async function loadContentSummary( index: number, ): Promise { 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 { + 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', diff --git a/packages/ui/src/components/base/FloatingActionBar.vue b/packages/ui/src/components/base/FloatingActionBar.vue index 7554295275..4234a3c315 100644 --- a/packages/ui/src/components/base/FloatingActionBar.vue +++ b/packages/ui/src/components/base/FloatingActionBar.vue @@ -17,6 +17,7 @@ const props = defineProps<{ ariaLabel?: string belowModal?: boolean hideWhenModalOpen?: boolean + toolbarMaxWidth?: string }>() const INTERCOM_BUBBLE_GAP = 8 @@ -46,6 +47,11 @@ const barStyle = computed(() => ({ '--floating-action-bar-left-offset': leftOffset.value, '--floating-action-bar-right-offset': rightOffset.value, })) +const toolbarStyle = computed(() => + props.toolbarMaxWidth + ? { '--floating-action-bar-toolbar-max-width': props.toolbarMaxWidth } + : undefined, +) function checkCompact() { const el = toolbarEl.value @@ -203,8 +209,9 @@ onUnmounted(() => { ref="toolbarEl" role="toolbar" :aria-label="ariaLabel" - class="relative overflow-clip flex items-center gap-1.5 rounded-[20px] bg-surface-3 border border-surface-5 border-solid mx-auto md:max-w-[60vw] px-3 py-2.5 shadow-[0px_1px_3px_0px_rgba(0,0,0,0.3),0px_6px_10px_0px_rgba(0,0,0,0.15)]" + class="floating-action-toolbar relative overflow-clip flex items-center gap-1.5 rounded-[20px] bg-surface-3 border border-surface-5 border-solid mx-auto px-3 py-2.5 shadow-[0px_1px_3px_0px_rgba(0,0,0,0.3),0px_6px_10px_0px_rgba(0,0,0,0.15)]" :class="{ 'bar-compact': compact }" + :style="toolbarStyle" > @@ -220,6 +227,12 @@ onUnmounted(() => { transition: bottom 0.25s ease-in-out; } +@media (min-width: 768px) { + .floating-action-toolbar { + max-width: var(--floating-action-bar-toolbar-max-width, 60vw); + } +} + .floating-action-bar-enter-active { transition: transform 0.25s cubic-bezier(0.15, 1.4, 0.64, 0.96), diff --git a/packages/ui/src/components/flows/creation-flow-modal/components/FinalConfigStage.vue b/packages/ui/src/components/flows/creation-flow-modal/components/FinalConfigStage.vue index 2690bc0767..64ea51bb13 100644 --- a/packages/ui/src/components/flows/creation-flow-modal/components/FinalConfigStage.vue +++ b/packages/ui/src/components/flows/creation-flow-modal/components/FinalConfigStage.vue @@ -5,7 +5,7 @@ class="flex flex-col gap-2" > - {{ formatMessage(messages.worldNameLabel) }} * + {{ formatMessage(messages.worldNameLabel) }} - -