1
1
<template >
2
- <NuxtLink
3
- class =" contents"
4
- :to =" status === 'suspended' ? '' : `/servers/manage/${props.server_id}`"
5
- >
6
- <div
7
- v-tooltip ="
8
- status === 'suspended'
9
- ? suspension_reason === 'upgrading'
10
- ? 'This server is being transferred to a new node. It will be unavailable until this process finishes.'
11
- : 'This server has been suspended. Please visit your billing settings or contact Modrinth Support for more information.'
12
- : ''
13
- "
14
- class =" flex cursor-pointer flex-row items-center overflow-x-hidden rounded-3xl bg-bg-raised p-4 transition-transform duration-100"
15
- :class =" status === 'suspended' ? '!rounded-b-none opacity-75' : 'active:scale-95'"
16
- data-pyro-server-listing
17
- :data-pyro-server-listing-id =" server_id"
18
- >
19
- <ServerIcon v-if =" status !== 'suspended'" :image =" image" />
2
+ <div >
3
+ <NuxtLink :to =" status === 'suspended' ? '' : `/servers/manage/${props.server_id}`" >
20
4
<div
21
- v-else
22
- class =" bg-bg-secondary flex size-24 items-center justify-center rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm"
5
+ class =" flex flex-row items-center overflow-x-hidden rounded-2xl border-[1px] border-solid border-button-bg bg-bg-raised p-4 transition-transform duration-100"
6
+ :class =" {
7
+ '!rounded-b-none border-b-0': status === 'suspended' || !!pendingChange,
8
+ 'opacity-75': status === 'suspended',
9
+ 'active:scale-95': status !== 'suspended' && !pendingChange,
10
+ }"
11
+ data-pyro-server-listing
12
+ :data-pyro-server-listing-id =" server_id"
23
13
>
24
- <LockIcon class =" size-20 text-secondary" />
25
- </div >
26
- <div class =" ml-8 flex flex-col gap-2.5" >
27
- <div class =" flex flex-row items-center gap-2" >
28
- <h2 class =" m-0 text-xl font-bold text-contrast" >{{ name }}</h2 >
29
- <ChevronRightIcon />
30
- </div >
31
-
14
+ <ServerIcon v-if =" status !== 'suspended'" :image =" image" />
32
15
<div
33
- v-if = " projectData?.title "
34
- class =" m-0 flex flex-row items-center gap-2 text-sm font-medium text-secondary "
16
+ v-else
17
+ class =" bg-bg-secondary flex size-16 items-center justify-center rounded-xl border-[1px] border-solid border-button-border bg-button-bg shadow-sm "
35
18
>
36
- <Avatar
37
- :src =" iconUrl"
38
- no-shadow
39
- style =" min-height : 20px ; min-width : 20px ; height : 20px ; width : 20px "
40
- alt =" Server Icon"
41
- />
42
- Using {{ projectData?.title || 'Unknown' }}
19
+ <LockIcon class =" size-12 text-secondary" />
43
20
</div >
44
- <div v-else class =" min-h-[20px]" ></div >
21
+ <div class =" ml-4 flex flex-col gap-2.5" >
22
+ <div class =" flex flex-row items-center gap-2" >
23
+ <h2 class =" m-0 text-xl font-bold text-contrast" >{{ name }}</h2 >
24
+ <ChevronRightIcon />
25
+ </div >
45
26
46
- <div
47
- v-if =" isConfiguring"
48
- class =" flex min-w-0 items-center gap-2 truncate text-sm font-semibold text-brand"
49
- >
50
- <SparklesIcon class =" size-5 shrink-0" /> New server
27
+ <div
28
+ v-if =" projectData?.title"
29
+ class =" m-0 flex flex-row items-center gap-2 text-sm font-medium text-secondary"
30
+ >
31
+ <Avatar
32
+ :src =" iconUrl"
33
+ no-shadow
34
+ style =" min-height : 20px ; min-width : 20px ; height : 20px ; width : 20px "
35
+ alt =" Server Icon"
36
+ />
37
+ Using {{ projectData?.title || 'Unknown' }}
38
+ </div >
39
+
40
+ <div
41
+ v-if =" isConfiguring"
42
+ class =" flex min-w-0 items-center gap-2 truncate text-sm font-semibold text-brand"
43
+ >
44
+ <SparklesIcon class =" size-5 shrink-0" /> New server
45
+ </div >
46
+ <ServerInfoLabels
47
+ v-else
48
+ :server-data =" { game, mc_version, loader, loader_version, net }"
49
+ :show-game-label =" showGameLabel"
50
+ :show-loader-label =" showLoaderLabel"
51
+ :linked =" false"
52
+ class =" pointer-events-none flex w-full flex-row flex-wrap items-center gap-4 text-secondary *:hidden sm:flex-row sm:*:flex"
53
+ />
51
54
</div >
52
- <ServerInfoLabels
53
- v-else
54
- :server-data =" { game, mc_version, loader, loader_version, net }"
55
- :show-game-label =" showGameLabel"
56
- :show-loader-label =" showLoaderLabel"
57
- :linked =" false"
58
- class =" pointer-events-none flex w-full flex-row flex-wrap items-center gap-4 text-secondary *:hidden sm:flex-row sm:*:flex"
59
- />
60
55
</div >
61
- </div >
56
+ </NuxtLink >
62
57
<div
63
58
v-if =" status === 'suspended' && suspension_reason === 'upgrading'"
64
- class =" relative -mt-4 flex w-full flex-row items-center gap-2 rounded-b-3xl bg-bg-blue p-4 text-sm font-bold text-contrast"
59
+ class =" relative flex w-full flex-row items-center gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-blue bg-bg-blue p-4 text-sm font-bold text-contrast"
65
60
>
66
61
<PanelSpinner />
67
62
Your server's hardware is currently being upgraded and will be back online shortly.
68
63
</div >
69
64
<div
70
65
v-else-if =" status === 'suspended' && suspension_reason === 'cancelled'"
71
- class =" relative -mt-4 flex w-full flex-col gap-2 rounded-b-3xl bg-bg-red p-4 text-sm font-bold text-contrast"
66
+ class =" relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
72
67
>
73
68
<div class =" flex flex-row gap-2" >
74
69
<PanelErrorIcon class =" !size-5" /> Your server has been cancelled. Please update your
78
73
</div >
79
74
<div
80
75
v-else-if =" status === 'suspended' && suspension_reason"
81
- class =" relative -mt-4 flex w-full flex-col gap-2 rounded-b-3xl bg-bg-red p-4 text-sm font-bold text-contrast"
76
+ class =" relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
82
77
>
83
78
<div class =" flex flex-row gap-2" >
84
79
<PanelErrorIcon class =" !size-5" /> Your server has been suspended: {{ suspension_reason }}.
88
83
</div >
89
84
<div
90
85
v-else-if =" status === 'suspended'"
91
- class =" relative -mt-4 flex w-full flex-col gap-2 rounded-b-3xl bg-bg-red p-4 text-sm font-bold text-contrast"
86
+ class =" relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-bg-red bg-bg-red p-4 text-sm font-bold text-contrast"
92
87
>
93
88
<div class =" flex flex-row gap-2" >
94
89
<PanelErrorIcon class =" !size-5" /> Your server has been suspended. Please update your
95
90
billing information or contact Modrinth Support for more information.
96
91
</div >
97
92
<CopyCode :text =" `${props.server_id}`" class =" ml-auto" />
98
93
</div >
99
- </NuxtLink >
94
+ <div
95
+ v-if =" pendingChange && status !== 'suspended'"
96
+ class =" relative flex w-full flex-col gap-2 rounded-b-2xl border-[1px] border-t-0 border-solid border-orange bg-bg-orange p-4 text-sm font-bold text-contrast"
97
+ >
98
+ <div >
99
+ Your server will {{ pendingChange.verb.toLowerCase() }} to the "{{
100
+ pendingChange.planSize
101
+ }}" plan on {{ formatDate(pendingChange.date) }}.
102
+ </div >
103
+ <ServersSpecs
104
+ class =" !font-normal !text-contrast"
105
+ :ram =" Math.round((pendingChange.ramGb ?? 0) * 1024)"
106
+ :storage =" Math.round((pendingChange.storageGb ?? 0) * 1024)"
107
+ :cpus =" pendingChange.cpuBurst"
108
+ bursting-link =" https://docs.modrinth.com/servers/bursting"
109
+ />
110
+ </div >
111
+ </div >
100
112
</template >
101
113
102
114
<script setup lang="ts">
103
115
import { ChevronRightIcon , LockIcon , SparklesIcon } from ' @modrinth/assets'
104
- import { Avatar , CopyCode } from ' @modrinth/ui'
116
+ import { Avatar , CopyCode , ServersSpecs } from ' @modrinth/ui'
105
117
import type { Project , Server } from ' @modrinth/utils'
118
+ import dayjs from ' dayjs'
106
119
107
120
import { useModrinthServers } from ' ~/composables/servers/modrinth-servers.ts'
108
121
@@ -111,7 +124,19 @@ import PanelSpinner from './PanelSpinner.vue'
111
124
import ServerIcon from ' ./ServerIcon.vue'
112
125
import ServerInfoLabels from ' ./ServerInfoLabels.vue'
113
126
114
- const props = defineProps <Partial <Server >>()
127
+ type PendingChange = {
128
+ planSize: string
129
+ cpu: number
130
+ cpuBurst: number
131
+ ramGb: number
132
+ swapGb? : number
133
+ storageGb? : number
134
+ date: string | number | Date
135
+ intervalChange? : string | null
136
+ verb: string
137
+ }
138
+
139
+ const props = defineProps <Partial <Server > & { pendingChange? : PendingChange }>()
115
140
116
141
if (props .server_id && props .status === ' available' ) {
117
142
// Necessary only to get server icon
@@ -138,4 +163,12 @@ if (props.upstream) {
138
163
const image = useState <string | undefined >(` server-icon-${props .server_id } ` , () => undefined )
139
164
const iconUrl = computed (() => projectData .value ?.icon_url || undefined )
140
165
const isConfiguring = computed (() => props .flows ?.intro )
166
+
167
+ const formatDate = (d : unknown ) => {
168
+ try {
169
+ return dayjs (d as any ).format (' MMMM D, YYYY' )
170
+ } catch {
171
+ return ' '
172
+ }
173
+ }
141
174
</script >
0 commit comments