Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions apps/app-frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,11 @@ const sidebarOverlayScrollbarsOptions = Object.freeze({
},
})

router.beforeEach(async (to) => {
const redirect = await resolveLegacyServerWorldTabRedirect(to)
if (redirect) return redirect
})

router.beforeEach(() => {
suspensePending = false
if (routerToken) loading.end(routerToken)
Expand Down Expand Up @@ -470,6 +475,50 @@ function onSuspensePending() {
suspenseToken = loading.begin()
}

async function resolveLegacyServerWorldTabRedirect(to) {
if (!['ServerManageContent', 'ServerManageFiles', 'ServerManageBackups'].includes(to.name)) {
return null
}

const serverId = getRouteParam(to.params.id)
if (!serverId) return null

const tabPath =
to.name === 'ServerManageFiles' ? '/files' : to.name === 'ServerManageBackups' ? '/backups' : ''
const worldsPath = `/hosting/manage/${encodeURIComponent(serverId)}/worlds`

try {
const serverFull = await tauriApiClient.archon.servers_v1.get(serverId)
const world = serverFull.worlds.find((item) => item.is_active) ?? serverFull.worlds[0]
if (world) {
return {
path: `${worldsPath}/${encodeURIComponent(world.id)}${tabPath}`,
query: to.query,
hash: to.hash,
replace: true,
}
}
} catch {
return {
path: worldsPath,
query: to.query,
hash: to.hash,
replace: true,
}
}

return {
path: worldsPath,
query: to.query,
hash: to.hash,
replace: true,
}
}

function getRouteParam(param) {
return Array.isArray(param) ? param[0] : param
}

function onSuspenseResolve() {
if (suspenseToken) {
loading.end(suspenseToken)
Expand Down
2 changes: 1 addition & 1 deletion apps/app-frontend/src/pages/hosting/manage/Backups.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const queryClient = useQueryClient()
if (worldId.value) {
try {
await queryClient.ensureQueryData({
queryKey: ['backups', 'list', serverId],
queryKey: ['backups', 'list', serverId, worldId.value],
queryFn: () => client.archon.backups_v1.list(serverId, worldId.value!),
staleTime: 30_000,
})
Expand Down
2 changes: 1 addition & 1 deletion apps/app-frontend/src/pages/hosting/manage/Content.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const queryClient = useQueryClient()
if (worldId.value) {
try {
await queryClient.ensureQueryData({
queryKey: ['content', 'list', 'v1', serverId],
queryKey: ['content', 'list', 'v1', serverId, worldId.value],
queryFn: () =>
client.archon.content_v1.getAddons(serverId, worldId.value!, { from_modpack: false }),
staleTime: 30_000,
Expand Down
2 changes: 1 addition & 1 deletion apps/app-frontend/src/pages/hosting/manage/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ watch(
breadcrumbs.setName('Server', server.name)
breadcrumbs.setContext({
name: server.name,
link: `/hosting/manage/${serverId.value}/content`,
link: `/hosting/manage/${serverId.value}/worlds`,
})
}
},
Expand Down
16 changes: 16 additions & 0 deletions apps/app-frontend/src/pages/hosting/manage/World.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<template>
<ServersManageWorldRootLayout>
<RouterView v-slot="{ Component }">
<template v-if="Component">
<Suspense>
<component :is="Component" />
</Suspense>
</template>
</RouterView>
</ServersManageWorldRootLayout>
</template>

<script setup lang="ts">
import { ServersManageWorldRootLayout } from '@modrinth/ui'
import { RouterView } from 'vue-router'
</script>
3 changes: 2 additions & 1 deletion apps/app-frontend/src/pages/hosting/manage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Content from './Content.vue'
import Files from './Files.vue'
import Index from './Index.vue'
import Overview from './Overview.vue'
import World from './World.vue'
import Worlds from './Worlds.vue'

export { Backups, Content, Files, Index, Overview, Worlds }
export { Backups, Content, Files, Index, Overview, World, Worlds }
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export function createServerInstallContent(opts: {
if (serverFlowFrom.value === 'reset-server') {
return `/hosting/manage/${sid}?openSettings=installation`
}
return `/hosting/manage/${sid}/content`
return getServerWorldContentPath(sid, effectiveServerWorldId.value)
})
const serverBackLabel = computed(() => {
if (serverFlowFrom.value === 'onboarding') return 'Back to setup'
Expand Down Expand Up @@ -351,7 +351,7 @@ export function createServerInstallContent(opts: {

if (serverFlowFrom.value === 'onboarding') {
await client.archon.servers_v1.endIntro(sid)
await router.push(`/hosting/manage/${sid}/content`)
await router.push(getServerWorldContentPath(sid, wid))
return
}

Expand All @@ -366,6 +366,11 @@ export function createServerInstallContent(opts: {
serverContentProjectIds.value = new Set([...serverContentProjectIds.value, id])
}

function getServerWorldContentPath(serverId: string, worldId: string | null) {
const base = `/hosting/manage/${encodeURIComponent(serverId)}/worlds`
return worldId ? `${base}/${encodeURIComponent(worldId)}` : base
}

return {
serverIdQuery,
worldIdQuery,
Expand Down
34 changes: 34 additions & 0 deletions apps/app-frontend/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,40 @@ export default new createRouter({
breadcrumb: [{ name: '?Server' }],
},
},
{
path: 'worlds/:world_id',
name: 'ServerManageWorld',
component: Hosting.World,
meta: {
breadcrumb: [{ name: '?Server' }],
},
children: [
{
path: '',
name: 'ServerManageWorldContent',
component: Hosting.Content,
meta: {
breadcrumb: [{ name: '?Server' }],
},
},
{
path: 'files',
name: 'ServerManageWorldFiles',
component: Hosting.Files,
meta: {
breadcrumb: [{ name: '?Server' }],
},
},
{
path: 'backups',
name: 'ServerManageWorldBackups',
component: Hosting.Backups,
meta: {
breadcrumb: [{ name: '?Server' }],
},
},
],
},
{
path: 'files',
name: 'ServerManageFiles',
Expand Down
40 changes: 40 additions & 0 deletions apps/frontend/src/middleware/server-world-tabs.global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { createModrinthClient } from '~/helpers/api.ts'

export default defineNuxtRouteMiddleware(async (to) => {
const match = to.path.match(/^\/hosting\/manage\/([^/]+)\/(content|files|backups)\/?$/)
if (!match) return

const serverId = decodeURIComponent(match[1])
const tab = match[2]
const worldsPath = `/hosting/manage/${encodeURIComponent(serverId)}/worlds`
const tabPath = tab === 'content' ? '' : `/${tab}`
const auth = await useAuth()

if (auth.value.token) {
try {
const config = useRuntimeConfig()
const client = createModrinthClient(auth, {
apiBaseUrl: config.public.apiBaseUrl.replace('/v2/', '/'),
archonBaseUrl: config.public.pyroBaseUrl.replace('/v2/', '/'),
rateLimitKey: config.rateLimitKey,
})
const serverFull = await client.archon.servers_v1.get(serverId)
const world = serverFull.worlds.find((item) => item.is_active) ?? serverFull.worlds[0]

if (world) {
return navigateTo(
{
path: `${worldsPath}/${encodeURIComponent(world.id)}${tabPath}`,
query: to.query,
hash: to.hash,
},
{ replace: true },
)
}
} catch {
return navigateTo({ path: worldsPath, query: to.query, hash: to.hash }, { replace: true })
}
}

return navigateTo({ path: worldsPath, query: to.query, hash: to.hash }, { replace: true })
})
16 changes: 12 additions & 4 deletions apps/frontend/src/pages/discover/[type]/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,10 @@ function syncHiddenInstalledProjectIds() {
hiddenInstalledProjectIdsInitialized.value = true
}

const contentQueryKey = computed(() => ['content', 'list', currentServerId.value ?? ''] as const)
const contentQueryKey = computed(
() =>
['content', 'list', 'v1', currentServerId.value ?? '', currentWorldId.value ?? null] as const,
)
const { data: serverContentData, error: serverContentError } = useQuery({
queryKey: contentQueryKey,
queryFn: () => client.archon.content_v1.getAddons(currentServerId.value!, currentWorldId.value!),
Expand Down Expand Up @@ -252,7 +255,7 @@ const installContentMutation = useMutation({
}),
onSuccess: () => {
if (currentServerId.value) {
queryClient.refetchQueries({ queryKey: ['content', 'list', currentServerId.value] })
queryClient.refetchQueries({ queryKey: contentQueryKey.value })
}
},
})
Expand Down Expand Up @@ -551,7 +554,7 @@ async function onModpackFlowCreate(config: CreationFlowContextValue) {
if (fromContext.value === 'onboarding') {
await client.archon.servers_v1.endIntro(currentServerId.value)
queryClient.invalidateQueries({ queryKey: ['servers', 'detail', currentServerId.value] })
navigateTo(`/hosting/manage/${currentServerId.value}/content`)
navigateTo(getServerWorldContentPath(currentServerId.value, currentWorldId.value ?? null))
} else {
navigateTo(`/hosting/manage/${currentServerId.value}?openSettings=installation`)
}
Expand All @@ -566,9 +569,14 @@ const serverBackUrl = computed(() => {
const id = serverData.value.server_id
if (fromContext.value === 'onboarding') return `/hosting/manage/${id}?resumeModal=setup-type`
if (fromContext.value === 'reset-server') return `/hosting/manage/${id}?openSettings=installation`
return `/hosting/manage/${id}/content`
return getServerWorldContentPath(id, currentWorldId.value ?? null)
})

function getServerWorldContentPath(serverId: string, worldId: string | null) {
const base = `/hosting/manage/${encodeURIComponent(serverId)}/worlds`
return worldId ? `${base}/${encodeURIComponent(worldId)}` : base
}

const serverBackLabel = computed(() => {
if (fromContext.value === 'onboarding') return 'Back to setup'
if (fromContext.value === 'reset-server') return 'Cancel reset'
Expand Down
11 changes: 11 additions & 0 deletions apps/frontend/src/pages/hosting/manage/[id]/worlds/[world_id].vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ServersManageWorldRootLayout } from '@modrinth/ui'

const route = useNativeRoute()
</script>

<template>
<ServersManageWorldRootLayout>
<NuxtPage :route="route" />
</ServersManageWorldRootLayout>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const flags = useFeatureFlags()
if (worldId.value) {
try {
await queryClient.ensureQueryData({
queryKey: ['backups', 'list', serverId],
queryKey: ['backups', 'list', serverId, worldId.value],
queryFn: () => client.archon.backups_v1.list(serverId, worldId.value!),
staleTime: 30_000,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const queryClient = useQueryClient()
if (worldId.value) {
try {
await queryClient.ensureQueryData({
queryKey: ['content', 'list', 'v1', serverId],
queryKey: ['content', 'list', 'v1', serverId, worldId.value],
queryFn: () =>
client.archon.content_v1.getAddons(serverId, worldId.value!, { from_modpack: false }),
staleTime: 30_000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ onMounted(() => {
isClient.value = true
})

const { serverId } = injectModrinthServerContext()
const { serverId, worldId } = injectModrinthServerContext()
const { featureFlags } = injectPageContext()

const props = withDefaults(
Expand Down Expand Up @@ -198,7 +198,9 @@ const metrics = computed(() => {
showGraph: false,
chartOptions: null as ReturnType<typeof buildChartOptions> | null,
series: null as { name: string; data: number[] }[] | null,
link: `/hosting/manage/${encodeURIComponent(serverId)}/files`,
link: worldId.value
? `/hosting/manage/${encodeURIComponent(serverId)}/worlds/${encodeURIComponent(worldId.value)}/files`
: `/hosting/manage/${encodeURIComponent(serverId)}/worlds`,
}

if (props.loading) {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/servers/ServerSettingsModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ async function show({ serverId, tabIndex, tabId }: ShowOptions) {
queryFn: () => client.archon.properties_v1.getProperties(targetServerId, worldId.value!),
})
queryClient.prefetchQuery({
queryKey: ['content', 'list', 'v1', targetServerId],
queryKey: ['content', 'list', 'v1', targetServerId, worldId.value],
queryFn: () =>
client.archon.content_v1.getAddons(targetServerId, worldId.value!, {
from_modpack: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import InstallingBanner, {
type SyncProgress,
} from '#ui/components/servers/InstallingBanner.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { useServerBackupsQueue } from '#ui/composables/server-backups-queue'
import { useServerBackupsQueue } from '#ui/composables/servers/server-backups-queue.ts'
import type { FileOperation } from '#ui/layouts/shared/files-tab/types'
import { injectModrinthClient, injectModrinthServerContext } from '#ui/providers'

Expand Down Expand Up @@ -55,8 +55,12 @@ const messages = defineMessages({
},
})

const isOnContentTab = computed(() => route.path.includes('/content'))
const isOnFilesTab = computed(() => route.path.includes('/files'))
const isOnContentTab = computed(
() =>
route.path.includes('/content') ||
(!!route.params.world_id && !isOnFilesTab.value && !route.path.includes('/backups')),
)

const bannerCoversInstalling = computed(
() => ctx.server.value?.status === 'installing' || ctx.isSyncingContent.value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ const props = defineProps<{
backups?: Archon.BackupsQueue.v1.BackupQueueBackup[]
}>()

const backupsQueryKey = ['backups', 'queue', ctx.serverId]
const backupsQueryKey = computed(() => ['backups', 'queue', ctx.serverId, ctx.worldId.value])

const createMutation = useMutation({
mutationFn: (name: string) =>
client.archon.backups_queue_v1.create(ctx.serverId, ctx.worldId.value!, { name }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: backupsQueryKey }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: backupsQueryKey.value }),
})

const modal = ref<InstanceType<typeof NewModal>>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ const props = defineProps<{
backups?: Archon.BackupsQueue.v1.BackupQueueBackup[]
}>()

const backupsQueryKey = ['backups', 'queue', ctx.serverId]
const backupsQueryKey = computed(() => ['backups', 'queue', ctx.serverId, ctx.worldId.value])

const renameMutation = useMutation({
mutationFn: ({ backupId, name }: { backupId: string; name: string }) =>
client.archon.backups_v1.rename(ctx.serverId, ctx.worldId.value!, backupId, { name }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: backupsQueryKey }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: backupsQueryKey.value }),
})

const modal = ref<InstanceType<typeof NewModal>>()
Expand Down
Loading
Loading