Add autoupdate pattern dialog
This commit is contained in:
@@ -1,21 +1,210 @@
|
||||
<script setup>
|
||||
|
||||
import { ref } from 'vue';
|
||||
import { Button } from 'pankow';
|
||||
const API_ORIGIN = import.meta.env.VITE_API_ORIGIN ? import.meta.env.VITE_API_ORIGIN : window.location.origin;
|
||||
|
||||
import { ref, onMounted, useTemplateRef } from 'vue';
|
||||
import { Button, Dialog, ProgressBar, Radiobutton, MultiSelect } from 'pankow';
|
||||
import Section from '../components/Section.vue';
|
||||
import UpdaterModel from '../models/UpdaterModel.js';
|
||||
import DashboardModel from '../models/DashboardModel.js';
|
||||
|
||||
const updaterModel = UpdaterModel.create(API_ORIGIN, localStorage.token);
|
||||
const dashboardModel = DashboardModel.create(API_ORIGIN, localStorage.token);
|
||||
|
||||
// values correspond to cron days
|
||||
const cronDays = [
|
||||
{ id: 0, name: 'Sunday', value: 0 },
|
||||
{ id: 1, name: 'Monday', value: 1 },
|
||||
{ id: 2, name: 'Tuesday', value: 2 },
|
||||
{ id: 3, name: 'Wednesday', value: 3 },
|
||||
{ id: 4, name: 'Thursday', value: 4 },
|
||||
{ id: 5, name: 'Friday', value: 5 },
|
||||
{ id: 6, name: 'Saturday', value: 6 },
|
||||
];
|
||||
|
||||
// generates 24h time sets (instead of american 12h) to avoid having to translate everything to locales eg. 12:00
|
||||
const cronHours = Array.from({ length: 24 }).map((v, i) => { return { name: (i < 10 ? '0' : '') + i + ':00', value: i, id: i }; });
|
||||
|
||||
function prettyAutoUpdateSchedule(pattern) {
|
||||
if (!pattern) return '';
|
||||
const tmp = pattern.split(' ');
|
||||
|
||||
if (tmp.length === 1) return tmp[0];
|
||||
|
||||
const hours = tmp[2].split(',');
|
||||
const days = tmp[5].split(',');
|
||||
const prettyDay = (days.length === 7 || days[0] === '*') ? 'Everyday' : days.map((day) => { return cronDays[parseInt(day, 10)].name.substr(0, 3); }).join(',');
|
||||
|
||||
try {
|
||||
const prettyHour = hours.map((hour) => { return cronHours[parseInt(hour, 10)].name; }).join(',');
|
||||
return prettyDay + ' at ' + prettyHour;
|
||||
} catch (error) {
|
||||
console.error('Unable to build pattern.', error);
|
||||
return 'Custom pattern';
|
||||
}
|
||||
}
|
||||
|
||||
const taskLogsMenu = ref([]);
|
||||
const version = ref('');
|
||||
const ubuntuVersion = ref('');
|
||||
const currentPattern = ref('');
|
||||
const percent = ref(0);
|
||||
const message = ref('');
|
||||
const updateBusy = ref(false);
|
||||
const checkingBusy = ref(false);
|
||||
const pendingUpdate = ref(null);
|
||||
|
||||
const configureDialog = useTemplateRef('configureDialog');
|
||||
const configureBusy = ref(false);
|
||||
const configureError = ref('');
|
||||
const configureType = ref('');
|
||||
const configurePattern = ref('');
|
||||
const configureDays = ref([]);
|
||||
const configureHours = ref([]);
|
||||
|
||||
async function refreshAutoupdatePattern() {
|
||||
const [error, result] = await updaterModel.getAutoupdatePattern();
|
||||
if (error) return console.error(error);
|
||||
|
||||
// just keep the UI sane by supporting previous default pattern
|
||||
if (result.pattern === '00 30 1,3,5,23 * * *') result.pattern = '00 15 1,3,5,23 * * *';
|
||||
|
||||
currentPattern.value = result.pattern;
|
||||
configurePattern.value = result.pattern;
|
||||
}
|
||||
|
||||
async function refreshInfo() {
|
||||
const [error, result] = await updaterModel.info();
|
||||
if (error) return console.error(error);
|
||||
|
||||
pendingUpdate.value = result.box || null;
|
||||
}
|
||||
|
||||
function onShowConfigure() {
|
||||
configureType.value = configurePattern.value === 'never' ? 'never' : 'pattern';
|
||||
const tmp = currentPattern.value.split(' ');
|
||||
const hours = tmp[2] ? tmp[2].split(',') : [];
|
||||
const days = tmp[5] ? tmp[5].split(',') : [];
|
||||
if (days[0] === '*') configureDays.value = cronDays;
|
||||
else configureDays.value = days.map(day => { return cronDays[parseInt(day, 10)]; });
|
||||
|
||||
try {
|
||||
configureHours.value = hours.map(hour => { return cronHours[parseInt(hour, 10)]; });
|
||||
} catch (error) {
|
||||
console.error('Error parsing hour', error);
|
||||
}
|
||||
|
||||
configureDialog.value.open();
|
||||
}
|
||||
|
||||
async function onSubmitConfigure() {
|
||||
let pattern = 'never';
|
||||
if (configureType.value === 'pattern') {
|
||||
let daysPattern;
|
||||
if (configureDays.value.length === 7) daysPattern = '*';
|
||||
else daysPattern = configureDays.value.map(d => { return d.value; });
|
||||
|
||||
let hoursPattern;
|
||||
if (configureHours.value.length === 24) hoursPattern = '*';
|
||||
else hoursPattern = configureHours.value.map(h => { return h.value; });
|
||||
|
||||
pattern ='00 00 ' + hoursPattern + ' * * ' + daysPattern;
|
||||
}
|
||||
|
||||
configureBusy.value = true;
|
||||
const [error] = await updaterModel.setAutoupdatePattern(pattern);
|
||||
if (error) {
|
||||
configureError.value = error.body ? error.body.message : 'Internal error';
|
||||
configureBusy.value = false;
|
||||
return console.error(error);
|
||||
}
|
||||
|
||||
await refreshAutoupdatePattern();
|
||||
|
||||
configureBusy.value = false;
|
||||
configureDialog.value.close();
|
||||
}
|
||||
|
||||
function onShowUpdate() {
|
||||
|
||||
}
|
||||
|
||||
async function onCheck() {
|
||||
checkingBusy.value = true;
|
||||
|
||||
const [error] = await updaterModel.check();
|
||||
if (error) return console.error(error);
|
||||
|
||||
await refreshInfo();
|
||||
checkingBusy.value = false;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const [error, result] = await dashboardModel.getConfig();
|
||||
if (error) return console.error(error);
|
||||
|
||||
version.value = result.version;
|
||||
ubuntuVersion.value = result.ubuntuVersion;
|
||||
|
||||
await refreshInfo();
|
||||
await refreshAutoupdatePattern();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Dialog ref="configureDialog"
|
||||
:title="$t('settings.updateScheduleDialog.title')"
|
||||
:confirm-label="$t('main.dialog.save')"
|
||||
:reject-label="$t('main.dialog.cancel')"
|
||||
reject-style="secondary"
|
||||
@confirm="onSubmitConfigure()"
|
||||
>
|
||||
<p v-html="$t('settings.updateScheduleDialog.description')"></p>
|
||||
|
||||
<p class="has-error text-center" v-show="configureError">{{ configureError }}</p>
|
||||
|
||||
<Radiobutton v-model="configureType" value="never" :label="$t('settings.updateScheduleDialog.disableCheckbox')" />
|
||||
<br/>
|
||||
<Radiobutton v-model="configureType" value="pattern" :label="$t('settings.updateScheduleDialog.enableCheckbox')" />
|
||||
|
||||
<div v-show="configureType === 'pattern'" style="display: flex; gap: 10px;">
|
||||
<div>{{ $t('settings.updateScheduleDialog.days') }}: <MultiSelect v-model="configureDays" :options="cronDays" option-label="name" /></div>
|
||||
<div>{{ $t('settings.updateScheduleDialog.hours') }}: <MultiSelect v-model="configureHours" :options="cronHours" option-label="name" /></div>
|
||||
</div>
|
||||
<!-- <span class="label label-danger" ng-show="updateSchedule.type === 'pattern' && !updateSchedule.isScheduleValid()">{{ 'settings.updateScheduleDialog.selectOne' | tr }}</span> -->
|
||||
</Dialog>
|
||||
|
||||
<Section :title="$t('settings.updates.title')">
|
||||
<template #header-buttons>
|
||||
<Button tool icon="fas fa-align-left" v-tooltip="$t('settings.updates.showLogsAction')" :menu="taskLogsMenu" :disabled="!taskLogsMenu.length"/>
|
||||
</template>
|
||||
|
||||
<p v-html="$t('settings.updates.description')"></p>
|
||||
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ $t('settings.updates.version') }}</div>
|
||||
<div class="info-value">v{{ version }} ({{ ubuntuVersion }})
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-row">
|
||||
<div class="info-label">{{ $t('settings.updates.schedule') }}</div>
|
||||
<div class="info-value actionable" @click="onShowConfigure()">
|
||||
<span v-show="currentPattern !== 'never'">{{ prettyAutoUpdateSchedule(currentPattern) }}</span>
|
||||
<span v-show="currentPattern === 'never'">{{ $t('settings.updates.disabled') }}</span>
|
||||
<i class="fa-solid fa-edit text-small"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ProgressBar v-show="updateBusy" :value="percent" />
|
||||
<p v-show="updateBusy">{{ message }}</p>
|
||||
|
||||
<Button danger v-show="updateBusy" @click="onStop()">{{ $t('settings.updates.stopUpdateAction') }}</Button>
|
||||
<Button v-show="!pendingUpdate" :disabled="checkingBusy" :loading="checkingBusy" @click="onCheck()">{{ $t('settings.updates.checkForUpdatesAction') }}</Button>
|
||||
<Button :danger="(pendingUpdate && pendingUpdate.unstable) ? true : undefined" :success="(pendingUpdate && !pendingUpdate.unstable) ? true : undefined" v-show="pendingUpdate && pendingUpdate.version !== version && !updateBusy" @click="onShowUpdate()">{{ $t('settings.updates.updateAvailableAction') }}</Button>
|
||||
|
||||
</Section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user