dashboard: rename backupTargets to backupSites

This commit is contained in:
Girish Ramakrishnan
2025-09-12 09:48:37 +02:00
parent c5b7264f1a
commit da6be5c490
8 changed files with 172 additions and 172 deletions
@@ -2,11 +2,11 @@
import { ref, useTemplateRef, computed } from 'vue';
import { Dialog, FormGroup, MultiSelect } from '@cloudron/pankow';
import BackupTargetsModel from '../models/BackupTargetsModel.js';
import BackupSitesModel from '../models/BackupSitesModel.js';
const emit = defineEmits([ 'success' ]);
const backupTargetsModel = BackupTargetsModel.create();
const backupSitesModel = BackupSitesModel.create();
const backupRetentions = [
{ name: '2 days', id: { keepWithinSecs: 2 * 24 * 60 * 60 }},
@@ -57,14 +57,14 @@ async function onSubmit() {
if (hours.value.length === 24) hoursPattern = '*';
else hoursPattern = hours.value;
let [error] = await backupTargetsModel.setSchedule(id.value, `00 00 ${hoursPattern} * * ${daysPattern}`);
let [error] = await backupSitesModel.setSchedule(id.value, `00 00 ${hoursPattern} * * ${daysPattern}`);
if (error) {
busy.value = false;
formError.value = error.body ? error.body.message : 'Internal error';
return console.error(error);
}
[error] = await backupTargetsModel.setRetention(id.value, configureRetention.value);
[error] = await backupSitesModel.setRetention(id.value, configureRetention.value);
if (error) {
busy.value = false;
formError.value = error.body ? error.body.message : 'Internal error';
@@ -78,17 +78,17 @@ async function onSubmit() {
}
defineExpose({
async open(target) {
id.value = target.id;
async open(site) {
id.value = site.id;
busy.value = false;
formError.value = false;
const currentRetentionString = JSON.stringify(target.retention);
const currentRetentionString = JSON.stringify(site.retention);
let selectedRetention = backupRetentions.find(function (x) { return JSON.stringify(x.id) === currentRetentionString; });
if (!selectedRetention) selectedRetention = backupRetentions[0];
configureRetention.value = selectedRetention.id;
const tmp = target.schedule.split(' ');
const tmp = site.schedule.split(' ');
const tmpHours = tmp[2].split(',');
const tmpDays = tmp[5].split(',');
@@ -6,18 +6,18 @@ import { prettyBinarySize } from '@cloudron/pankow/utils';
import { REGIONS_CONTABO, REGIONS_VULTR, REGIONS_IONOS, REGIONS_OVH, REGIONS_LINODE, REGIONS_SCALEWAY, REGIONS_WASABI } from '../constants.js';
import { mountlike, s3like } from '../utils.js';
import BackupProviderForm from './BackupProviderForm.vue';
import BackupTargetsModel from '../models/BackupTargetsModel.js';
import BackupSitesModel from '../models/BackupSitesModel.js';
import SystemModel from '../models/SystemModel.js';
const emit = defineEmits([ 'success' ]);
const backupTargetsModel = BackupTargetsModel.create();
const backupSitesModel = BackupSitesModel.create();
const systemModel = SystemModel.create();
const dialog = useTemplateRef('dialog');
const form = useTemplateRef('form');
const step = ref('storage');
const newTargetId = ref('');
const newSiteId = ref('');
const name = ref('');
const useEncryption = ref(false);
const encryptionPassword = ref('');
@@ -146,7 +146,7 @@ async function onSubmit() {
formError.value = {};
busy.value = true;
const [error, result] = await backupTargetsModel.add(name.value, format.value, provider.value, data, schedulePattern, retention, limitsConfig);
const [error, result] = await backupSitesModel.add(name.value, format.value, provider.value, data, schedulePattern, retention, limitsConfig);
if (error) {
formError.value.generic = error.body ? error.body.message : 'Internal error';
busy.value = false;
@@ -154,7 +154,7 @@ async function onSubmit() {
}
// stash for encryption password step
newTargetId.value = result;
newSiteId.value = result;
busy.value = false;
formError.value = {};
@@ -178,7 +178,7 @@ async function onSetupEncryption() {
busy.value = true;
const [error] = await backupTargetsModel.setEncryption(newTargetId.value, encryptionPassword.value, encryptedFilenames.value, encryptionPasswordHint.value);
const [error] = await backupSitesModel.setEncryption(newSiteId.value, encryptionPassword.value, encryptedFilenames.value, encryptionPasswordHint.value);
if (error) {
if (error.body && error.body.message.indexOf('password') === 0) {
formError.value.password = error.body.message;
@@ -4,19 +4,19 @@ import { ref, useTemplateRef } from 'vue';
import { Dialog, FormGroup, TextInput } from '@cloudron/pankow';
import { prettyBinarySize } from '@cloudron/pankow/utils';
import { mountlike, s3like } from '../utils.js';
import BackupTargetsModel from '../models/BackupTargetsModel.js';
import BackupSitesModel from '../models/BackupSitesModel.js';
import SystemModel from '../models/SystemModel.js';
const emit = defineEmits([ 'success' ]);
const backupTargetsModel = BackupTargetsModel.create();
const backupSitesModel = BackupSitesModel.create();
const systemModel = SystemModel.create();
const minMemoryLimit = ref(1024 * 1024 * 1024); // 1 GB
const maxMemoryLimit = ref(minMemoryLimit.value); // set later
const dialog = useTemplateRef('dialog');
const target = ref({});
const site = ref({});
const formError = ref({});
const busy = ref(false);
const name = ref('');
@@ -29,7 +29,7 @@ const copyConcurrency = ref(0);
async function onSubmit() {
busy.value = true;
let [error] = await backupTargetsModel.setName(target.value.id, name.value);
let [error] = await backupSitesModel.setName(site.value.id, name.value);
if (error) {
formError.value.generic = error.body ? error.body.message : 'Internal error';
busy.value = false;
@@ -44,7 +44,7 @@ async function onSubmit() {
copyConcurrency: parseInt(copyConcurrency.value),
};
[error] = await backupTargetsModel.setLimits(target.value.id, limits);
[error] = await backupSitesModel.setLimits(site.value.id, limits);
if (error) {
formError.value.generic = error.body ? error.body.message : 'Internal error';
busy.value = false;
@@ -67,7 +67,7 @@ defineExpose({
async open(t) {
formError.value = {};
busy.value = false;
target.value = t;
site.value = t;
name.value = t.name || '';
memoryLimit.value = t.limits.memoryLimit || 1024 * 1024 * 1024; // 1 GB
@@ -97,33 +97,33 @@ defineExpose({
<div>
<div class="info-row">
<div class="info-label">{{ $t('backups.configureBackupStorage.provider') }}</div>
<div class="info-value">{{ target.provider }}</div>
<div class="info-value">{{ site.provider }}</div>
</div>
<div class="info-row" v-if="target.provider !== 'noop'">
<div class="info-row" v-if="site.provider !== 'noop'">
<div class="info-label">{{ $t('backups.configureBackupStorage.format') }}</div>
<div class="info-value">{{ target.format }} <i v-if="target.encrypted" class="fa-solid fa-lock"></i></div>
<div class="info-value">{{ site.format }} <i v-if="site.encrypted" class="fa-solid fa-lock"></i></div>
</div>
<div class="info-row" v-if="target.provider !== 'noop'">
<div class="info-row" v-if="site.provider !== 'noop'">
<div class="info-label">{{ $t('backups.location.location') }}</div>
<div class="info-value" style="overflow: auto;">
<span v-if="mountlike(target.provider) || target.provider === 'filesystem'">
<span v-if="target.provider === 'filesystem'">{{ target.config.backupDir }}{{ (target.config.prefix ? `/${target.config.prefix}` : '') }}</span>
<span v-if="target.provider === 'disk' || target.provider === 'ext4' || target.provider === 'xfs' || target.provider === 'mountpoint'">{{ target.config.mountOptions.diskPath || target.config.mountPoint }}{{ (target.config.prefix ? '/' : '') + target.config.prefix }}</span>
<span v-if="target.provider === 'cifs' || target.provider === 'nfs' || target.provider === 'sshfs'">{{ target.config.mountOptions.host }}:{{ target.config.mountOptions.remoteDir }}{{ (target.config.prefix ? '/' : '') + target.config.prefix }}</span>
<span v-if="mountlike(site.provider) || site.provider === 'filesystem'">
<span v-if="site.provider === 'filesystem'">{{ site.config.backupDir }}{{ (site.config.prefix ? `/${site.config.prefix}` : '') }}</span>
<span v-if="site.provider === 'disk' || site.provider === 'ext4' || site.provider === 'xfs' || site.provider === 'mountpoint'">{{ site.config.mountOptions.diskPath || site.config.mountPoint }}{{ (site.config.prefix ? '/' : '') + site.config.prefix }}</span>
<span v-if="site.provider === 'cifs' || site.provider === 'nfs' || site.provider === 'sshfs'">{{ site.config.mountOptions.host }}:{{ site.config.mountOptions.remoteDir }}{{ (site.config.prefix ? '/' : '') + site.config.prefix }}</span>
</span>
<span v-if="target.provider !== 's3' && target.provider !== 'minio' && (s3like(target.provider) || target.provider === 'gcs')">{{ target.config.bucket + (target.config.prefix ? '/' : '') + target.config.prefix }}</span>
<span v-if="target.provider === 's3'">{{ target.config.region + ' ' + target.config.bucket + (target.config.prefix ? '/' : '') + target.config.prefix }}</span>
<span v-if="target.provider === 'minio'">{{ target.config.endpoint + ' ' + target.config.bucket + (target.config.prefix ? '/' : '') + target.config.prefix }}</span>
<span v-if="site.provider !== 's3' && site.provider !== 'minio' && (s3like(site.provider) || site.provider === 'gcs')">{{ site.config.bucket + (site.config.prefix ? '/' : '') + site.config.prefix }}</span>
<span v-if="site.provider === 's3'">{{ site.config.region + ' ' + site.config.bucket + (site.config.prefix ? '/' : '') + site.config.prefix }}</span>
<span v-if="site.provider === 'minio'">{{ site.config.endpoint + ' ' + site.config.bucket + (site.config.prefix ? '/' : '') + site.config.prefix }}</span>
</div>
</div>
<div class="info-row" v-if="target.provider !== 'minio' && target.config?.endpoint">
<div class="info-row" v-if="site.provider !== 'minio' && site.config?.endpoint">
<div class="info-label">{{ $t('backups.location.endpoint') }}</div>
<div class="info-value">{{ target.config.endpoint || target.config.region }}</div>
<div class="info-value">{{ site.config.endpoint || site.config.region }}</div>
</div>
<div class="info-row" v-if="target.encrypted">
<div class="info-row" v-if="site.encrypted">
<div class="info-label">{{ $t('backups.configureBackupStorage.encryptionHint') }}</div>
<div class="info-value">{{ target.encryptionPasswordHint }}</div>
<div class="info-value">{{ site.encryptionPasswordHint }}</div>
</div>
<form @submit.prevent="onSubmit()" autocomplete="off" ref="form">
@@ -147,7 +147,7 @@ defineExpose({
<input type="range" id="memoryLimitInput" v-model="memoryLimit" :step="256*1024*1024" :min="minMemoryLimit" :max="maxMemoryLimit" />
</FormGroup>
<FormGroup v-if="s3like(target.provider)">
<FormGroup v-if="s3like(site.provider)">
<label for="uploadPartSizeInput">{{ $t('backups.configureBackupStorage.uploadPartSize') }}: <b>{{ prettyBinarySize(uploadPartSize, 'Default (50 MiB)') }}</b></label>
<p class="small">{{ $t('backups.configureBackupStorage.uploadPartSizeDescription') }}</p>
<input type="range" id="uploadPartSizeInput" v-model="uploadPartSize" list="uploadPartSizeTicks" :step="1024*1024" :min="10*1024*1024" :max="1024*1024*1024" />
@@ -161,22 +161,22 @@ defineExpose({
</datalist>
</FormGroup>
<FormGroup v-if="target.format === 'rsync' && target.provider !== 'noop'">
<FormGroup v-if="site.format === 'rsync' && site.provider !== 'noop'">
<label for="syncConcurrencyInput">{{ $t('backups.configureBackupStorage.uploadConcurrency') }}: <b>{{ syncConcurrency }}</b></label>
<div class="small">{{ $t('backups.configureBackupStorage.uploadConcurrencyDescription') }}</div>
<input type="range" id="syncConcurrencyInput" v-model="syncConcurrency" step="10" min="10" max="200" />
</FormGroup>
<FormGroup v-if="target.format === 'rsync' && (s3like(target.provider) || target.provider === 'gcs')">
<FormGroup v-if="site.format === 'rsync' && (s3like(site.provider) || site.provider === 'gcs')">
<label for="downloadConcurrencyInput">{{ $t('backups.configureBackupStorage.downloadConcurrency') }}: <b>{{ downloadConcurrency }}</b></label>
<div class="small">{{ $t('backups.configureBackupStorage.downloadConcurrencyDescription') }}</div>
<input type="range" id="downloadConcurrencyInput" v-model="downloadConcurrency" step="10" min="10" max="200" />
</FormGroup>
<FormGroup v-if="target.format === 'rsync' && (s3like(target.provider) || target.provider === 'gcs')">
<FormGroup v-if="site.format === 'rsync' && (s3like(site.provider) || site.provider === 'gcs')">
<label for="copyConcurrencyInput">{{ $t('backups.configureBackupStorage.copyConcurrency') }}: <b>{{ copyConcurrency }}</b></label>
<div class="small">{{ $t('backups.configureBackupStorage.copyConcurrencyDescription') }}
<span v-show="target.provider === 'digitalocean-spaces'">{{ $t('backups.configureBackupStorage.copyConcurrencyDigitalOceanNote') }}</span>
<span v-show="site.provider === 'digitalocean-spaces'">{{ $t('backups.configureBackupStorage.copyConcurrencyDigitalOceanNote') }}</span>
</div>
<input type="range" id="copyConcurrencyInput" v-model="copyConcurrency" step="10" min="10" max="500" />
</FormGroup>
+13 -13
View File
@@ -7,18 +7,18 @@ const t = i18n.t;
import { ref, onMounted, useTemplateRef } from 'vue';
import { Icon, Button, Switch, Checkbox, FormGroup, TextInput, TableView, Menu, Dialog, ProgressBar } from '@cloudron/pankow';
import { prettyLongDate } from '@cloudron/pankow/utils';
import { API_ORIGIN, RSTATES, TASK_TYPES } from '../../constants.js';
import { API_ORIGIN, RSTATES } from '../../constants.js';
import { download } from '../../utils.js';
import AppImportDialog from '../AppImportDialog.vue';
import AppRestoreDialog from '../AppRestoreDialog.vue';
import SettingsItem from '../SettingsItem.vue';
import AppsModel from '../../models/AppsModel.js';
import BackupTargetsModel from '../../models/BackupTargetsModel.js';
import BackupSitesModel from '../../models/BackupSitesModel.js';
import TasksModel from '../../models/TasksModel.js';
import BackupsModel from '../../models/BackupsModel.js';
const appsModel = AppsModel.create();
const backupTargetsModel = BackupTargetsModel.create();
const backupSitesModel = BackupSitesModel.create();
const tasksModel = TasksModel.create();
const props = defineProps([ 'app' ]);
@@ -38,7 +38,7 @@ const columns = ref({
label: t('app.backups.backups.time'),
sort: true,
},
target: {
site: {
label: t('backup.target.label'),
sort: true,
},
@@ -59,7 +59,7 @@ function onActionMenu(backup, event) {
}, {
icon: 'fa-solid fa-download',
label: t('app.backups.backups.downloadBackupTooltip'),
visible: backup.target.format === 'tgz' && props.app.accessLevel === 'admin',
visible: backup.site.format === 'tgz' && props.app.accessLevel === 'admin',
action: getDownloadLink.bind(null, backup),
}, {
icon: 'fa-solid fa-file-alt',
@@ -102,7 +102,7 @@ const taskLogsMenu = ref([]);
const lastTask = ref({});
const startBackupBusy = ref(false);
const stopBackupBusy = ref(false);
let backupTargets = [];
let backupSites = [];
async function onChangeAutoBackups(value) {
const [error] = await appsModel.configure(props.app.id, 'automatic_backup', { enable: value });
@@ -197,14 +197,14 @@ function getDownloadLink(backup) {
}
async function onDownloadConfig(backup) {
const [error, backupTarget] = await backupTargetsModel.get(backup.targetId);
const [error, backupSite] = await backupSitesModel.get(backup.siteId);
if (error) return console.error(error);
const tmp = {
remotePath: backup.remotePath
};
for (const k of ['provider', 'config', 'limits', 'format', 'encrypted', 'encryptedFilenames', 'encryptionPasswordHint']) {
tmp[k] = backupTarget[k];
tmp[k] = backupSite[k];
}
const filename = `${props.app.fqdn}-backup-config-${(new Date(backup.creationTime)).toISOString().split('T')[0]}.json`;
@@ -253,7 +253,7 @@ async function refreshBackupList() {
if (error) return console.error(error);
result.forEach(backup => {
backup.target = backupTargets.find(t => t.id === backup.targetId);
backup.site = backupSites.find(t => t.id === backup.siteId);
});
backups.value = result;
}
@@ -261,10 +261,10 @@ async function refreshBackupList() {
onMounted(async () => {
autoBackupsEnabled.value = props.app.enableBackup;
const [error, result] = await backupTargetsModel.list();
const [error, result] = await backupSitesModel.list();
if (error) return console.error(error);
backupTargets = result;
backupSites = result;
await refreshBackupList();
await refreshTasks();
@@ -378,8 +378,8 @@ onMounted(async () => {
<template #creationTime="backup">
{{ prettyLongDate(backup.creationTime) }} <b v-show="backup.label">({{ backup.label }})</b>
</template>
<template #target="backup">
{{ backup.target ? backup.target.name : 'unknown' }}
<template #site="backup">
{{ backup.site ? backup.site.name : 'unknown' }}
</template>
<template #actions="backup">
<div style="text-align: right;">