(add): Backup/Restore

This commit is contained in:
dbob16 committed 2026-07-16 22:38:01 -04:00
1 parent 76040c1f91
commit 1e6b7787b3
14 files changed
+343 -12

No files matched your search

+1
View File
@@ -29,6 +29,7 @@
<a href={resolve('/settings/auth-keys')} class={bS.gray}>Auth Keys</a>
{/if}
<a href={resolve('/settings/prefixes')} class={bS.gray}>Prefixes</a>
<a href={resolve('/settings/backuprestore')} class={bS.gray}>Backup/Restore</a>
</HeaderBar>
<h1 class="text-xl font-bold">{pageTitle}</h1>
<div class="flex flex-col gap-1 w-full py-1">
@@ -0,0 +1,6 @@
import { getSettings } from "$lib/server/settings/index.js"
export const load = async () => {
const s = getSettings();
return { remoteServer: s.remote_server };
}
@@ -0,0 +1,131 @@
<script>
import { resolve } from '$app/paths';
import HeaderBar from '$lib/client/components/HeaderBar.svelte';
import { bS, iS } from '$lib/client/styles';
const pageTitle = 'Backup and Restore | TAM';
let { data } = $props();
let remoteServer = $derived(data.remoteServer);
let uploadFile = $state();
let contents = $state('');
let results = $state('');
function setResult(newResult) {
results = newResult;
setTimeout(() => (results = ''), 10000);
}
async function downloadBackupFile(target) {
let fetch_url;
if (target === 'local') {
fetch_url = '/api/backuprestore/local';
} else if (target === 'remote') {
fetch_url = '/api/backuprestore/remote';
}
const now = new Date();
const date = {
year: now.getFullYear(),
month: String(now.getMonth() + 1).padStart(2, '0'),
day: String(now.getDate()).padStart(2, '0'),
hour: String(now.getHours()).padStart(2, '0'),
minutes: String(now.getMinutes()).padStart(2, '0')
};
const res = await fetch(fetch_url);
if (res.ok) {
const data = await res.json();
const jsonString = JSON.stringify(data, null, 2);
const blob = new Blob([jsonString], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `TAM_${date.year}-${date.month}-${date.day} ${date.hour}:${date.minutes}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
}
async function fileUpload(target) {
const reader = new FileReader();
reader.readAsText(uploadFile[0], 'utf-8');
reader.onload = function (e) {
contents = String(e.target.result);
};
console.log(contents);
setTimeout(async () => {
const res = await fetch(`/api/backuprestore/${target}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: contents
});
if (res.ok) setResult('File uploaded successfully. Check to see if your data exists.');
else setResult('Error uploading file.');
}, 100);
}
async function pushData(target) {
const res = await fetch(`/api/backuprestore/push/${target}`, { method: 'HEAD' });
const targetStr = target.charAt(0).toUpperCase() + target.slice(1);
if (res.ok) {
setResult(`${targetStr} pushed successfully.`);
} else {
setResult(`Error pushing ${targetStr}. Error [${res.status}] ${res.statusText}.`);
}
}
</script>
<svelte:head>
<title>{pageTitle}</title>
</svelte:head>
<div id="app_container" class="p-1">
<HeaderBar>
<a href={resolve('/settings')} class={bS.gray}>Back to Settings</a>
<div>Other Settings</div>
<a href={resolve('/settings/prefixes')} class={bS.gray}>Prefixes</a>
{#if remoteServer}
<a href={resolve('/settings/auth-keys')} class={bS.gray}>Auth Keys</a>
{/if}
</HeaderBar>
<h1 class="text-xl font-bold">{pageTitle}</h1>
<div class="my-1 p-1 border border-black rounded">
<h2 class="text-lg font-bold">Backup File Downloads</h2>
<div class="flex flex-row gap-1">
<button class={bS.gray} onclick={downloadBackupFile('local')}>Local Data</button>
{#if remoteServer}
<button class={bS.gray} onclick={downloadBackupFile('remote')}>Remote Data</button>
{/if}
</div>
</div>
<div class="my-1 p-1 border border-black rounded">
<h2 class="text-lg font-bold">Backup File Upload</h2>
<div class="flex flex-row gap-1 items-center">
<input
type="file"
accept=".json"
class="{iS.normal} rounded file:bg-gray-300 file:border file:border-black file:px-2 file:py-1 file:rounded"
bind:files={uploadFile}
/>
<button class={bS.gray} onclick={() => fileUpload('local')}>Upload to Local</button>
{#if remoteServer}
<button class={bS.gray} onclick={() => fileUpload('remote')}>Upload to Remote</button>
{/if}
</div>
</div>
{#if remoteServer}
<div class="my-1 p-1 border border-black rounded">
<h2 class="text-lg font-bold">Push Data to Server</h2>
<div class="flex flex-row gap-1">
<button class={bS.gray} onclick={() => pushData('prefixes')}>Push Prefixes</button>
<button class={bS.gray} onclick={() => pushData('tickets')}>Push Tickets</button>
<button class={bS.gray} onclick={() => pushData('baskets')}>Push Baskets</button>
</div>
</div>
{/if}
<div class="my-1 p-1 border border-black rounded">
<span class="font-bold">Status: </span><span>{results}</span>
</div>
</div>