From 102c21feaa2332987accc6a560bfdea998646841 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sun, 24 May 2026 23:04:37 -0400 Subject: [PATCH] =?UTF-8?q?fc3h(ui):=20Pinia=20backup=20store=20=E2=80=94?= =?UTF-8?q?=20runs,=20triggers,=20restore,=20delete,=20tag,=20settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/src/stores/backup.js | 109 ++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 frontend/src/stores/backup.js diff --git a/frontend/src/stores/backup.js b/frontend/src/stores/backup.js new file mode 100644 index 0000000..1bc5c85 --- /dev/null +++ b/frontend/src/stores/backup.js @@ -0,0 +1,109 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' + +import { useApi } from '../composables/useApi.js' + +export const useBackupStore = defineStore('backup', () => { + const api = useApi() + + const dbRuns = ref([]) + const imagesRuns = ref([]) + const settings = ref(null) + const loading = ref({ dbRuns: false, imagesRuns: false, settings: false }) + const lastError = ref(null) + + async function loadRuns(kind) { + const targetRef = kind === 'db' ? dbRuns : imagesRuns + const loadingKey = kind === 'db' ? 'dbRuns' : 'imagesRuns' + loading.value[loadingKey] = true + lastError.value = null + try { + const body = await api.get('/api/system/backup/runs', { + params: { kind, limit: 50 }, + }) + targetRef.value = body.runs || [] + } catch (e) { + lastError.value = e.message + } finally { + loading.value[loadingKey] = false + } + } + + async function triggerBackup(kind, tag = null) { + lastError.value = null + try { + await api.post(`/api/system/backup/${kind}`, { + body: tag ? { tag } : {}, + }) + } catch (e) { + lastError.value = e.message + throw e + } + } + + async function restore(runId, confirm) { + lastError.value = null + try { + await api.post(`/api/system/backup/runs/${runId}/restore`, { + body: { confirm }, + }) + } catch (e) { + lastError.value = e.message + throw e + } + } + + async function deleteRun(runId, confirm) { + lastError.value = null + try { + await api.delete(`/api/system/backup/runs/${runId}`, { + body: { confirm }, + }) + } catch (e) { + lastError.value = e.message + throw e + } + } + + async function setTag(runId, tag) { + lastError.value = null + try { + await api.patch(`/api/system/backup/runs/${runId}`, { + body: { tag }, + }) + } catch (e) { + lastError.value = e.message + throw e + } + } + + async function loadSettings() { + loading.value.settings = true + lastError.value = null + try { + settings.value = await api.get('/api/system/backup/settings') + } catch (e) { + lastError.value = e.message + } finally { + loading.value.settings = false + } + } + + async function patchSettings(patch) { + lastError.value = null + try { + settings.value = await api.patch('/api/system/backup/settings', { + body: patch, + }) + } catch (e) { + lastError.value = e.message + throw e + } + } + + return { + dbRuns, imagesRuns, settings, loading, lastError, + loadRuns, triggerBackup, restore, deleteRun, setTag, + loadSettings, patchSettings, + } +})