chore: rename worlds -> instances

This commit is contained in:
Calum H. (IMB11)
2026-06-26 17:09:22 +01:00
parent f799e6f67e
commit f097409b92
33 changed files with 227 additions and 172 deletions
+6 -6
View File
@@ -496,7 +496,7 @@ const sidebarOverlayScrollbarsOptions = Object.freeze({
}) })
router.beforeEach(async (to) => { router.beforeEach(async (to) => {
const redirect = await resolveLegacyServerWorldTabRedirect(to) const redirect = await resolveLegacyServerInstanceTabRedirect(to)
if (redirect) return redirect if (redirect) return redirect
}) })
@@ -531,7 +531,7 @@ function onSuspensePending() {
suspenseToken = loading.begin() suspenseToken = loading.begin()
} }
async function resolveLegacyServerWorldTabRedirect(to) { async function resolveLegacyServerInstanceTabRedirect(to) {
if (!['ServerManageContent', 'ServerManageFiles', 'ServerManageBackups'].includes(to.name)) { if (!['ServerManageContent', 'ServerManageFiles', 'ServerManageBackups'].includes(to.name)) {
return null return null
} }
@@ -541,14 +541,14 @@ async function resolveLegacyServerWorldTabRedirect(to) {
const tabPath = const tabPath =
to.name === 'ServerManageFiles' ? '/files' : to.name === 'ServerManageBackups' ? '/backups' : '' to.name === 'ServerManageFiles' ? '/files' : to.name === 'ServerManageBackups' ? '/backups' : ''
const worldsPath = `/hosting/manage/${encodeURIComponent(serverId)}/worlds` const instancesPath = `/hosting/manage/${encodeURIComponent(serverId)}/instances`
try { try {
const serverFull = await tauriApiClient.archon.servers_v1.get(serverId) const serverFull = await tauriApiClient.archon.servers_v1.get(serverId)
const world = serverFull.worlds.find((item) => item.is_active) ?? serverFull.worlds[0] const world = serverFull.worlds.find((item) => item.is_active) ?? serverFull.worlds[0]
if (world) { if (world) {
return { return {
path: `${worldsPath}/${encodeURIComponent(world.id)}${tabPath}`, path: `${instancesPath}/${encodeURIComponent(world.id)}${tabPath}`,
query: to.query, query: to.query,
hash: to.hash, hash: to.hash,
replace: true, replace: true,
@@ -556,7 +556,7 @@ async function resolveLegacyServerWorldTabRedirect(to) {
} }
} catch { } catch {
return { return {
path: worldsPath, path: instancesPath,
query: to.query, query: to.query,
hash: to.hash, hash: to.hash,
replace: true, replace: true,
@@ -564,7 +564,7 @@ async function resolveLegacyServerWorldTabRedirect(to) {
} }
return { return {
path: worldsPath, path: instancesPath,
query: to.query, query: to.query,
hash: to.hash, hash: to.hash,
replace: true, replace: true,
@@ -93,7 +93,7 @@ watch(
breadcrumbs.setName('Server', server.name) breadcrumbs.setName('Server', server.name)
breadcrumbs.setContext({ breadcrumbs.setContext({
name: server.name, name: server.name,
link: `/hosting/manage/${serverId.value}/worlds`, link: `/hosting/manage/${serverId.value}/instances`,
}) })
} }
}, },
@@ -1,5 +1,5 @@
<template> <template>
<ServersManageWorldRootLayout> <ServersManageInstanceRootLayout>
<RouterView v-slot="{ Component }"> <RouterView v-slot="{ Component }">
<template v-if="Component"> <template v-if="Component">
<Suspense> <Suspense>
@@ -7,10 +7,10 @@
</Suspense> </Suspense>
</template> </template>
</RouterView> </RouterView>
</ServersManageWorldRootLayout> </ServersManageInstanceRootLayout>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ServersManageWorldRootLayout } from '@modrinth/ui' import { ServersManageInstanceRootLayout } from '@modrinth/ui'
import { RouterView } from 'vue-router' import { RouterView } from 'vue-router'
</script> </script>
@@ -0,0 +1,7 @@
<script setup lang="ts">
import { ServersManageInstancesPage } from '@modrinth/ui'
</script>
<template>
<ServersManageInstancesPage />
</template>
@@ -1,7 +0,0 @@
<script setup lang="ts">
import { ServersManageWorldsPage } from '@modrinth/ui'
</script>
<template>
<ServersManageWorldsPage />
</template>
@@ -3,8 +3,8 @@ import Backups from './Backups.vue'
import Content from './Content.vue' import Content from './Content.vue'
import Files from './Files.vue' import Files from './Files.vue'
import Index from './Index.vue' import Index from './Index.vue'
import Instance from './Instance.vue'
import Instances from './Instances.vue'
import Overview from './Overview.vue' import Overview from './Overview.vue'
import World from './World.vue'
import Worlds from './Worlds.vue'
export { Access, Backups, Content, Files, Index, Overview, World, Worlds } export { Access, Backups, Content, Files, Index, Instance, Instances, Overview }
@@ -252,7 +252,7 @@ export function createServerInstallContent(opts: {
if (serverFlowFrom.value === 'reset-server') { if (serverFlowFrom.value === 'reset-server') {
return `/hosting/manage/${sid}?openSettings=installation` return `/hosting/manage/${sid}?openSettings=installation`
} }
return getServerWorldContentPath(sid, effectiveServerWorldId.value) return getServerInstanceContentPath(sid, effectiveServerWorldId.value)
}) })
const serverBackLabel = computed(() => { const serverBackLabel = computed(() => {
if (serverFlowFrom.value === 'onboarding') return 'Back to setup' if (serverFlowFrom.value === 'onboarding') return 'Back to setup'
@@ -424,7 +424,7 @@ export function createServerInstallContent(opts: {
if (isInstallingQueuedServerInstalls.value) return false if (isInstallingQueuedServerInstalls.value) return false
if (!serverId || !worldId) { if (!serverId || !worldId) {
handleError(new Error('No server world is available for install.')) handleError(new Error('No server instance is available for install.'))
return false return false
} }
@@ -556,7 +556,7 @@ export function createServerInstallContent(opts: {
if (serverFlowFrom.value === 'onboarding') { if (serverFlowFrom.value === 'onboarding') {
await client.archon.servers_v1.endIntro(sid) await client.archon.servers_v1.endIntro(sid)
await router.push(getServerWorldContentPath(sid, wid)) await router.push(getServerInstanceContentPath(sid, wid))
return return
} }
@@ -571,8 +571,8 @@ export function createServerInstallContent(opts: {
serverContentProjectIds.value = new Set([...serverContentProjectIds.value, id]) serverContentProjectIds.value = new Set([...serverContentProjectIds.value, id])
} }
function getServerWorldContentPath(serverId: string, worldId: string | null) { function getServerInstanceContentPath(serverId: string, worldId: string | null) {
const base = `/hosting/manage/${encodeURIComponent(serverId)}/worlds` const base = `/hosting/manage/${encodeURIComponent(serverId)}/instances`
return worldId ? `${base}/${encodeURIComponent(worldId)}` : base return worldId ? `${base}/${encodeURIComponent(worldId)}` : base
} }
+9 -9
View File
@@ -58,24 +58,24 @@ export default new createRouter({
}, },
}, },
{ {
path: 'worlds', path: 'instances',
name: 'ServerManageWorlds', name: 'ServerManageInstances',
component: Hosting.Worlds, component: Hosting.Instances,
meta: { meta: {
breadcrumb: [{ name: '?Server' }], breadcrumb: [{ name: '?Server' }],
}, },
}, },
{ {
path: 'worlds/:world_id', path: 'instances/:instance_id',
name: 'ServerManageWorld', name: 'ServerManageInstance',
component: Hosting.World, component: Hosting.Instance,
meta: { meta: {
breadcrumb: [{ name: '?Server' }], breadcrumb: [{ name: '?Server' }],
}, },
children: [ children: [
{ {
path: '', path: '',
name: 'ServerManageWorldContent', name: 'ServerManageInstanceContent',
component: Hosting.Content, component: Hosting.Content,
meta: { meta: {
breadcrumb: [{ name: '?Server' }], breadcrumb: [{ name: '?Server' }],
@@ -83,7 +83,7 @@ export default new createRouter({
}, },
{ {
path: 'files', path: 'files',
name: 'ServerManageWorldFiles', name: 'ServerManageInstanceFiles',
component: Hosting.Files, component: Hosting.Files,
meta: { meta: {
breadcrumb: [{ name: '?Server' }], breadcrumb: [{ name: '?Server' }],
@@ -91,7 +91,7 @@ export default new createRouter({
}, },
{ {
path: 'backups', path: 'backups',
name: 'ServerManageWorldBackups', name: 'ServerManageInstanceBackups',
component: Hosting.Backups, component: Hosting.Backups,
meta: { meta: {
breadcrumb: [{ name: '?Server' }], breadcrumb: [{ name: '?Server' }],
@@ -65,7 +65,7 @@ const messages = defineMessages({
}, },
noServerWorld: { noServerWorld: {
id: 'discover.install.error.no-server-world', id: 'discover.install.error.no-server-world',
defaultMessage: 'No server world is available for install.', defaultMessage: 'No server instance is available for install.',
}, },
backToSetup: { backToSetup: {
id: 'discover.install.back-to-setup', id: 'discover.install.back-to-setup',
@@ -662,7 +662,7 @@ export function useServerInstallContent({
if (fromContext.value === 'onboarding') { if (fromContext.value === 'onboarding') {
await client.archon.servers_v1.endIntro(currentServerId.value) await client.archon.servers_v1.endIntro(currentServerId.value)
queryClient.invalidateQueries({ queryKey: ['servers', 'detail', currentServerId.value] }) queryClient.invalidateQueries({ queryKey: ['servers', 'detail', currentServerId.value] })
navigateTo(getServerWorldContentPath(currentServerId.value, currentWorldId.value ?? null)) navigateTo(getServerInstanceContentPath(currentServerId.value, currentWorldId.value ?? null))
} else { } else {
navigateTo(`/hosting/manage/${currentServerId.value}?openSettings=installation`) navigateTo(`/hosting/manage/${currentServerId.value}?openSettings=installation`)
} }
@@ -678,11 +678,11 @@ export function useServerInstallContent({
if (fromContext.value === 'onboarding') return `/hosting/manage/${id}?resumeModal=setup-type` if (fromContext.value === 'onboarding') return `/hosting/manage/${id}?resumeModal=setup-type`
if (fromContext.value === 'reset-server') if (fromContext.value === 'reset-server')
return `/hosting/manage/${id}?openSettings=installation` return `/hosting/manage/${id}?openSettings=installation`
return getServerWorldContentPath(id, currentWorldId.value) return getServerInstanceContentPath(id, currentWorldId.value)
}) })
function getServerWorldContentPath(serverId: string, worldId: string | null) { function getServerInstanceContentPath(serverId: string, worldId: string | null) {
const base = `/hosting/manage/${encodeURIComponent(serverId)}/worlds` const base = `/hosting/manage/${encodeURIComponent(serverId)}/instances`
return worldId ? `${base}/${encodeURIComponent(worldId)}` : base return worldId ? `${base}/${encodeURIComponent(worldId)}` : base
} }
+3 -3
View File
@@ -1956,7 +1956,7 @@
"message": "Cancel reset" "message": "Cancel reset"
}, },
"discover.install.error.no-server-world": { "discover.install.error.no-server-world": {
"message": "No server world is available for install." "message": "No server instance is available for install."
}, },
"discover.install.error.unsupported-content-type": { "discover.install.error.unsupported-content-type": {
"message": "This content type cannot be installed to a server from Discover." "message": "This content type cannot be installed to a server from Discover."
@@ -3938,8 +3938,8 @@
"servers.manage.content.title": { "servers.manage.content.title": {
"message": "Content - {serverName} - Modrinth" "message": "Content - {serverName} - Modrinth"
}, },
"servers.manage.worlds.meta.title": { "servers.manage.instances.meta.title": {
"message": "Worlds - {server} - Modrinth" "message": "Instances - {server} - Modrinth"
}, },
"servers.notice.actions": { "servers.notice.actions": {
"message": "Actions" "message": "Actions"
@@ -6,7 +6,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
const serverId = decodeURIComponent(match[1]) const serverId = decodeURIComponent(match[1])
const tab = match[2] const tab = match[2]
const worldsPath = `/hosting/manage/${encodeURIComponent(serverId)}/worlds` const instancesPath = `/hosting/manage/${encodeURIComponent(serverId)}/instances`
const tabPath = tab === 'content' ? '' : `/${tab}` const tabPath = tab === 'content' ? '' : `/${tab}`
const auth = await useAuth() const auth = await useAuth()
@@ -24,7 +24,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
if (world) { if (world) {
return navigateTo( return navigateTo(
{ {
path: `${worldsPath}/${encodeURIComponent(world.id)}${tabPath}`, path: `${instancesPath}/${encodeURIComponent(world.id)}${tabPath}`,
query: to.query, query: to.query,
hash: to.hash, hash: to.hash,
}, },
@@ -32,9 +32,9 @@ export default defineNuxtRouteMiddleware(async (to) => {
) )
} }
} catch { } catch {
return navigateTo({ path: worldsPath, query: to.query, hash: to.hash }, { replace: true }) return navigateTo({ path: instancesPath, query: to.query, hash: to.hash }, { replace: true })
} }
} }
return navigateTo({ path: worldsPath, query: to.query, hash: to.hash }, { replace: true }) return navigateTo({ path: instancesPath, query: to.query, hash: to.hash }, { replace: true })
}) })
@@ -0,0 +1,11 @@
<script setup lang="ts">
import { ServersManageInstanceRootLayout } from '@modrinth/ui'
const route = useNativeRoute()
</script>
<template>
<ServersManageInstanceRootLayout>
<NuxtPage :route="route" />
</ServersManageInstanceRootLayout>
</template>
@@ -3,7 +3,7 @@ import {
commonMessages, commonMessages,
defineMessages, defineMessages,
injectModrinthServerContext, injectModrinthServerContext,
ServersManageWorldsPage, ServersManageInstancesPage,
useVIntl, useVIntl,
} from '@modrinth/ui' } from '@modrinth/ui'
@@ -12,8 +12,8 @@ const { formatMessage } = useVIntl()
const messages = defineMessages({ const messages = defineMessages({
title: { title: {
id: 'servers.manage.worlds.meta.title', id: 'servers.manage.instances.meta.title',
defaultMessage: 'Worlds - {server} - Modrinth', defaultMessage: 'Instances - {server} - Modrinth',
}, },
}) })
@@ -26,5 +26,5 @@ useHead({
</script> </script>
<template> <template>
<ServersManageWorldsPage /> <ServersManageInstancesPage />
</template> </template>
@@ -1,11 +0,0 @@
<script setup lang="ts">
import { ServersManageWorldRootLayout } from '@modrinth/ui'
const route = useNativeRoute()
</script>
<template>
<ServersManageWorldRootLayout>
<NuxtPage :route="route" />
</ServersManageWorldRootLayout>
</template>
@@ -191,8 +191,8 @@ const metrics = computed(() => {
chartOptions: null as ReturnType<typeof buildChartOptions> | null, chartOptions: null as ReturnType<typeof buildChartOptions> | null,
series: null as { name: string; data: number[] }[] | null, series: null as { name: string; data: number[] }[] | null,
link: worldId.value link: worldId.value
? `/hosting/manage/${encodeURIComponent(serverId)}/worlds/${encodeURIComponent(worldId.value)}/files` ? `/hosting/manage/${encodeURIComponent(serverId)}/instances/${encodeURIComponent(worldId.value)}/files`
: `/hosting/manage/${encodeURIComponent(serverId)}/worlds`, : `/hosting/manage/${encodeURIComponent(serverId)}/instances`,
} }
if (props.loading) { if (props.loading) {
@@ -59,7 +59,7 @@ const isOnFilesTab = computed(() => route.path.includes('/files'))
const isOnContentTab = computed( const isOnContentTab = computed(
() => () =>
route.path.includes('/content') || route.path.includes('/content') ||
(!!route.params.world_id && !isOnFilesTab.value && !route.path.includes('/backups')), (!!route.params.instance_id && !isOnFilesTab.value && !route.path.includes('/backups')),
) )
const bannerCoversInstalling = computed( const bannerCoversInstalling = computed(
@@ -76,7 +76,7 @@
<div class="mt-6 flex flex-col gap-1"> <div class="mt-6 flex flex-col gap-1">
<h2 class="m-0 text-2xl font-semibold leading-8 text-contrast">{{ world.name }}</h2> <h2 class="m-0 text-2xl font-semibold leading-8 text-contrast">{{ world.name }}</h2>
<p class="m-0 text-base leading-6 text-secondary"> <p class="m-0 text-base leading-6 text-secondary">
{{ formatMessage(messages.newWorldInstance) }} {{ formatMessage(messages.newInstance) }}
</p> </p>
</div> </div>
</div> </div>
@@ -85,7 +85,7 @@
<ButtonStyled color="brand"> <ButtonStyled color="brand">
<button class="w-full !h-10" @click="emit('create', world.id)"> <button class="w-full !h-10" @click="emit('create', world.id)">
<PlusIcon aria-hidden="true" /> <PlusIcon aria-hidden="true" />
{{ formatMessage(messages.createWorld) }} {{ formatMessage(messages.createInstance) }}
</button> </button>
</ButtonStyled> </ButtonStyled>
</div> </div>
@@ -172,12 +172,12 @@
<ButtonStyled> <ButtonStyled>
<button class="!shadow-none" @click="emit('edit', world.id)"> <button class="!shadow-none" @click="emit('edit', world.id)">
<PencilIcon aria-hidden="true" /> <PencilIcon aria-hidden="true" />
{{ formatMessage(messages.editWorld) }} {{ formatMessage(messages.editInstance) }}
</button> </button>
</ButtonStyled> </ButtonStyled>
<ButtonStyled circular> <ButtonStyled circular>
<button <button
v-tooltip="formatMessage(messages.worldSettings)" v-tooltip="formatMessage(messages.instanceSettings)"
class="!shadow-none" class="!shadow-none"
@click="emit('settings', world.id)" @click="emit('settings', world.id)"
> >
@@ -203,44 +203,44 @@ import { truncatedTooltip } from '#ui/utils'
import { commonMessages } from '#ui/utils/common-messages' import { commonMessages } from '#ui/utils/common-messages'
const messages = defineMessages({ const messages = defineMessages({
newWorldInstance: { newInstance: {
id: 'servers.manage.worlds.card.empty-description', id: 'servers.manage.instances.card.empty-description',
defaultMessage: 'New world instance', defaultMessage: 'New instance',
}, },
createWorld: { createInstance: {
id: 'servers.manage.worlds.card.create', id: 'servers.manage.instances.card.create',
defaultMessage: 'Create world', defaultMessage: 'Create instance',
}, },
active: { active: {
id: 'servers.manage.worlds.card.active', id: 'servers.manage.instances.card.active',
defaultMessage: 'Active', defaultMessage: 'Active',
}, },
none: { none: {
id: 'servers.manage.worlds.card.none', id: 'servers.manage.instances.card.none',
defaultMessage: 'None', defaultMessage: 'None',
}, },
installedContent: { installedContent: {
id: 'servers.manage.worlds.card.installed-content', id: 'servers.manage.instances.card.installed-content',
defaultMessage: 'Installed content', defaultMessage: 'Installed content',
}, },
lastActive: { lastActive: {
id: 'servers.manage.worlds.card.last-active', id: 'servers.manage.instances.card.last-active',
defaultMessage: 'Last active', defaultMessage: 'Last active',
}, },
created: { created: {
id: 'servers.manage.worlds.card.created', id: 'servers.manage.instances.card.created',
defaultMessage: 'Created', defaultMessage: 'Created',
}, },
editWorld: { editInstance: {
id: 'servers.manage.worlds.card.edit', id: 'servers.manage.instances.card.edit',
defaultMessage: 'Edit world', defaultMessage: 'Edit instance',
}, },
worldSettings: { instanceSettings: {
id: 'servers.manage.worlds.card.settings', id: 'servers.manage.instances.card.settings',
defaultMessage: 'World settings', defaultMessage: 'Instance settings',
}, },
notTrackedYet: { notTrackedYet: {
id: 'servers.manage.worlds.card.not-tracked-yet', id: 'servers.manage.instances.card.not-tracked-yet',
defaultMessage: 'Not tracked yet', defaultMessage: 'Not tracked yet',
}, },
}) })
@@ -319,8 +319,8 @@ const advancedActionTooltip = computed(() =>
) )
const filesTabLink = computed(() => const filesTabLink = computed(() =>
worldId.value worldId.value
? `/hosting/manage/${encodeURIComponent(serverId)}/worlds/${encodeURIComponent(worldId.value)}/files?path=/&editing=server.properties` ? `/hosting/manage/${encodeURIComponent(serverId)}/instances/${encodeURIComponent(worldId.value)}/files?path=/&editing=server.properties`
: `/hosting/manage/${encodeURIComponent(serverId)}/worlds`, : `/hosting/manage/${encodeURIComponent(serverId)}/instances`,
) )
const serverSettings = injectServerSettings(null) const serverSettings = injectServerSettings(null)
@@ -93,8 +93,8 @@
</ErrorInformationCard> </ErrorInformationCard>
</div> </div>
<div <div
v-else-if="serverData && isWorldDetailRoute" v-else-if="serverData && isInstanceDetailRoute"
data-pyro-world-manager-root data-pyro-instance-manager-root
class="experimental-styles-within relative mx-auto box-border flex w-full min-w-0 flex-col px-6 transition-all duration-300" class="experimental-styles-within relative mx-auto box-border flex w-full min-w-0 flex-col px-6 transition-all duration-300"
:class="[ :class="[
'server-panel-' + revealState, 'server-panel-' + revealState,
@@ -316,7 +316,7 @@
</template> </template>
</div> </div>
<div <div
v-if="showAdvancedDebugInfo && !isWorldDetailRoute" v-if="showAdvancedDebugInfo && !isInstanceDetailRoute"
class="experimental-styles-within relative mx-auto mt-6 box-border w-full min-w-0 max-w-[1280px] px-6" class="experimental-styles-within relative mx-auto mt-6 box-border w-full min-w-0 max-w-[1280px] px-6"
> >
<h2 class="m-0 text-lg font-extrabold text-contrast"> <h2 class="m-0 text-lg font-extrabold text-contrast">
@@ -632,9 +632,9 @@ const messages = defineMessages({
id: 'servers.manage.nav.overview', id: 'servers.manage.nav.overview',
defaultMessage: 'Overview', defaultMessage: 'Overview',
}, },
worldsNav: { instancesNav: {
id: 'servers.manage.nav.worlds', id: 'servers.manage.nav.instances',
defaultMessage: 'Worlds', defaultMessage: 'Instances',
}, },
errorDismissingNotice: { errorDismissingNotice: {
id: 'servers.manage.notice.dismiss-error', id: 'servers.manage.notice.dismiss-error',
@@ -769,14 +769,14 @@ const { data: serverFull } = useQuery({
}) })
const worldId = computed(() => { const worldId = computed(() => {
const routeWorldId = getRouteParam(route.params.world_id) const routeInstanceId = getRouteParam(route.params.instance_id)
if (routeWorldId) return routeWorldId if (routeInstanceId) return routeInstanceId
if (!serverFull.value) return null if (!serverFull.value) return null
const activeWorld = serverFull.value.worlds.find((w) => w.is_active) const activeWorld = serverFull.value.worlds.find((w) => w.is_active)
return activeWorld?.id ?? serverFull.value.worlds[0]?.id ?? null return activeWorld?.id ?? serverFull.value.worlds[0]?.id ?? null
}) })
const isWorldDetailRoute = computed(() => !!getRouteParam(route.params.world_id)) const isInstanceDetailRoute = computed(() => !!getRouteParam(route.params.instance_id))
const activeWorldName = computed(() => { const activeWorldName = computed(() => {
if (!serverFull.value) return null if (!serverFull.value) return null
const activeWorld = serverFull.value.worlds.find((world) => world.is_active) const activeWorld = serverFull.value.worlds.find((world) => world.is_active)
@@ -789,7 +789,7 @@ function getRouteParam(param: string | string[] | undefined): string | null {
} }
function getWorldPath(targetWorldId: string) { function getWorldPath(targetWorldId: string) {
return `/hosting/manage/${encodeURIComponent(props.serverId)}/worlds/${encodeURIComponent(targetWorldId)}` return `/hosting/manage/${encodeURIComponent(props.serverId)}/instances/${encodeURIComponent(targetWorldId)}`
} }
const { handleWsBackupProgress, busyReasons: backupsBusy } = useServerBackupsQueue( const { handleWsBackupProgress, busyReasons: backupsBusy } = useServerBackupsQueue(
@@ -1051,8 +1051,8 @@ const navLinks = computed<Tab[]>(() => [
subpages: [], subpages: [],
}, },
{ {
label: formatMessage(messages.worldsNav), label: formatMessage(messages.instancesNav),
href: `/hosting/manage/${encodeURIComponent(props.serverId)}/worlds`, href: `/hosting/manage/${encodeURIComponent(props.serverId)}/instances`,
icon: WorldIcon, icon: WorldIcon,
subpages: [], subpages: [],
}, },
@@ -1476,7 +1476,7 @@ const copyServerDebugInfo = () => {
const openInstallLog = () => { const openInstallLog = () => {
const filesPath = worldId.value const filesPath = worldId.value
? `${getWorldPath(worldId.value)}/files` ? `${getWorldPath(worldId.value)}/files`
: `/hosting/manage/${encodeURIComponent(props.serverId)}/worlds` : `/hosting/manage/${encodeURIComponent(props.serverId)}/instances`
const url = `${filesPath}?editing=${encodeURIComponent(errorLogFile.value)}` const url = `${filesPath}?editing=${encodeURIComponent(errorLogFile.value)}`
window.history.pushState({}, '', url) window.history.pushState({}, '', url)
window.dispatchEvent(new PopStateEvent('popstate')) window.dispatchEvent(new PopStateEvent('popstate'))
@@ -386,7 +386,7 @@ const error = computed(() => {
}) })
const refetch = () => query.refetch() const refetch = () => query.refetch()
/** Until world exists we cannot fetch; `isLoading` is false while the query is disabled, which would flash empty state. */ /** Until the instance exists we cannot fetch; `isLoading` is false while the query is disabled, which would flash empty state. */
const backupsReadyPending = computed( const backupsReadyPending = computed(
() => !worldId.value || (query.data.value === undefined && !query.error.value), () => !worldId.value || (query.data.value === undefined && !query.error.value),
) )
@@ -2,11 +2,11 @@
<div class="flex min-h-[36rem] flex-col gap-6 text-primary"> <div class="flex min-h-[36rem] flex-col gap-6 text-primary">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<RouterLink <RouterLink
:to="worldsPath" :to="instancesPath"
class="flex w-fit items-center gap-1 text-base font-medium text-blue hover:underline" class="flex w-fit items-center gap-1 text-base font-medium text-blue hover:underline"
> >
<ChevronLeftIcon class="size-4" aria-hidden="true" /> <ChevronLeftIcon class="size-4" aria-hidden="true" />
{{ formatMessage(messages.allWorlds) }} {{ formatMessage(messages.allInstances) }}
</RouterLink> </RouterLink>
<div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between"> <div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
@@ -23,10 +23,10 @@
</div> </div>
<div class="flex shrink-0 items-center gap-2"> <div class="flex shrink-0 items-center gap-2">
<PanelServerActionButton size="large" start-label="Start world" /> <PanelServerActionButton size="large" start-label="Start instance" />
<ButtonStyled size="large" circular> <ButtonStyled size="large" circular>
<button <button
v-tooltip="formatMessage(messages.worldSettings)" v-tooltip="formatMessage(messages.instanceSettings)"
@click="openServerSettings({ tabId: 'installation' })" @click="openServerSettings({ tabId: 'installation' })"
> >
<SettingsIcon aria-hidden="true" /> <SettingsIcon aria-hidden="true" />
@@ -78,9 +78,9 @@ interface Tab {
} }
const messages = defineMessages({ const messages = defineMessages({
allWorlds: { allInstances: {
id: 'servers.manage.world.all-worlds', id: 'servers.manage.instance.all-instances',
defaultMessage: 'All worlds', defaultMessage: 'All instances',
}, },
contentNav: { contentNav: {
id: 'servers.manage.nav.content', id: 'servers.manage.nav.content',
@@ -95,16 +95,16 @@ const messages = defineMessages({
defaultMessage: 'Backups', defaultMessage: 'Backups',
}, },
worldFallbackName: { worldFallbackName: {
id: 'servers.manage.world.fallback-name', id: 'servers.manage.instance.fallback-name',
defaultMessage: 'World', defaultMessage: 'Instance',
}, },
lastActive: { lastActive: {
id: 'servers.manage.world.last-active', id: 'servers.manage.instance.last-active',
defaultMessage: 'Last active {time}', defaultMessage: 'Last active {time}',
}, },
worldSettings: { instanceSettings: {
id: 'servers.manage.world.settings', id: 'servers.manage.instance.settings',
defaultMessage: 'World settings', defaultMessage: 'Instance settings',
}, },
}) })
@@ -121,9 +121,11 @@ const { data: serverFull } = useQuery({
staleTime: 30_000, staleTime: 30_000,
}) })
const worldsPath = computed(() => `/hosting/manage/${encodeURIComponent(serverId)}/worlds`) const instancesPath = computed(() => `/hosting/manage/${encodeURIComponent(serverId)}/instances`)
const worldPath = computed(() => const worldPath = computed(() =>
worldId.value ? `${worldsPath.value}/${encodeURIComponent(worldId.value)}` : worldsPath.value, worldId.value
? `${instancesPath.value}/${encodeURIComponent(worldId.value)}`
: instancesPath.value,
) )
const currentWorld = computed(() => { const currentWorld = computed(() => {
@@ -193,7 +195,7 @@ watch(
() => [serverFull.value, currentWorld.value, worldId.value] as const, () => [serverFull.value, currentWorld.value, worldId.value] as const,
([full, world, id]) => { ([full, world, id]) => {
if (full && id && !world) { if (full && id && !world) {
router.replace(worldsPath.value) router.replace(instancesPath.value)
} }
}, },
{ immediate: true }, { immediate: true },
@@ -6,12 +6,12 @@
> >
<div <div
v-for="slot in WORLD_SLOT_COUNT" v-for="slot in WORLD_SLOT_COUNT"
:key="`world-card-skeleton-${slot}`" :key="`instance-card-skeleton-${slot}`"
class="min-h-[19.75rem] animate-pulse rounded-2xl border border-solid border-surface-5 bg-bg-raised shadow-xl" class="min-h-[19.75rem] animate-pulse rounded-2xl border border-solid border-surface-5 bg-bg-raised shadow-xl"
/> />
</div> </div>
<div v-else class="grid grid-cols-[repeat(auto-fit,minmax(min(100%,20.25rem),1fr))] gap-6"> <div v-else class="grid grid-cols-[repeat(auto-fit,minmax(min(100%,20.25rem),1fr))] gap-6">
<WorldCard <InstanceCard
v-for="world in worldSlots" v-for="world in worldSlots"
:key="world.id" :key="world.id"
:world="world" :world="world"
@@ -29,7 +29,7 @@ import { useQuery } from '@tanstack/vue-query'
import { computed } from 'vue' import { computed } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import WorldCard from '#ui/components/servers/worlds/WorldCard.vue' import InstanceCard from '#ui/components/servers/instances/InstanceCard.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n' import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { import {
injectModrinthClient, injectModrinthClient,
@@ -39,9 +39,9 @@ import {
import { formatLoaderLabel } from '#ui/utils/loaders' import { formatLoaderLabel } from '#ui/utils/loaders'
const messages = defineMessages({ const messages = defineMessages({
worldSlotName: { instanceSlotName: {
id: 'servers.manage.worlds.slot-name', id: 'servers.manage.instances.slot-name',
defaultMessage: 'World #{index}', defaultMessage: 'Instance #{index}',
}, },
}) })
@@ -154,7 +154,7 @@ function padWorldSlots(slots: WorldSlot[]): WorldSlot[] {
padded.push({ padded.push({
type: 'empty', type: 'empty',
id: `empty-world-slot-${i + 1}`, id: `empty-world-slot-${i + 1}`,
name: formatMessage(messages.worldSlotName, { index: i + 1 }), name: formatMessage(messages.instanceSlotName, { index: i + 1 }),
}) })
} }
return padded return padded
@@ -268,14 +268,14 @@ function createDummyWorldSlots(): WorldSlot[] {
{ {
type: 'empty', type: 'empty',
id: 'empty-world-slot-3', id: 'empty-world-slot-3',
name: formatMessage(messages.worldSlotName, { index: 3 }), name: formatMessage(messages.instanceSlotName, { index: 3 }),
}, },
] ]
} }
function handleEditWorld(worldId: string) { function handleEditWorld(worldId: string) {
router.push( router.push(
`/hosting/manage/${encodeURIComponent(serverId)}/worlds/${encodeURIComponent(worldId)}`, `/hosting/manage/${encodeURIComponent(serverId)}/instances/${encodeURIComponent(worldId)}`,
) )
} }
@@ -146,14 +146,14 @@ const messages = defineMessages({
defaultMessage: defaultMessage:
'Pick your favorite modpack from Modrinth, or choose a loader and add the mods you want.', 'Pick your favorite modpack from Modrinth, or choose a loader and add the mods you want.',
}, },
configureWorldTitle: { configureInstanceTitle: {
id: 'servers.setup.onboarding.step.configure-world.title', id: 'servers.setup.onboarding.step.configure-instance.title',
defaultMessage: 'Configure your world', defaultMessage: 'Configure your instance',
}, },
configureWorldDescription: { configureInstanceDescription: {
id: 'servers.setup.onboarding.step.configure-world.description', id: 'servers.setup.onboarding.step.configure-instance.description',
defaultMessage: defaultMessage:
'Set up your world just like singleplayer. Choose your gamemode and world seed.', 'Set up your instance just like singleplayer. Choose your gamemode and world seed.',
}, },
inviteFriendsTitle: { inviteFriendsTitle: {
id: 'servers.setup.onboarding.step.invite-friends.title', id: 'servers.setup.onboarding.step.invite-friends.title',
@@ -274,8 +274,8 @@ async function finalizeSetup() {
}) })
await router.push( await router.push(
worldId.value worldId.value
? `/hosting/manage/${encodeURIComponent(serverId)}/worlds/${encodeURIComponent(worldId.value)}` ? `/hosting/manage/${encodeURIComponent(serverId)}/instances/${encodeURIComponent(worldId.value)}`
: `/hosting/manage/${encodeURIComponent(serverId)}/worlds`, : `/hosting/manage/${encodeURIComponent(serverId)}/instances`,
) )
} }
@@ -375,8 +375,8 @@ const steps = computed(() => [
}, },
{ {
icon: GlobeIcon, icon: GlobeIcon,
title: formatMessage(messages.configureWorldTitle), title: formatMessage(messages.configureInstanceTitle),
description: formatMessage(messages.configureWorldDescription), description: formatMessage(messages.configureInstanceDescription),
}, },
{ {
icon: UsersIcon, icon: UsersIcon,
+5 -5
View File
@@ -2,9 +2,9 @@ export { default as ServersManageAccessPage } from './hosting/manage/[id]/access
export { default as ServersManageRootLayout } from './hosting/manage/[id]/index.vue' export { default as ServersManageRootLayout } from './hosting/manage/[id]/index.vue'
export { default as ServerOnboardingPanelPage } from './hosting/manage/[id]/onboarding.vue' export { default as ServerOnboardingPanelPage } from './hosting/manage/[id]/onboarding.vue'
export { default as ServersManageOverviewPage } from './hosting/manage/[id]/overview.vue' export { default as ServersManageOverviewPage } from './hosting/manage/[id]/overview.vue'
export { default as ServersManageBackupsPage } from './hosting/manage/[id]/worlds/[world-id]/backups.vue' export { default as ServersManageBackupsPage } from './hosting/manage/[id]/instances/[instance-id]/backups.vue'
export { default as ServersManageContentPage } from './hosting/manage/[id]/worlds/[world-id]/content.vue' export { default as ServersManageContentPage } from './hosting/manage/[id]/instances/[instance-id]/content.vue'
export { default as ServersManageFilesPage } from './hosting/manage/[id]/worlds/[world-id]/files.vue' export { default as ServersManageFilesPage } from './hosting/manage/[id]/instances/[instance-id]/files.vue'
export { default as ServersManageWorldRootLayout } from './hosting/manage/[id]/worlds/[world-id]/index.vue' export { default as ServersManageInstanceRootLayout } from './hosting/manage/[id]/instances/[instance-id]/index.vue'
export { default as ServersManageWorldsPage } from './hosting/manage/[id]/worlds/index.vue' export { default as ServersManageInstancesPage } from './hosting/manage/[id]/instances/index.vue'
export { default as ServersManagePageIndex } from './hosting/manage/index.vue' export { default as ServersManagePageIndex } from './hosting/manage/index.vue'
+29 -29
View File
@@ -4670,8 +4670,8 @@
"servers.manage.nav.overview": { "servers.manage.nav.overview": {
"defaultMessage": "Overview" "defaultMessage": "Overview"
}, },
"servers.manage.nav.worlds": { "servers.manage.nav.instances": {
"defaultMessage": "Worlds" "defaultMessage": "Instances"
}, },
"servers.manage.new-server-button": { "servers.manage.new-server-button": {
"defaultMessage": "New server" "defaultMessage": "New server"
@@ -4766,50 +4766,50 @@
"servers.manage.websocket.reconnecting": { "servers.manage.websocket.reconnecting": {
"defaultMessage": "Hang on, we're reconnecting to your server." "defaultMessage": "Hang on, we're reconnecting to your server."
}, },
"servers.manage.world.all-worlds": { "servers.manage.instance.all-instances": {
"defaultMessage": "All worlds" "defaultMessage": "All instances"
}, },
"servers.manage.world.fallback-name": { "servers.manage.instance.fallback-name": {
"defaultMessage": "World" "defaultMessage": "Instance"
}, },
"servers.manage.world.last-active": { "servers.manage.instance.last-active": {
"defaultMessage": "Last active {time}" "defaultMessage": "Last active {time}"
}, },
"servers.manage.world.settings": { "servers.manage.instance.settings": {
"defaultMessage": "World settings" "defaultMessage": "Instance settings"
}, },
"servers.manage.worlds.card.active": { "servers.manage.instances.card.active": {
"defaultMessage": "Active" "defaultMessage": "Active"
}, },
"servers.manage.worlds.card.create": { "servers.manage.instances.card.create": {
"defaultMessage": "Create world" "defaultMessage": "Create instance"
}, },
"servers.manage.worlds.card.created": { "servers.manage.instances.card.created": {
"defaultMessage": "Created" "defaultMessage": "Created"
}, },
"servers.manage.worlds.card.edit": { "servers.manage.instances.card.edit": {
"defaultMessage": "Edit world" "defaultMessage": "Edit instance"
}, },
"servers.manage.worlds.card.empty-description": { "servers.manage.instances.card.empty-description": {
"defaultMessage": "New world instance" "defaultMessage": "New instance"
}, },
"servers.manage.worlds.card.installed-content": { "servers.manage.instances.card.installed-content": {
"defaultMessage": "Installed content" "defaultMessage": "Installed content"
}, },
"servers.manage.worlds.card.last-active": { "servers.manage.instances.card.last-active": {
"defaultMessage": "Last active" "defaultMessage": "Last active"
}, },
"servers.manage.worlds.card.none": { "servers.manage.instances.card.none": {
"defaultMessage": "None" "defaultMessage": "None"
}, },
"servers.manage.worlds.card.not-tracked-yet": { "servers.manage.instances.card.not-tracked-yet": {
"defaultMessage": "Not tracked yet" "defaultMessage": "Not tracked yet"
}, },
"servers.manage.worlds.card.settings": { "servers.manage.instances.card.settings": {
"defaultMessage": "World settings" "defaultMessage": "Instance settings"
}, },
"servers.manage.worlds.slot-name": { "servers.manage.instances.slot-name": {
"defaultMessage": "World #{index}" "defaultMessage": "Instance #{index}"
}, },
"servers.manage.your-servers-title": { "servers.manage.your-servers-title": {
"defaultMessage": "Your servers" "defaultMessage": "Your servers"
@@ -5042,11 +5042,11 @@
"servers.setup.onboarding.step.choose.title": { "servers.setup.onboarding.step.choose.title": {
"defaultMessage": "Choose what to play" "defaultMessage": "Choose what to play"
}, },
"servers.setup.onboarding.step.configure-world.description": { "servers.setup.onboarding.step.configure-instance.description": {
"defaultMessage": "Set up your world just like singleplayer. Choose your gamemode and world seed." "defaultMessage": "Set up your instance just like singleplayer. Choose your gamemode and world seed."
}, },
"servers.setup.onboarding.step.configure-world.title": { "servers.setup.onboarding.step.configure-instance.title": {
"defaultMessage": "Configure your world" "defaultMessage": "Configure your instance"
}, },
"servers.setup.onboarding.step.invite-friends.description": { "servers.setup.onboarding.step.invite-friends.description": {
"defaultMessage": "Share your server with friends by copying the address and letting them know which mods they'll need to join." "defaultMessage": "Share your server with friends by copying the address and letting them know which mods they'll need to join."
@@ -0,0 +1,53 @@
import type { Meta, StoryObj } from '@storybook/vue3-vite'
import InstanceCard from '../../components/servers/instances/InstanceCard.vue'
const meta = {
title: 'Servers/InstanceCard',
component: InstanceCard,
parameters: {
layout: 'padded',
},
render: (args) => ({
components: { InstanceCard },
setup() {
return { args }
},
template: '<div style="max-width: 360px"><InstanceCard v-bind="args" /></div>',
}),
} satisfies Meta<typeof InstanceCard>
export default meta
type Story = StoryObj<typeof meta>
export const Active: Story = {
args: {
world: {
type: 'world',
id: 'demo-world',
name: 'Cobbletown',
active: true,
gameVersion: '1.20.4',
loaderLabel: 'Fabric 0.16.6',
linkedModpack: {
name: 'Cobblemon Official',
iconUrl: null,
link: null,
},
installedContentCount: 47,
lastActiveAt: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),
createdAt: new Date(Date.now() - 197 * 24 * 60 * 60 * 1000).toISOString(),
},
},
}
export const Empty: Story = {
args: {
world: {
type: 'empty',
id: 'empty-instance-slot',
name: 'Instance #2',
},
},
}
@@ -25,7 +25,7 @@ const meta = {
setup() { setup() {
const router = useRouter() const router = useRouter()
onMounted(() => { onMounted(() => {
router.replace('/hosting/manage/demo-server/worlds/demo-world') router.replace('/hosting/manage/demo-server/instances/demo-world')
}) })
const server = ref({ const server = ref({