Migrate first parts of backups view to vue

This commit is contained in:
Johannes Zellner
2025-02-04 15:10:38 +01:00
parent 55939f6320
commit 776e65bc5e
10 changed files with 631 additions and 16 deletions
+140
View File
@@ -0,0 +1,140 @@
<script setup>
import { useI18n } from 'vue-i18n';
const i18n = useI18n();
const t = i18n.t;
import { ref, onMounted, useTemplateRef, computed } from 'vue';
import { Button, InputDialog, Dialog, FormGroup, TableView } from 'pankow';
import { prettyLongDate } from 'pankow/utils';
import { TASK_TYPES } from '../constants.js';
import Section from '../components/Section.vue';
import BackupsModel from '../models/BackupsModel.js';
import AppsModel from '../models/AppsModel.js';
import TasksModel from '../models/TasksModel.js';
const backupsModel = BackupsModel.create();
const appsModel = AppsModel.create();
const tasksModel = TasksModel.create();
const columns = {
archived: {},
packageVersion: { label: t('backups.listing.version'), sort: true },
creationTime: { label: t('main.table.date'), sort: true },
content: { label: t('backups.listing.contents'), sort: false },
actions: {}
};
const busy = ref(true);
const backups = ref([]);
const taskLogsMenu = ref([]);
const backupTask = ref({});
async function waitForTask() {
if (!backupTask.value.id) return;
const [error, result] = await tasksModel.get(backupTask.value.id);
if (error) return console.error(error);
backupTask.value = result;
// task done, refresh menu
if (!result.active) return await refreshTasks();
setTimeout(waitForTask, 2000);
}
async function refreshTasks() {
const [error, result] = await tasksModel.getByType(TASK_TYPES.TASK_BACKUP);
if (error) return console.error(error);
backupTask.value = result[0] || {};
// limit to last 10
taskLogsMenu.value = result.slice(0,10).map(t => {
return {
icon: 'fa-solid ' + ((!t.active && t.success) ? 'status-active fa-check-circle' : (t.active ? 'fa-circle-notch fa-spin' : 'status-error fa-times-circle')),
label: prettyLongDate(t.ts),
action: () => { window.open(`/logs.html?taskId=${t.id}`); }
};
});
// if last task is currently active, start polling
if (backupTask.value.active) waitForTask();
}
async function refreshBackups() {
const [error, result] = await backupsModel.list();
if (error) return console.error(error);
// add contents property
const appsById = {};
const appsByFqdn = {};
const [appsError, apps] = await appsModel.list();
if (appsError) console.error(error);
(apps || []).forEach(function (app) {
appsById[app.id] = app;
appsByFqdn[app.fqdn] = app;
});
result.forEach(function (backup) {
backup.contents = []; // { id, label, fqdn }
backup.dependsOn.forEach(function (appBackupId) {
const match = appBackupId.match(/app_(.*?)_.*/); // *? means non-greedy
if (!match) return; // for example, 'mail'
const app = appsById[match[1]];
if (app) {
backup.contents.push({
id: app.id,
label: app.label,
fqdn: app.fqdn
});
} else {
backup.contents.push({
id: match[1],
label: null,
fqdn: null
});
}
});
});
backups.value = result;
}
onMounted(async () => {
await refreshBackups();
await refreshTasks();
busy.value = false;
});
</script>
<template>
<Section :title="$t('backups.listing.title')">
<template #header-buttons>
<Button tool icon="fas fa-align-left" v-tooltip="$t('settings.updates.showLogsAction')" :menu="taskLogsMenu" :disabled="!taskLogsMenu.length"/>
</template>
<TableView :columns="columns" :model="backups" :busy="busy">
<template #archived="slotProps">
<i class="fas fa-archive" v-show="slotProps.preserveSecs === -1" v-tooltip="$t('backups.listing.tooltipPreservedBackup')"></i>
</template>
<template #creationTime="slotProps">{{ prettyLongDate(slotProps.creationTime) }}</template>
<template #content="slotProps">
<span v-if="slotProps.contents.length">{{ $t('backups.listing.appCount', { appCount: slotProps.contents.length }) }}</span>
<span v-else>{{ $t('backups.listing.noApps') }}</span>
</template>
<template #actions="slotProps">
<div class="table-actions">
<Button tool secondary small icon="fa-solid fa-pencil-alt" v-tooltip="$t('backups.listing.tooltipEditBackup')" @click="onEdit(slotProps)"></Button>
<Button tool secondary small icon="fa-solid fa-file-alt" v-tooltip="$t('backups.listing.tooltipDownloadBackupConfig')" @click="onDownloadConfig(slotProps)"></Button>
</div>
</template>
</TableView>
</Section>
</template>