You've already forked AstralRinth
feat: backups page cleanup before worlds (#5844)
* feat: card alignment + fix modals * feat: change admon title in restore alert modal * fix: lint * feat: backups queue api into api-client * feat: impl backup queue api endpoints into frontend * feat: ack fix * feat: bulk actions * feat: bulk delete impl * fix: lint * fix: align error states * fix: transition group * feat: ready for qa * fix: lint * feat: qa * feat: stacked admonitions component * fix: issues with stacking * feat: hook up admonition stacking + fix app csp for staging kyros nodes * fix: logs.vue * qa: close stack on admonitions click * fix: all problems with stacked admonitions * qa: admonition cleanup and copy overhaul draft * fix: qa issues padding * fix: padding bug * feat: qa * fix: intercom in app csp bug * fix: positioning intercom * feat: loading overlay on top of console + admon consistency changes * feat: scroll indicator fade in backup delete modal + admon timestamp fix * feat: move action bar behind modal * fix: lint + i18n * fix: server ping spam on filter (cache but clear on unmount) * fix: 1 admon fade in flicker issue * chore: temp staging undo * qa: changes * fix: lint * chore: revert staging to use staging * fix: scoping
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<NewModal ref="modal" header="Restore backup" fade="danger">
|
||||
<div class="flex flex-col gap-6 max-w-[400px]">
|
||||
<NewModal ref="modal" header="Restore backup" fade="danger" width="500px">
|
||||
<div class="flex flex-col gap-6">
|
||||
<Admonition v-if="ctx.isServerRunning.value" type="critical" header="Server is running">
|
||||
Stop the server before restoring a backup.
|
||||
</Admonition>
|
||||
<Admonition v-else type="critical" header="Restore warning">
|
||||
<Admonition v-else type="critical" header="Your server files will be replaced">
|
||||
Restoring your server will replace the current world and server files. Any changes made
|
||||
since that backup will be permanently lost.
|
||||
</Admonition>
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
<template #actions>
|
||||
<div class="flex gap-2 justify-end">
|
||||
<ButtonStyled>
|
||||
<button @click="modal?.hide()">
|
||||
<ButtonStyled type="outlined">
|
||||
<button class="!border !border-surface-4" @click="modal?.hide()">
|
||||
<XIcon />
|
||||
Cancel
|
||||
</button>
|
||||
@@ -56,18 +56,24 @@ const client = injectModrinthClient()
|
||||
const queryClient = useQueryClient()
|
||||
const ctx = injectModrinthServerContext()
|
||||
|
||||
const backupsQueryKey = ['backups', 'list', ctx.serverId]
|
||||
const backupsQueryKey = ['backups', 'queue', ctx.serverId]
|
||||
|
||||
function safetyBackupName(backupName: string) {
|
||||
const base = `Before restoring "${backupName}"`
|
||||
return base.slice(0, 92)
|
||||
}
|
||||
|
||||
const restoreMutation = useMutation({
|
||||
mutationFn: (backupId: string) =>
|
||||
client.archon.backups_v1.restore(ctx.serverId, ctx.worldId.value!, backupId),
|
||||
mutationFn: ({ backupId, name }: { backupId: string; name: string }) =>
|
||||
client.archon.backups_queue_v1.restore(ctx.serverId, ctx.worldId.value!, backupId, { name }),
|
||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: backupsQueryKey }),
|
||||
})
|
||||
|
||||
const modal = ref<InstanceType<typeof NewModal>>()
|
||||
const currentBackup = ref<Archon.Backups.v1.Backup | null>(null)
|
||||
const currentBackup = ref<Archon.BackupsQueue.v1.BackupQueueBackup | null>(null)
|
||||
const isRestoring = ref(false)
|
||||
|
||||
function show(backup: Archon.Backups.v1.Backup) {
|
||||
function show(backup: Archon.BackupsQueue.v1.BackupQueueBackup) {
|
||||
currentBackup.value = backup
|
||||
modal.value?.show()
|
||||
}
|
||||
@@ -85,22 +91,24 @@ const restoreBackup = () => {
|
||||
}
|
||||
|
||||
isRestoring.value = true
|
||||
restoreMutation.mutate(currentBackup.value.id, {
|
||||
onSuccess: () => {
|
||||
// Optimistically update backupsState to show restore in progress immediately
|
||||
ctx.backupsState.set(currentBackup.value!.id, {
|
||||
restore: { progress: 0, state: 'ongoing' },
|
||||
})
|
||||
modal.value?.hide()
|
||||
restoreMutation.mutate(
|
||||
{
|
||||
backupId: currentBackup.value.id,
|
||||
name: safetyBackupName(currentBackup.value.name),
|
||||
},
|
||||
onError: (error) => {
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
addNotification({ type: 'error', title: 'Failed to restore backup', text: message })
|
||||
{
|
||||
onSuccess: () => {
|
||||
modal.value?.hide()
|
||||
},
|
||||
onError: (error) => {
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
addNotification({ type: 'error', title: 'Failed to restore backup', text: message })
|
||||
},
|
||||
onSettled: () => {
|
||||
isRestoring.value = false
|
||||
},
|
||||
},
|
||||
onSettled: () => {
|
||||
isRestoring.value = false
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
|
||||
Reference in New Issue
Block a user