mirror of
https://github.com/Sebclem/hassio-nextcloud-backup.git
synced 2024-11-22 17:22:58 +01:00
🔨 Display backed up snaps in Web UI (Close #3)
This commit is contained in:
parent
c403ec5079
commit
cc9f35e1ec
@ -43,16 +43,29 @@ router.get('/formated-local-snap', function(req, res, next) {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/formated-remote-manual', function(req, res, next) {
|
router.get('/formated-backup-manual', function(req, res, next) {
|
||||||
webdav.init(true, 'cloud.seb6596.ovh', 'admin', 'WPHRG-4jwCw-i8eqg-mtiao-Kmwrw').then(() => {
|
webdav.getFolderContent('/Hassio Backup/Manual/')
|
||||||
console.log('success');
|
.then((contents) => {
|
||||||
}, (err) => {
|
contents.sort((a, b) => {
|
||||||
console.log('failure');
|
if (moment(a.lastmod).isBefore(moment(b.lastmod)))
|
||||||
console.log(err);
|
return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
})
|
})
|
||||||
|
res.render('backupSnaps',{backups: contents, moment: moment});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/formated-backup-auto', function(req, res, next) {
|
||||||
|
webdav.getFolderContent('/Hassio Backup/Auto/')
|
||||||
|
.then((contents) => {
|
||||||
|
res.render('backupSnaps',{backups: contents, moment: moment});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
router.post('/nextcloud-settings', function(req, res, next) {
|
router.post('/nextcloud-settings', function(req, res, next) {
|
||||||
let settings = req.body;
|
let settings = req.body;
|
||||||
@ -90,7 +103,7 @@ router.post('/manual-backup', function(req, res, next) {
|
|||||||
let id = req.query.id;
|
let id = req.query.id;
|
||||||
let name = req.query.name;
|
let name = req.query.name;
|
||||||
let status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
if (status.status == "creating" && status.status == "upload" && status.status == "download"){
|
if (status.status == "creating" && status.status == "upload" && status.status == "download") {
|
||||||
res.status(503);
|
res.status(503);
|
||||||
res.send();
|
res.send();
|
||||||
return;
|
return;
|
||||||
@ -112,7 +125,7 @@ router.post('/manual-backup', function(req, res, next) {
|
|||||||
router.post('/new-backup', function(req, res, next) {
|
router.post('/new-backup', function(req, res, next) {
|
||||||
|
|
||||||
let status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
if (status.status == "creating" && status.status == "upload" && status.status == "download"){
|
if (status.status == "creating" && status.status == "upload" && status.status == "download") {
|
||||||
res.status(503);
|
res.status(503);
|
||||||
res.send();
|
res.send();
|
||||||
return;
|
return;
|
||||||
@ -147,9 +160,6 @@ router.post('/backup-settings', function(req, res, next) {
|
|||||||
res.status(400);
|
res.status(400);
|
||||||
res.send();
|
res.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,10 +163,10 @@ class WebdavTools {
|
|||||||
let lastPercent = 0;
|
let lastPercent = 0;
|
||||||
let req = request.put(option)
|
let req = request.put(option)
|
||||||
.on('drain', () => {
|
.on('drain', () => {
|
||||||
let percent = Math.floor((req.req.connection.bytesWritten / fileSize)*100);
|
let percent = Math.floor((req.req.connection.bytesWritten / fileSize) * 100);
|
||||||
if(lastPercent != percent){
|
if (lastPercent != percent) {
|
||||||
lastPercent = percent;
|
lastPercent = percent;
|
||||||
status.progress = percent/100;
|
status.progress = percent / 100;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ class WebdavTools {
|
|||||||
reject(status.message);
|
reject(status.message);
|
||||||
|
|
||||||
}).on('response', (res) => {
|
}).on('response', (res) => {
|
||||||
if (res.statusCode != 204) {
|
if (res.statusCode != 201) {
|
||||||
status.status = "error";
|
status.status = "error";
|
||||||
status.error_code = 4;
|
status.error_code = 4;
|
||||||
status.message = "Fail to upload snapshot to nextcloud (Status code: " + res.statusCode + ") !"
|
status.message = "Fail to upload snapshot to nextcloud (Status code: " + res.statusCode + ") !"
|
||||||
@ -205,6 +205,17 @@ class WebdavTools {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFolderContent(path) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.client.getDirectoryContents(path)
|
||||||
|
.then((contents)=>{
|
||||||
|
resolve(contents);
|
||||||
|
}).catch((error)=>{
|
||||||
|
reject(error);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
<% if (locals.backups) { %>
|
||||||
|
<div class="collection">
|
||||||
|
<% for(const index in backups) { %>
|
||||||
|
<a class="collection-item local-snap-listener modal-trigger" href="#modal-<%=backups[index].etag%>"
|
||||||
|
data-id="<%= backups[index].etag %>">
|
||||||
|
<div><%= backups[index].basename%><div class="secondary-content">
|
||||||
|
<%= moment(backups[index].lastmod).format('MMM D, YYYY HH:mm') %></div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div id="modal-<%=backups[index].etag%>" class="modal modal-fixed-footer blue-grey darken-4 white-text">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12 center">
|
||||||
|
<h4>Backup Detail</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12 center divider">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="input-field col s12">
|
||||||
|
<input disabled type="text" id="name-<%=backups[index].etag%>" value="<%= backups[index].basename %>" />
|
||||||
|
<label for="name-<%=backups[index].etag%>" class="white-text active">Name</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="input-field col s12">
|
||||||
|
<input disabled type="text" id="date-<%=backups[index].etag%>"
|
||||||
|
value="<%=moment(backups[index].lastmod).format('MMM D, YYYY HH:mm')%>" />
|
||||||
|
<label for="date-<%=backups[index].etag%>" class="white-text active">Date</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer blue-grey darken-4">
|
||||||
|
<a href="#!" class="modal-close waves-effect waves-green btn red">Close</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<% } %>
|
@ -131,12 +131,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col s12 m3">
|
<div class="col s12 m3">
|
||||||
<div class="card cyan darken-3">
|
<div class="card cyan darken-3">
|
||||||
<div class="card-content" >
|
<div class="card-content">
|
||||||
<span class="card-title white-text" style="font-weight: bold;">Manual </span>
|
<span class="card-title white-text" style="font-weight: bold;">Manual </span>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div style="width: 100%;" class="center">
|
<div style="width: 100%;" class="center">
|
||||||
<a class="btn green center waves-effect waves-light" id="btn-backup-now" style="margin-top: 7px;">Backup Now</a>
|
<a class="btn green center waves-effect waves-light" id="btn-backup-now" style="margin-top: 7px;">Backup
|
||||||
<a class="btn center teal darken-4 waves-effect waves-light" id="btn-clean-now" style="margin-top: 7px;">Clean Now</a>
|
Now</a>
|
||||||
|
<a class="btn center teal darken-4 waves-effect waves-light" id="btn-clean-now"
|
||||||
|
style="margin-top: 7px;">Clean Now</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -154,6 +156,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col s12 m12 l6 ">
|
||||||
|
<div class="card cyan darken-3">
|
||||||
|
<div class="card-content">
|
||||||
|
<span class="card-title center white-text">Nextcloud Backups</span>
|
||||||
|
<span class="card-title center white-text">Auto</span>
|
||||||
|
<span class="card-title center white-text divider"></span>
|
||||||
|
<div id="auto_backups"></div>
|
||||||
|
<span class="card-title center white-text">Manu</span>
|
||||||
|
<span class="card-title center white-text divider"></span>
|
||||||
|
<div id="manual_backups"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -353,6 +368,8 @@
|
|||||||
<script>
|
<script>
|
||||||
var last_status = "";
|
var last_status = "";
|
||||||
var last_local_snap = "";
|
var last_local_snap = "";
|
||||||
|
var last_manu_back = "";
|
||||||
|
var last_auto_back = "";
|
||||||
|
|
||||||
var loadingModal = null;
|
var loadingModal = null;
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
@ -369,14 +386,7 @@
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateLocalSnaps() {
|
function updateDynamicListeners() {
|
||||||
$.get('./api/formated-local-snap', (data) => {
|
|
||||||
if (JSON.stringify(data) === last_local_snap)
|
|
||||||
return;
|
|
||||||
last_local_snap = JSON.stringify(data);
|
|
||||||
$('#local_snaps').empty();
|
|
||||||
$('#local_snaps').html(data);
|
|
||||||
|
|
||||||
var elems = document.querySelectorAll('.collapsible');
|
var elems = document.querySelectorAll('.collapsible');
|
||||||
M.Collapsible.init(elems, { accordion: true });
|
M.Collapsible.init(elems, { accordion: true });
|
||||||
var modals = document.querySelectorAll('.modal:not(#modal-loading)');
|
var modals = document.querySelectorAll('.modal:not(#modal-loading)');
|
||||||
@ -396,7 +406,49 @@
|
|||||||
let name = this.getAttribute('data-name');
|
let name = this.getAttribute('data-name');
|
||||||
manualBackup(id, name);
|
manualBackup(id, name);
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateLocalSnaps() {
|
||||||
|
let needUpdate = false;
|
||||||
|
$.get('./api/formated-local-snap', (data) => {
|
||||||
|
if (JSON.stringify(data) === last_local_snap)
|
||||||
|
return;
|
||||||
|
last_local_snap = JSON.stringify(data);
|
||||||
|
needUpdate = true;
|
||||||
|
$('#local_snaps').empty();
|
||||||
|
$('#local_snaps').html(data);
|
||||||
|
}).always(() => {
|
||||||
|
updateManuBackup(needUpdate);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateManuBackup(prevUpdate) {
|
||||||
|
let needUpdate = false;
|
||||||
|
$.get('./api/formated-backup-manual', (data) => {
|
||||||
|
if (JSON.stringify(data) === last_manu_back)
|
||||||
|
return;
|
||||||
|
last_manu_back = JSON.stringify(data);
|
||||||
|
needUpdate = true;
|
||||||
|
$('#manual_backups').empty();
|
||||||
|
$('#manual_backups').html(data);
|
||||||
|
|
||||||
|
}).always(() => {
|
||||||
|
updateAutoBackup(prevUpdate || needUpdate);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function updateAutoBackup(prevUpdate) {
|
||||||
|
let needUpdate = false;
|
||||||
|
$.get('./api/formated-backup-auto', (data) => {
|
||||||
|
if (JSON.stringify(data) === last_auto_back)
|
||||||
|
return;
|
||||||
|
needUpdate = true;
|
||||||
|
last_auto_back = JSON.stringify(data);
|
||||||
|
$('#auto_backups').empty();
|
||||||
|
$('#auto_backups').html(data);
|
||||||
|
|
||||||
|
}).always(() => {
|
||||||
|
if (prevUpdate || needUpdate)
|
||||||
|
updateDynamicListeners();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,23 +459,23 @@
|
|||||||
switch (data.status) {
|
switch (data.status) {
|
||||||
case "error":
|
case "error":
|
||||||
printStatus('Error', data.message);
|
printStatus('Error', data.message);
|
||||||
$('#btn-backup-now').removeClass("disabled");
|
$('#btn-backup-now, #btn-clean-now').removeClass("disabled");
|
||||||
break;
|
break;
|
||||||
case "idle":
|
case "idle":
|
||||||
printStatus('Idle', "Waiting for next backup.");
|
printStatus('Idle', "Waiting for next backup.");
|
||||||
$('#btn-backup-now').removeClass("disabled");
|
$('#btn-backup-now, #btn-clean-now').removeClass("disabled");
|
||||||
break;
|
break;
|
||||||
case "download":
|
case "download":
|
||||||
printStatusWithBar('Downloading Snapshot', data.progress);
|
printStatusWithBar('Downloading Snapshot', data.progress);
|
||||||
$('#btn-backup-now').addClass("disabled");
|
$('#btn-backup-now, #btn-clean-now').addClass("disabled");
|
||||||
break;
|
break;
|
||||||
case "upload":
|
case "upload":
|
||||||
printStatusWithBar('Uploading Snapshot', data.progress);
|
printStatusWithBar('Uploading Snapshot', data.progress);
|
||||||
$('#btn-backup-now').addClass("disabled");
|
$('#btn-backup-now, #btn-clean-now').addClass("disabled");
|
||||||
break;
|
break;
|
||||||
case "creating":
|
case "creating":
|
||||||
printStatusWithBar('Creating Snapshot', data.progress);
|
printStatusWithBar('Creating Snapshot', data.progress);
|
||||||
$('#btn-backup-now').addClass("disabled");
|
$('#btn-backup-now, #btn-clean-now').addClass("disabled");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (data.last_backup != null) {
|
if (data.last_backup != null) {
|
||||||
@ -629,9 +681,9 @@
|
|||||||
.done(() => {
|
.done(() => {
|
||||||
M.toast({ html: '<i class="material-icons" style="margin-right:10px">check_box</i> Backup settings saved !', classes: "green" });
|
M.toast({ html: '<i class="material-icons" style="margin-right:10px">check_box</i> Backup settings saved !', classes: "green" });
|
||||||
M.Modal.getInstance(document.querySelector('#modal-settings-backup')).close();
|
M.Modal.getInstance(document.querySelector('#modal-settings-backup')).close();
|
||||||
}).fail(()=>{
|
}).fail(() => {
|
||||||
M.toast({ html: '<i class="material-icons" style="margin-right:10px">warning</i> Can\'t save backup settings !', classes: "red" });
|
M.toast({ html: '<i class="material-icons" style="margin-right:10px">warning</i> Can\'t save backup settings !', classes: "red" });
|
||||||
}).always(()=>{
|
}).always(() => {
|
||||||
loadingModal.close();
|
loadingModal.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user