mirror of
https://github.com/modrinth/code.git
synced 2026-08-30 19:46:33 +00:00
implement proper provisioning state for resubscribe
This commit is contained in:
@@ -80,7 +80,7 @@
|
||||
|
||||
<div v-if="noticeType" class="server-listing-notice">
|
||||
<div v-if="noticeType === 'provisioning'" class="flex gap-2">
|
||||
Please wait while we set up your server. This should only take a minute.
|
||||
Please wait while we set up your server. This can take up to 10 minutes.
|
||||
</div>
|
||||
<div v-else-if="noticeType === 'upgrading'" class="flex gap-2">
|
||||
Your server's hardware is currently being upgraded and will be back online shortly.
|
||||
@@ -234,6 +234,7 @@ type ServerListingProps = {
|
||||
current?: number
|
||||
max?: number
|
||||
}
|
||||
isProvisioning?: boolean
|
||||
cancellationDate?: string | Date | null
|
||||
onResubscribe?: (() => void) | null
|
||||
onDownloadBackup?: (() => void) | null
|
||||
@@ -244,11 +245,10 @@ const props = defineProps<ServerListingProps>()
|
||||
const { kyros, labrinth } = injectModrinthClient()
|
||||
|
||||
const isConfiguring = computed(() => props.flows?.intro)
|
||||
const isProvisioning = computed(() => props.status === 'installing' && !isConfiguring.value)
|
||||
const isUpgrading = computed(
|
||||
() => props.status === 'suspended' && props.suspension_reason === 'upgrading',
|
||||
)
|
||||
const isDisabled = computed(() => props.status === 'suspended' || isProvisioning.value)
|
||||
const isDisabled = computed(() => props.status === 'suspended' || props.isProvisioning)
|
||||
const isSetToCancel = computed(() => !!props.cancellationDate && props.status !== 'suspended')
|
||||
const filesRemainingDays = computed(() => {
|
||||
if (!props.cancellationDate) return 0
|
||||
@@ -260,7 +260,7 @@ const filesRemainingDays = computed(() => {
|
||||
const isFilesExpired = computed(() => filesRemainingDays.value <= 0)
|
||||
|
||||
const hasIconOverlay = computed(
|
||||
() => isProvisioning.value || isUpgrading.value || props.status === 'suspended',
|
||||
() => props.isProvisioning || isUpgrading.value || props.status === 'suspended',
|
||||
)
|
||||
|
||||
type NoticeType =
|
||||
@@ -273,7 +273,7 @@ type NoticeType =
|
||||
| 'setToCancel'
|
||||
|
||||
const noticeType = computed<NoticeType | null>(() => {
|
||||
if (isProvisioning.value) return 'provisioning'
|
||||
if (props.isProvisioning) return 'provisioning'
|
||||
if (props.status === 'suspended') {
|
||||
switch (props.suspension_reason) {
|
||||
case 'upgrading':
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
:key="server.server_id"
|
||||
v-bind="server"
|
||||
:cancellation-date="serverBillingMap.get(server.server_id)?.cancellationDate"
|
||||
:is-provisioning="serverBillingMap.get(server.server_id)?.isProvisioning"
|
||||
:on-resubscribe="serverBillingMap.get(server.server_id)?.onResubscribe"
|
||||
:on-download-backup="serverBillingMap.get(server.server_id)?.onDownloadBackup"
|
||||
/>
|
||||
@@ -208,6 +209,7 @@ import {
|
||||
} from '@modrinth/ui'
|
||||
import type { ModrinthServersFetchError } from '@modrinth/utils'
|
||||
import { useQuery, useQueryClient } from '@tanstack/vue-query'
|
||||
import { useIntervalFn } from '@vueuse/core'
|
||||
import dayjs from 'dayjs'
|
||||
import Fuse from 'fuse.js'
|
||||
import type Stripe from 'stripe'
|
||||
@@ -539,6 +541,41 @@ const { data: charges } = useQuery({
|
||||
queryFn: () => client.labrinth.billing_internal.getPayments(),
|
||||
})
|
||||
|
||||
const CHARGE_POLL_INTERVAL_MS = 20_000
|
||||
|
||||
const hasProvisioningSubscription = computed(() => {
|
||||
if (!subscriptions.value || !charges.value) return false
|
||||
return subscriptions.value
|
||||
.filter((s) => s?.metadata?.type === 'pyro')
|
||||
.some((sub) => {
|
||||
if (sub.status !== 'unprovisioned') return false
|
||||
const charge = charges.value?.find((c) => c.subscription_id === sub.id)
|
||||
return charge?.status === 'processing' || charge?.status === 'open'
|
||||
})
|
||||
})
|
||||
|
||||
const { pause: pauseChargePoll, resume: resumeChargePoll } = useIntervalFn(
|
||||
() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['billing', 'payments'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['billing', 'subscriptions'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['servers'] })
|
||||
},
|
||||
CHARGE_POLL_INTERVAL_MS,
|
||||
{ immediate: false },
|
||||
)
|
||||
|
||||
watch(
|
||||
hasProvisioningSubscription,
|
||||
(isProvisioning) => {
|
||||
if (isProvisioning) {
|
||||
resumeChargePoll()
|
||||
} else {
|
||||
pauseChargePoll()
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
const { data: serverFullList } = useQuery({
|
||||
queryKey: ['servers', 'v1'],
|
||||
queryFn: () => client.archon.servers_v1.list(),
|
||||
@@ -546,6 +583,7 @@ const { data: serverFullList } = useQuery({
|
||||
|
||||
type ServerBillingInfo = {
|
||||
cancellationDate?: string | null
|
||||
isProvisioning?: boolean
|
||||
onResubscribe?: () => void
|
||||
onDownloadBackup?: (() => void) | null
|
||||
}
|
||||
@@ -598,7 +636,10 @@ function getLatestBackupDownload(serverId: string): (() => void) | null {
|
||||
function getProductFromPriceId(priceId: string | null | undefined) {
|
||||
if (!priceId) return null
|
||||
|
||||
return pyroProducts.value.find((product) => product.prices.some((price) => price.id === priceId)) ?? null
|
||||
return (
|
||||
pyroProducts.value.find((product) => product.prices.some((price) => price.id === priceId)) ??
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
function getPlanName(product: Labrinth.Billing.Internal.Product | null): string {
|
||||
@@ -673,7 +714,8 @@ function openResubscribeModal(
|
||||
resubscribeModal.value?.show({
|
||||
subscriptionId: subscription.id,
|
||||
wasSuspended: !!charge?.due && dayjs(charge.due).isBefore(dayjs()),
|
||||
serverName: serverList.value.find((server) => server.server_id === serverId)?.name ?? 'this server',
|
||||
serverName:
|
||||
serverList.value.find((server) => server.server_id === serverId)?.name ?? 'this server',
|
||||
planName: getPlanName(product),
|
||||
ramGb: getRamGb(product),
|
||||
storageGb: getStorageGb(product),
|
||||
@@ -697,7 +739,7 @@ async function handleResubscribeConfirm({ subscriptionId, wasSuspended }: Resubs
|
||||
if (wasSuspended) {
|
||||
addNotification({
|
||||
title: 'Resubscription request submitted',
|
||||
text: 'If the server is currently suspended, it may take up to 10 minutes for another charge attempt to be made.',
|
||||
text: 'If the server is currently cancelled, it may take up to 10 minutes for another charge attempt to be made.',
|
||||
type: 'success',
|
||||
})
|
||||
} else {
|
||||
@@ -729,7 +771,11 @@ const serverBillingMap = computed(() => {
|
||||
(c) => c.subscription_id === sub.id && c.status !== 'succeeded',
|
||||
)
|
||||
|
||||
const info: ServerBillingInfo = {}
|
||||
const info: ServerBillingInfo = {
|
||||
isProvisioning:
|
||||
sub.status === 'unprovisioned' &&
|
||||
(charge?.status === 'processing' || charge?.status === 'open'),
|
||||
}
|
||||
|
||||
info.onDownloadBackup = getLatestBackupDownload(serverId)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user