hook up on download button

This commit is contained in:
tdgao
2026-03-20 11:52:38 -06:00
parent 0a05061bf7
commit 672757c295
4 changed files with 131 additions and 18 deletions
@@ -93,14 +93,15 @@
class="server-listing-notice"
>
<div>
Your subscription was cancelled
<template v-if="cancellationDate">
Your subscription was cancelled<template v-if="cancellationDate">
on
<span class="font-medium text-contrast">
{{ formatDate(cancellationDate) }}
</span> </template
>. Your files will be kept for <span class="font-medium text-red">30 days</span> and can be
downloaded below before they're deleted.
</span></template
>.<template v-if="!isFilesExpired">
Your files will be kept for <span class="font-medium text-red">30 days</span> and can be
downloaded below before they're deleted.</template
>
</div>
<div class="flex gap-2">
<ButtonStyled v-if="onDownloadBackup" type="outlined" circular>
@@ -194,16 +195,26 @@
class="server-listing-notice"
>
<div>
Your subscription is set to cancel
<template v-if="cancellationDate">
Your subscription is set to cancel<template v-if="cancellationDate">
on
<span class="font-medium text-contrast">
{{ formatDate(cancellationDate) }}
</span> </template
>. Your files will be preserved for <span class="font-medium text-red">30 days</span> after
cancellation.
</span></template
>.<template v-if="!isFilesExpired">
Your files will be preserved for
<span class="font-medium text-red">30 days</span> after cancellation.</template
>
</div>
<div class="flex gap-2">
<ButtonStyled v-if="onDownloadBackup" type="outlined" circular>
<button
class="!border-surface-5"
v-tooltip="'Download latest backup'"
@click="onDownloadBackup"
>
<DownloadIcon />
</button>
</ButtonStyled>
<ButtonStyled type="outlined">
<button
class="!border-surface-5 w-28"
@@ -312,6 +323,12 @@ const isConfiguring = computed(() => props.flows?.intro)
const isProvisioning = computed(() => props.status === 'installing' && !isConfiguring.value)
const isDisabled = computed(() => props.status === 'suspended' || isProvisioning.value)
const isSetToCancel = computed(() => !!props.cancellationDate && props.status !== 'suspended')
const isFilesExpired = computed(() => {
if (!props.cancellationDate) return false
const cancellation = new Date(props.cancellationDate)
const thirtyDaysLater = new Date(cancellation.getTime() + 30 * 24 * 60 * 60 * 1000)
return new Date() > thirtyDaysLater
})
const hasNotice = computed(
() =>
isProvisioning.value ||
@@ -410,6 +427,6 @@ async function copyToClipboard(text: string) {
<style scoped>
.server-listing-notice {
@apply relative flex w-full rounded-b-2xl border-[1px] border-solid p-4 flex-col gap-2 border-surface-5 bg-bg-raised text-primary;
@apply relative flex w-full rounded-b-2xl border-[1px] border-solid p-4 flex-col gap-4 border-surface-5 bg-bg-raised text-primary;
}
</style>
@@ -331,10 +331,55 @@ const { data: charges } = useQuery({
queryFn: () => client.labrinth.billing_internal.getPayments(),
})
const { data: serverFullList } = useQuery({
queryKey: ['servers', 'v1'],
queryFn: () => client.archon.servers_v1.list(),
})
type ServerBillingInfo = {
cancellationDate?: string | null
onResubscribe?: () => void
onDownloadBackup?: () => void
onDownloadBackup?: (() => void) | null
}
function getLatestBackupDownload(serverId: string): (() => void) | null {
const serverFull = serverFullList.value?.find((s) => s.id === serverId)
if (!serverFull) return null
const activeWorld = serverFull.worlds.find((w) => w.is_active) ?? serverFull.worlds[0]
if (!activeWorld?.backups?.length) return null
const latestBackup = activeWorld.backups
.filter((b) => b.status === 'done')
.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0]
if (!latestBackup) return null
return async () => {
try {
const server = await client.archon.servers_v0.get(serverId)
const kyrosUrl = server.node?.instance
const jwt = server.node?.token
if (!kyrosUrl || !jwt) {
addNotification({
title: 'Download unavailable',
text: 'Server connection info is not available. Please contact support.',
type: 'error',
})
return
}
window.open(
`https://${kyrosUrl}/modrinth/v0/backups/${latestBackup.id}/download?auth=${jwt}`,
'_blank',
)
} catch {
addNotification({
title: 'Download failed',
text: 'An error occurred while trying to download the backup.',
type: 'error',
})
}
}
}
const serverBillingMap = computed(() => {
@@ -352,6 +397,8 @@ const serverBillingMap = computed(() => {
const info: ServerBillingInfo = {}
info.onDownloadBackup = getLatestBackupDownload(serverId)
if (charge?.status === 'cancelled') {
info.cancellationDate = charge.due
@@ -90,16 +90,17 @@ export const SetToCancel: Story = {
args: {
...baseServer,
name: 'Survival SMP',
cancellationDate: new Date(2025, 1, 17).toISOString(),
cancellationDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
onResubscribe: () => alert('Resubscribe clicked'),
onDownloadBackup: () => alert('Download backup clicked'),
},
}
export const SetToCancelWithResubscribe: Story = {
export const SetToCancelFilesExpired: Story = {
args: {
...baseServer,
name: 'Survival SMP',
cancellationDate: new Date(2025, 1, 17).toISOString(),
onResubscribe: () => alert('Resubscribe clicked'),
},
}
@@ -109,19 +110,21 @@ export const SuspendedCancelled: Story = {
name: 'Old Event Server',
status: 'suspended',
suspension_reason: 'cancelled',
cancellationDate: new Date(2025, 1, 17).toISOString(),
cancellationDate: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),
onResubscribe: () => alert('Resubscribe clicked'),
onDownloadBackup: () => alert('Download backup clicked'),
},
}
export const SuspendedCancelledWithActions: Story = {
export const SuspendedCancelledFilesExpired: Story = {
args: {
...baseServer,
onDownloadBackup: null,
name: 'Old Event Server',
status: 'suspended',
suspension_reason: 'cancelled',
cancellationDate: new Date(2025, 1, 17).toISOString(),
onResubscribe: () => alert('Resubscribe clicked'),
onDownloadBackup: () => alert('Download backup clicked'),
},
}