Migrate first parts of backups view to vue
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user