Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"files.insertFinalNewline": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "always"
"source.organizeImports": "never"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[vue]": {
Expand Down
33 changes: 33 additions & 0 deletions apps/app-frontend/src/pages/hosting/manage/Access.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script setup lang="ts">
import {
injectModrinthClient,
injectModrinthServerContext,
ServersManageAccessPage,
} from '@modrinth/ui'
import { useQueryClient } from '@tanstack/vue-query'

const client = injectModrinthClient()
const { serverId } = injectModrinthServerContext()
const queryClient = useQueryClient()

try {
await Promise.all([
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,
}),
])
} catch {
// Let mounted layouts' useQuery surface errors; do not fail route setup.
}
</script>

<template>
<ServersManageAccessPage />
</template>
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
@@ -1,7 +1,8 @@
import Access from './Access.vue'
import Backups from './Backups.vue'
import Content from './Content.vue'
import Files from './Files.vue'
import Index from './Index.vue'
import Overview from './Overview.vue'

export { Backups, Content, Files, Index, Overview }
export { Access, Backups, Content, Files, Index, Overview }
8 changes: 8 additions & 0 deletions apps/app-frontend/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ export default new createRouter({
breadcrumb: [{ name: '?Server' }],
},
},
{
path: 'access',
name: 'ServerManageAccess',
component: Hosting.Access,
meta: {
breadcrumb: [{ name: '?Server' }],
},
},
],
},
{
Expand Down
1 change: 0 additions & 1 deletion apps/frontend/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,3 @@ These composables are deprecated and should not be used in new code:

- **`useAsyncData`** - we use tanstack, not nuxt's built in async data utility.
- **`useBaseFetch`** (`src/composables/fetch.js`) — legacy Labrinth fetch wrapper. Use `client.labrinth.*` modules instead.
- **`useServersFetch`** (`src/composables/servers/servers-fetch.ts`) — legacy Archon fetch wrapper with manual retry/circuit-breaker. Use `client.archon.*` modules instead — refer to the `packages/api-client/CLAUDE.md` for more information.
54 changes: 24 additions & 30 deletions apps/frontend/src/components/ui/admin/AssignNoticeModal.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<script setup lang="ts">
import type { Archon } from '@modrinth/api-client'
import { PlusIcon, XIcon } from '@modrinth/assets'
import {
Accordion,
ButtonStyled,
injectModrinthClient,
injectNotificationManager,
NewModal,
ServerNotice,
StyledInput,
TagItem,
} from '@modrinth/ui'
import type { ServerNotice as ServerNoticeType } from '@modrinth/utils'
import { ref } from 'vue'

import { useServersFetch } from '~/composables/servers/servers-fetch.ts'

const { addNotification } = injectNotificationManager()
const client = injectModrinthClient()

type ServerNoticeType = Archon.Notices.v0.ListedNotice

const modal = ref<InstanceType<typeof NewModal>>()

Expand All @@ -32,28 +34,23 @@ const assignedNodes = computed(() => assigned.value.filter((n) => n.kind === 'no
const inputField = ref('')

async function refresh() {
await useServersFetch('notices').then((res) => {
const notices = res as ServerNoticeType[]
assigned.value = notices.find((n) => n.id === notice.value?.id)?.assigned ?? []
})
const notices = await client.archon.notices_v0.list()
assigned.value = notices.find((n) => n.id === notice.value?.id)?.assigned ?? []
}

async function assign(server: boolean = true) {
const input = inputField.value.trim()

if (input !== '' && notice.value) {
await useServersFetch(
`notices/${notice.value.id}/assign?${server ? 'server' : 'node'}=${input}`,
{
method: 'PUT',
},
).catch((err) => {
addNotification({
title: 'Error assigning notice',
text: err,
type: 'error',
await client.archon.notices_v0
.assign(notice.value.id, server ? { server: input } : { node: input })
.catch((err) => {
addNotification({
title: 'Error assigning notice',
text: err,
type: 'error',
})
})
})
} else {
addNotification({
title: 'Error assigning notice',
Expand Down Expand Up @@ -84,18 +81,15 @@ async function unassignDetect() {

async function unassign(id: string, server: boolean = true) {
if (notice.value) {
await useServersFetch(
`notices/${notice.value.id}/unassign?${server ? 'server' : 'node'}=${id}`,
{
method: 'PUT',
},
).catch((err) => {
addNotification({
title: 'Error unassigning notice',
text: err,
type: 'error',
await client.archon.notices_v0
.unassign(notice.value.id, server ? { server: id } : { node: id })
.catch((err) => {
addNotification({
title: 'Error unassigning notice',
text: err,
type: 'error',
})
})
})
}
await refresh()
}
Expand Down Expand Up @@ -125,7 +119,7 @@ defineExpose({ show, hide })
:level="notice.level"
:message="notice.message"
:dismissable="notice.dismissable"
:title="notice.title"
:title="notice.title ?? undefined"
preview
/>
<div class="flex flex-col gap-2">
Expand Down
9 changes: 5 additions & 4 deletions apps/frontend/src/components/ui/admin/BatchCreditModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ import { CheckIcon, PlusIcon, XIcon } from '@modrinth/assets'
import {
ButtonStyled,
Combobox,
injectModrinthClient,
injectNotificationManager,
NewModal,
StyledInput,
Expand All @@ -143,9 +144,9 @@ import { DEFAULT_CREDIT_EMAIL_MESSAGE } from '@modrinth/utils/utils.ts'
import { computed, ref } from 'vue'

import { useBaseFetch } from '#imports'
import { useServersFetch } from '~/composables/servers/servers-fetch.ts'

const { addNotification } = injectNotificationManager()
const client = injectModrinthClient()

const modal = ref<InstanceType<typeof NewModal>>()

Expand Down Expand Up @@ -205,12 +206,12 @@ const applyDisabled = computed(() => {
async function ensureOverview() {
if (regions.value.length || nodeHostnames.value.length) return
try {
const data = await useServersFetch<any>('/nodes/overview', { version: 'internal' })
regions.value = (data.regions || []).map((r: any) => ({
const data = await client.archon.nodes_internal.overview()
regions.value = data.regions.map((r) => ({
value: r.key,
label: `${r.display_name} (${r.key})`,
}))
nodeHostnames.value = data.node_hostnames || []
nodeHostnames.value = data.node_hostnames
if (!selectedRegion.value && regions.value.length) selectedRegion.value = regions.value[0].value
} catch (err) {
addNotification({ title: 'Failed to load nodes overview', text: String(err), type: 'error' })
Expand Down
46 changes: 19 additions & 27 deletions apps/frontend/src/components/ui/admin/TransferModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ import {
ButtonStyled,
Chips,
Combobox,
injectModrinthClient,
injectNotificationManager,
NewModal,
StyledInput,
Expand All @@ -207,13 +208,12 @@ import {
import dayjs from 'dayjs'
import { computed, ref } from 'vue'

import { useServersFetch } from '~/composables/servers/servers-fetch.ts'

const emit = defineEmits<{
success: []
}>()

const { addNotification } = injectNotificationManager()
const client = injectModrinthClient()

const modal = ref<InstanceType<typeof NewModal>>()

Expand Down Expand Up @@ -341,12 +341,12 @@ const submitDisabled = computed(() => {
async function ensureOverview() {
if (regions.value.length || nodeHostnames.value.length) return
try {
const data = await useServersFetch<any>('/nodes/overview', { version: 'internal' })
regions.value = (data.regions || []).map((r: any) => ({
const data = await client.archon.nodes_internal.overview()
regions.value = data.regions.map((r) => ({
value: r.key,
label: `${r.display_name} (${r.key})`,
}))
nodeHostnames.value = data.node_hostnames || []
nodeHostnames.value = data.node_hostnames
if (!selectedRegion.value && regions.value.length) {
selectedRegion.value = regions.value[0].value
}
Expand All @@ -364,30 +364,22 @@ async function submit() {
scheduleOption.value === 'now' ? undefined : dayjs(scheduledDate.value).toISOString()

if (mode.value === 'servers') {
await useServersFetch('/transfers/schedule/servers', {
version: 'internal',
method: 'POST',
body: {
server_ids: parsedServerIds.value,
scheduled_at: scheduledAt,
target_region: selectedRegion.value || undefined,
node_tags: selectedTags.value.length > 0 ? selectedTags.value : undefined,
reason: reason.value.trim(),
},
await client.archon.transfers_internal.scheduleServers({
server_ids: parsedServerIds.value,
scheduled_at: scheduledAt,
target_region: selectedRegion.value || undefined,
node_tags: selectedTags.value.length > 0 ? selectedTags.value : undefined,
reason: reason.value.trim(),
})
} else {
await useServersFetch('/transfers/schedule/nodes', {
version: 'internal',
method: 'POST',
body: {
node_hostnames: selectedNodes.value.slice(),
scheduled_at: scheduledAt,
target_region: selectedRegion.value || undefined,
node_tags: selectedTags.value.length > 0 ? selectedTags.value : undefined,
reason: reason.value.trim(),
cordon_nodes: cordonNodes.value,
tag_nodes: tagNodes.value.trim() || undefined,
},
await client.archon.transfers_internal.scheduleNodes({
node_hostnames: selectedNodes.value.slice(),
scheduled_at: scheduledAt,
target_region: selectedRegion.value || undefined,
node_tags: selectedTags.value.length > 0 ? selectedTags.value : undefined,
reason: reason.value.trim(),
cordon_nodes: cordonNodes.value,
tag_nodes: tagNodes.value.trim() || undefined,
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@
>{{ isIncome ? '' : '-' }}{{ formatMoney(transaction.amount) }}</span
>
<template v-if="transaction.type === 'withdrawal' && transaction.status === 'in-transit'">
<Tooltip theme="dismissable-prompt" :triggers="['hover', 'focus']" no-auto-focus>
<Tooltip
theme="dismissable-prompt"
class="inline-flex shrink-0"
:triggers="['hover', 'focus']"
no-auto-focus
>
<span class="my-auto align-middle"
><ButtonStyled circular type="outlined" size="small">
<button class="align-middle" @click="cancelPayout">
Expand Down
1 change: 1 addition & 0 deletions apps/frontend/src/composables/featureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const DEFAULT_FEATURE_FLAGS = validateValues({
showDiscoverProjectButtons: false,
useV1ContentTabAPI: true,
labrinthApiCanary: false,
archonApiStaging: false,
dismissedExternalProjectsInfo: false,
modpackPermissionsPage: false,
showAllBanners: false,
Expand Down
Loading
Loading