mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 14:56:37 +00:00
Hass.io improved snapshot view (#872)
* HASSIO Improved snapshot view * HASSIO Improved snapshot view2 * Update main * Feedback * Travis * Travis 2
This commit is contained in:
parent
710c2f1094
commit
6ce72444ae
@ -13,7 +13,7 @@
|
|||||||
<link rel="import" href="./addon-view/hassio-addon-view.html">
|
<link rel="import" href="./addon-view/hassio-addon-view.html">
|
||||||
<link rel="import" href="./addon-store/hassio-addon-store.html">
|
<link rel="import" href="./addon-store/hassio-addon-store.html">
|
||||||
<link rel="import" href="./supervisor/hassio-supervisor.html">
|
<link rel="import" href="./supervisor/hassio-supervisor.html">
|
||||||
<link rel="import" href="./snapshot/hassio-snapshot.html">
|
<link rel="import" href="./snapshots/hassio-snapshots.html">
|
||||||
<link rel="import" href="./hassio-data.html">
|
<link rel="import" href="./hassio-data.html">
|
||||||
|
|
||||||
<dom-module id="hassio-main">
|
<dom-module id="hassio-main">
|
||||||
@ -86,10 +86,11 @@
|
|||||||
hass-info='[[hassInfo]]'
|
hass-info='[[hassInfo]]'
|
||||||
></hassio-advanced>
|
></hassio-advanced>
|
||||||
|
|
||||||
<hassio-snapshot
|
<hassio-snapshots
|
||||||
page-name='snapshot'
|
page-name='snapshot'
|
||||||
hass='[[hass]]'
|
hass='[[hass]]'
|
||||||
></hassio-snapshot>
|
installed-addons='[[supervisorInfo.addons]]'
|
||||||
|
></hassio-snapshots>
|
||||||
|
|
||||||
<hass-error-screen
|
<hass-error-screen
|
||||||
page-name='not-found'
|
page-name='not-found'
|
||||||
|
@ -1,183 +0,0 @@
|
|||||||
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
|
|
||||||
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
|
|
||||||
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
|
|
||||||
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
|
|
||||||
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
|
|
||||||
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
|
|
||||||
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
|
|
||||||
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
|
|
||||||
|
|
||||||
<link rel='import' href='../../src/util/hass-mixins.html'>
|
|
||||||
|
|
||||||
<link rel="import" href="../../src/components/ha-menu-button.html">
|
|
||||||
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
|
|
||||||
|
|
||||||
<dom-module id="hassio-snapshot">
|
|
||||||
<template>
|
|
||||||
<style include="iron-flex ha-style">
|
|
||||||
paper-card {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
paper-card {
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 24px 0 32px;
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form paper-input {
|
|
||||||
max-width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ha-call-api-button {
|
|
||||||
color: var(--primary-color);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<app-header-layout has-scrolling-region>
|
|
||||||
<app-header slot="header" fixed>
|
|
||||||
<app-toolbar>
|
|
||||||
<paper-icon-button
|
|
||||||
icon='mdi:arrow-left'
|
|
||||||
on-tap='_backTapped'
|
|
||||||
></paper-icon-button>
|
|
||||||
<div main-title>Snapshots</div>
|
|
||||||
<paper-icon-button
|
|
||||||
icon="mdi:refresh"
|
|
||||||
on-tap="_refreshTapped"
|
|
||||||
></paper-icon-button>
|
|
||||||
</app-toolbar>
|
|
||||||
</app-header>
|
|
||||||
|
|
||||||
<div class='content'>
|
|
||||||
<template is='dom-if' if='[[_error]]'>
|
|
||||||
<p class='error'>[[_error]]</p>
|
|
||||||
</template>
|
|
||||||
<paper-card heading='Make a snapshot'>
|
|
||||||
<div class='card-content form'>
|
|
||||||
Snapshots allow you to easily backup and restore all data in your Hass.io instance.
|
|
||||||
<p>
|
|
||||||
<paper-input
|
|
||||||
disabled='[[_creatingSnapshot]]'
|
|
||||||
label="Snapshot name"
|
|
||||||
value='{{_snapshotName}}'
|
|
||||||
></paper-input>
|
|
||||||
</div>
|
|
||||||
<div class='card-actions'>
|
|
||||||
<paper-button
|
|
||||||
disabled='[[_creatingSnapshot]]'
|
|
||||||
on-tap='_createSnapshot'
|
|
||||||
>Create</paper-button>
|
|
||||||
</div>
|
|
||||||
</paper-card>
|
|
||||||
|
|
||||||
<paper-card heading='Available Snapshots'>
|
|
||||||
<div class='card-content'>
|
|
||||||
Snapshots allow you to easily backup and restore all data in your Hass.io instance.
|
|
||||||
<template is='dom-if' if='[[!data.length]]'>
|
|
||||||
<p>Looks like you don't have any snapshots yet.</p>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<template is='dom-repeat' items='[[_data]]' as='snapshot'>
|
|
||||||
<paper-item>
|
|
||||||
<paper-item-body two-line>
|
|
||||||
<div>[[snapshot.name]]</div>
|
|
||||||
<div secondary>[[snapshot.date]]</div>
|
|
||||||
</paper-item-body>
|
|
||||||
<ha-call-api-button
|
|
||||||
hass='[[hass]]'
|
|
||||||
path="[[_computeRestorePath(snapshot)]]"
|
|
||||||
>Restore</ha-call-api-button>
|
|
||||||
</paper-item>
|
|
||||||
</template>
|
|
||||||
</paper-card>
|
|
||||||
</div>
|
|
||||||
</app-header-layout>
|
|
||||||
</template>
|
|
||||||
</dom-module>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
class HassioSnapshot extends window.hassMixins.EventsMixin(Polymer.Element) {
|
|
||||||
static get is() { return 'hassio-snapshot'; }
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
observer: '_visibleChanged',
|
|
||||||
},
|
|
||||||
_snapshotName: String,
|
|
||||||
_creatingSnapshot: Boolean,
|
|
||||||
_error: Object,
|
|
||||||
_data: {
|
|
||||||
type: Array,
|
|
||||||
value: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ready() {
|
|
||||||
super.ready();
|
|
||||||
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
|
|
||||||
}
|
|
||||||
|
|
||||||
_visibleChanged(visible) {
|
|
||||||
if (visible) {
|
|
||||||
this._updateData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_apiCalled(ev) {
|
|
||||||
if (ev.detail.success) {
|
|
||||||
this._updateData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateData() {
|
|
||||||
this.hass.callApi('get', 'hassio/snapshots')
|
|
||||||
.then(function (result) {
|
|
||||||
this._data = result.data.snapshots;
|
|
||||||
}.bind(this), function (error) {
|
|
||||||
this._error = error.message;
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
_createSnapshot() {
|
|
||||||
this._creatingSnapshot = true;
|
|
||||||
this.hass.callApi('post', 'hassio/snapshots/new/full', {
|
|
||||||
name: this._snapshotName,
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
this._creatingSnapshot = false;
|
|
||||||
this._snapshotName = '';
|
|
||||||
|
|
||||||
// This will trigger a refresh of supervisor info
|
|
||||||
this.fire('hass-api-called', { success: true });
|
|
||||||
}.bind(this), function (error) {
|
|
||||||
this._creatingSnapshot = false;
|
|
||||||
this._error = error.message;
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeRestorePath(snapshot) {
|
|
||||||
return 'hassio/snapshots/' + snapshot.slug + '/restore/full';
|
|
||||||
}
|
|
||||||
|
|
||||||
_backTapped() {
|
|
||||||
history.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
_refreshTapped() {
|
|
||||||
this.hass.callApi('post', 'hassio/snapshots/reload')
|
|
||||||
.then(function () {
|
|
||||||
this._updateData();
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define(HassioSnapshot.is, HassioSnapshot);
|
|
||||||
</script>
|
|
221
hassio/snapshots/hassio-snapshot.html
Normal file
221
hassio/snapshots/hassio-snapshot.html
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-dialog/paper-dialog.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-checkbox/paper-checkbox.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-button/paper-button.html'>
|
||||||
|
|
||||||
|
<dom-module id='hassio-snapshot'>
|
||||||
|
<template>
|
||||||
|
<style include='ha-style'>
|
||||||
|
paper-checkbox {
|
||||||
|
display: block;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
||||||
|
.snapshot-details {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.addon-version {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
.warning,
|
||||||
|
.error {
|
||||||
|
color: var(--google-red-500);
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
paper-dialog {
|
||||||
|
position: absolute !important;
|
||||||
|
bottom: 0; left: 0; right: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<paper-dialog id='dialog' with-backdrop on-iron-overlay-closed='dialogClosed'>
|
||||||
|
<h2>[[computeName(snapshot)]]</h2>
|
||||||
|
<div>
|
||||||
|
<div class='snapshot-details'>
|
||||||
|
[[computeType(snapshot.type)]] ([[computeSize(snapshot.size)]])<br/>
|
||||||
|
[[formatDatetime(snapshot.date)]]
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Home Assistant:
|
||||||
|
<paper-checkbox checked='{{restoreHass}}'>
|
||||||
|
Home Assistant [[snapshot.homeassistant]]
|
||||||
|
</paper-checkbox>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Folders:
|
||||||
|
<template is='dom-repeat' items='[[snapshot.folders]]'>
|
||||||
|
<paper-checkbox checked='{{item.checked}}'>
|
||||||
|
[[item.name]]
|
||||||
|
</paper-checkbox>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<template is='dom-if' if='[[snapshot.addons.length]]'>
|
||||||
|
<div>
|
||||||
|
Add-ons:
|
||||||
|
<template is='dom-repeat' items='[[snapshot.addons]]' sort='sortAddons'>
|
||||||
|
<paper-checkbox checked='{{item.checked}}'>
|
||||||
|
[[item.name]]
|
||||||
|
<span class='addon-version'>([[item.version]])</span>
|
||||||
|
</paper-checkbox>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template is='dom-if' if='[[error]]'>
|
||||||
|
<p class='error'>Error: [[error]]</p>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class='buttons'>
|
||||||
|
<paper-button class='warning' on-tap='deleteTapped'>Delete</paper-button>
|
||||||
|
<paper-button on-tap='partialRestoreTapped'>Partial restore</paper-button>
|
||||||
|
<template is='dom-if' if='[[isFullSnapshot(snapshot.type)]]'>
|
||||||
|
<paper-button on-tap='fullRestoreTapped'>Full restore</paper-button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</paper-dialog>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
class HassioSnapshot extends window.hassMixins.EventsMixin(Polymer.Element) {
|
||||||
|
static get is() { return 'hassio-snapshot'; }
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
hass: Object,
|
||||||
|
snapshotSlug: {
|
||||||
|
type: String,
|
||||||
|
observer: 'computeSnapshot',
|
||||||
|
},
|
||||||
|
snapshot: Object,
|
||||||
|
restoreHass: {
|
||||||
|
type: Boolean,
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
opened: {
|
||||||
|
type: Boolean,
|
||||||
|
observer: 'openedChanged',
|
||||||
|
notify: true,
|
||||||
|
},
|
||||||
|
updateOverview: {
|
||||||
|
type: Boolean,
|
||||||
|
notify: true,
|
||||||
|
},
|
||||||
|
error: String,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
computeSnapshot(snapshotSlug) {
|
||||||
|
this.hass.callApi('get', `hassio/snapshots/${snapshotSlug}/info`)
|
||||||
|
.then((info) => {
|
||||||
|
info.data.folders = this.computeFolders(info.data.folders);
|
||||||
|
info.data.addons = this.computeAddons(info.data.addons);
|
||||||
|
this.snapshot = info.data;
|
||||||
|
}, () => {
|
||||||
|
this.snapshot = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
computeFolders(folders) {
|
||||||
|
const list = [];
|
||||||
|
if (folders.includes('homeassistant')) list.push({ slug: 'homeassistant', name: 'Home Assistant configuration', checked: true });
|
||||||
|
if (folders.includes('ssl')) list.push({ slug: 'ssl', name: 'SSL', checked: true });
|
||||||
|
if (folders.includes('share')) list.push({ slug: 'share', name: 'Share', checked: true });
|
||||||
|
if (folders.includes('addons/local')) list.push({ slug: 'addons/local', name: 'Local add-ons', checked: true });
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
computeAddons(addons) {
|
||||||
|
return addons.map(addon => (
|
||||||
|
{ slug: addon.slug, name: addon.name, version: addon.version, checked: true }));
|
||||||
|
}
|
||||||
|
|
||||||
|
isFullSnapshot(type) {
|
||||||
|
return type === 'full';
|
||||||
|
}
|
||||||
|
|
||||||
|
partialRestoreTapped() {
|
||||||
|
if (!confirm('Are you sure you want to restore this snapshot?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const addons = this.snapshot.addons.filter(addon => addon.checked).map(addon => addon.slug);
|
||||||
|
const folders =
|
||||||
|
this.snapshot.folders.filter(folder => folder.checked).map(folder => folder.slug);
|
||||||
|
|
||||||
|
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/restore/partial`, {
|
||||||
|
homeassistant: this.restoreHass,
|
||||||
|
addons: addons,
|
||||||
|
folders: folders
|
||||||
|
}).then(() => {
|
||||||
|
alert('Snapshot restored!');
|
||||||
|
this.$.dialog.close();
|
||||||
|
}, (error) => {
|
||||||
|
this.error = error.body.message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fullRestoreTapped() {
|
||||||
|
if (!confirm('Are you sure you want to restore this snapshot?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/restore/full`)
|
||||||
|
.then(() => {
|
||||||
|
alert('Snapshot restored!');
|
||||||
|
this.$.dialog.close();
|
||||||
|
}, (error) => {
|
||||||
|
this.error = error.body.message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTapped() {
|
||||||
|
if (!confirm('Are you sure you want to delete this snapshot?')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.hass.callApi('post', `hassio/snapshots/${this.snapshotSlug}/remove`)
|
||||||
|
.then(() => {
|
||||||
|
this.$.dialog.close();
|
||||||
|
this.updateOverview = true;
|
||||||
|
}, (error) => {
|
||||||
|
this.error = error.body.message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
computeName(snapshot) {
|
||||||
|
return snapshot.name || snapshot.slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
computeType(type) {
|
||||||
|
return type === 'full' ? 'Full snapshot' : 'Partial snapshot';
|
||||||
|
}
|
||||||
|
|
||||||
|
computeSize(size) {
|
||||||
|
return Math.ceil(size) + ' MB';
|
||||||
|
}
|
||||||
|
|
||||||
|
sortAddons(a, b) {
|
||||||
|
return a.name < b.name ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatDatetime(datetime) {
|
||||||
|
return new Date(datetime + '+00:00').toLocaleDateString(navigator.language, {
|
||||||
|
weekday: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric',
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: '2-digit'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
openedChanged(opened) {
|
||||||
|
if (opened) this.$.dialog.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogClosed() {
|
||||||
|
this.opened = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customElements.define(HassioSnapshot.is, HassioSnapshot);
|
||||||
|
</script>
|
291
hassio/snapshots/hassio-snapshots.html
Normal file
291
hassio/snapshots/hassio-snapshots.html
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
|
||||||
|
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
|
||||||
|
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
|
||||||
|
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
|
||||||
|
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
|
||||||
|
<link rel='import' href='../../bower_components/paper-radio-group/paper-radio-group.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-radio-button/paper-radio-button.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-checkbox/paper-checkbox.html'>
|
||||||
|
|
||||||
|
<link rel='import' href='../../src/util/hass-mixins.html'>
|
||||||
|
|
||||||
|
<link rel='import' href='../../src/components/hassio-card-content.html'>
|
||||||
|
<link rel='import' href='../../src/resources/hassio-style.html'>
|
||||||
|
<link rel='import' href='./hassio-snapshot.html'>
|
||||||
|
|
||||||
|
<dom-module id="hassio-snapshots">
|
||||||
|
<template>
|
||||||
|
<style include="ha-style hassio-style">
|
||||||
|
paper-checkbox {
|
||||||
|
display: block;
|
||||||
|
margin: 4px 0 4px 48px;
|
||||||
|
}
|
||||||
|
.pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<app-header-layout has-scrolling-region>
|
||||||
|
<app-header slot="header" fixed>
|
||||||
|
<app-toolbar>
|
||||||
|
<paper-icon-button
|
||||||
|
icon='mdi:arrow-left'
|
||||||
|
on-tap='_backTapped'
|
||||||
|
></paper-icon-button>
|
||||||
|
<div main-title>Snapshots</div>
|
||||||
|
<paper-icon-button
|
||||||
|
icon="mdi:refresh"
|
||||||
|
on-tap="_refreshTapped"
|
||||||
|
></paper-icon-button>
|
||||||
|
</app-toolbar>
|
||||||
|
</app-header>
|
||||||
|
|
||||||
|
<div class='content'>
|
||||||
|
<div class='card-group'>
|
||||||
|
<div class='title'>
|
||||||
|
New snapshot
|
||||||
|
<div class='description'>
|
||||||
|
Snapshots allow you to easily backup and
|
||||||
|
restore all data of your Hass.io instance.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<paper-card>
|
||||||
|
<div class='card-content'>
|
||||||
|
<paper-input autofocus label='Name' value='{{snapshotName}}'>
|
||||||
|
</paper-input>
|
||||||
|
<label id='lbltype'>Type:</label>
|
||||||
|
<paper-radio-group selected='{{snapshotType}}' aria-labelledby='lbltype' on-paper-radio-group-changed='typeChanged'>
|
||||||
|
<paper-radio-button name='full'>
|
||||||
|
Full snapshot
|
||||||
|
</paper-radio-button>
|
||||||
|
<paper-radio-button name='partial'>
|
||||||
|
Partial snapshot
|
||||||
|
</paper-radio-button>
|
||||||
|
</paper-radio-group>
|
||||||
|
<div id='folders' class='hidden'>
|
||||||
|
Folders:
|
||||||
|
<template is='dom-repeat' items='[[folderList]]'>
|
||||||
|
<paper-checkbox checked='{{item.checked}}'>
|
||||||
|
[[item.name]]
|
||||||
|
</paper-checkbox>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div id='addons' class='hidden'>
|
||||||
|
Add-ons:
|
||||||
|
<template is='dom-repeat' items='[[addonList]]' sort='sortAddons'>
|
||||||
|
<paper-checkbox checked='{{item.checked}}'>
|
||||||
|
[[item.name]]
|
||||||
|
</paper-checkbox>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='card-actions'>
|
||||||
|
<paper-button disabled='[[creatingSnapshot]]' on-tap='createSnapshot'>Create</paper-button>
|
||||||
|
<template is='dom-if' if='[[error]]'>
|
||||||
|
<p class='error'>[[error]]</p>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</paper-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='card-group'>
|
||||||
|
<div class='title'>Available snapshots</div>
|
||||||
|
<template is='dom-if' if='[[!snapshots.length]]'>
|
||||||
|
<paper-card>
|
||||||
|
<div class='card-content'>You don't have any snapshots yet.</div>
|
||||||
|
</paper-card>
|
||||||
|
</template>
|
||||||
|
<template is='dom-repeat' items='[[snapshots]]' as='snapshot' sort='sortSnapshots'>
|
||||||
|
<paper-card class='pointer' on-click='snapshotTapped'>
|
||||||
|
<div class='card-content'>
|
||||||
|
<hassio-card-content
|
||||||
|
title='[[computeName(snapshot)]]'
|
||||||
|
description='[[computeType(snapshot.type)]]'
|
||||||
|
datetime='[[snapshot.date]]+00:00'
|
||||||
|
icon='[[computeIcon(snapshot.type)]]'
|
||||||
|
icon-class='snapshot'
|
||||||
|
></hassio-card-content>
|
||||||
|
</div>
|
||||||
|
</paper-card>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</app-header-layout>
|
||||||
|
<hassio-snapshot
|
||||||
|
hass='[[hass]]'
|
||||||
|
snapshot-slug='[[selectedSnapshot]]'
|
||||||
|
opened='{{dialogOpened}}'
|
||||||
|
update-overview='{{updateOverview}}'
|
||||||
|
></hassio-snapshot>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
class HassioSnapshots extends window.hassMixins.EventsMixin(Polymer.Element) {
|
||||||
|
static get is() { return 'hassio-snapshots'; }
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
hass: Object,
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
observer: 'visibleChanged',
|
||||||
|
},
|
||||||
|
snapshotName: String,
|
||||||
|
snapshotType: {
|
||||||
|
type: String,
|
||||||
|
value: 'full',
|
||||||
|
},
|
||||||
|
snapshots: {
|
||||||
|
type: Array,
|
||||||
|
value: [],
|
||||||
|
},
|
||||||
|
installedAddons: {
|
||||||
|
type: Array,
|
||||||
|
observer: 'installedAddonsChanged',
|
||||||
|
},
|
||||||
|
addonList: Array,
|
||||||
|
folderList: {
|
||||||
|
type: Array,
|
||||||
|
value: [
|
||||||
|
{ slug: 'homeassistant', name: 'Home Assistant configuration', checked: true },
|
||||||
|
{ slug: 'ssl', name: 'SSL', checked: true },
|
||||||
|
{ slug: 'share', name: 'Share', checked: true },
|
||||||
|
{ slug: 'addons/local', name: 'Local add-ons', checked: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
selectedSnapshot: String,
|
||||||
|
creatingSnapshot: Boolean,
|
||||||
|
dialogOpened: Boolean,
|
||||||
|
updateOverview: {
|
||||||
|
type: Boolean,
|
||||||
|
observer: 'updateOverviewChanged',
|
||||||
|
},
|
||||||
|
error: String,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ready() {
|
||||||
|
super.ready();
|
||||||
|
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
|
||||||
|
}
|
||||||
|
|
||||||
|
visibleChanged(visible) {
|
||||||
|
if (visible) {
|
||||||
|
this.updateSnapshots();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apiCalled(ev) {
|
||||||
|
if (ev.detail.success) {
|
||||||
|
this.updateSnapshots();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSnapshots() {
|
||||||
|
this.hass.callApi('get', 'hassio/snapshots')
|
||||||
|
.then((result) => {
|
||||||
|
this.snapshots = result.data.snapshots;
|
||||||
|
}, (error) => {
|
||||||
|
this.error = error.message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createSnapshot() {
|
||||||
|
this.creatingSnapshot = true;
|
||||||
|
let name = this.snapshotName;
|
||||||
|
if (!name || name.length === 0) {
|
||||||
|
name = new Date().toLocaleDateString(navigator.language, {
|
||||||
|
weekday: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'short',
|
||||||
|
day: 'numeric' });
|
||||||
|
}
|
||||||
|
let data;
|
||||||
|
let path;
|
||||||
|
if (this.snapshotType === 'full') {
|
||||||
|
data = { name: name };
|
||||||
|
path = 'hassio/snapshots/new/full';
|
||||||
|
} else {
|
||||||
|
const addons = this.addonList.filter(addon => addon.checked).map(addon => addon.slug);
|
||||||
|
const folders = this.folderList.filter(folder => folder.checked).map(folder => folder.slug);
|
||||||
|
|
||||||
|
data = { name: name, folders: folders, addons: addons };
|
||||||
|
path = 'hassio/snapshots/new/partial';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hass.callApi('post', path, data)
|
||||||
|
.then(() => {
|
||||||
|
this.creatingSnapshot = false;
|
||||||
|
this.fire('hass-api-called', { success: true });
|
||||||
|
}, (error) => {
|
||||||
|
this.creatingSnapshot = false;
|
||||||
|
this.error = error.message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
installedAddonsChanged(addons) {
|
||||||
|
this.addonList = addons.map(addon => ({ slug: addon.slug, name: addon.name, checked: true }));
|
||||||
|
}
|
||||||
|
|
||||||
|
sortAddons(a, b) {
|
||||||
|
return a.name < b.name ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sortSnapshots(a, b) {
|
||||||
|
return a.date < b.date ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
computeName(snapshot) {
|
||||||
|
return snapshot.name || snapshot.slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
computeType(type) {
|
||||||
|
return type === 'full' ? 'Full snapshot' : 'Partial snapshot';
|
||||||
|
}
|
||||||
|
|
||||||
|
computeIcon(type) {
|
||||||
|
return type === 'full' ? 'mdi:package-variant-closed' : 'mdi:package-variant';
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshotTapped(ev) {
|
||||||
|
this.selectedSnapshot = ev.model.snapshot.slug;
|
||||||
|
this.dialogOpened = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
typeChanged() {
|
||||||
|
if (this.snapshotType === 'full') {
|
||||||
|
this.$.folders.classList.add('hidden');
|
||||||
|
this.$.addons.classList.add('hidden');
|
||||||
|
} else {
|
||||||
|
this.$.folders.classList.remove('hidden');
|
||||||
|
this.$.addons.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOverviewChanged(update) {
|
||||||
|
if (update) {
|
||||||
|
this.updateSnapshots();
|
||||||
|
this.updateOverview = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
backTapped() {
|
||||||
|
history.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshTapped() {
|
||||||
|
this.hass.callApi('post', 'hassio/snapshots/reload')
|
||||||
|
.then(() => {
|
||||||
|
this.updateSnapshots();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define(HassioSnapshots.is, HassioSnapshots);
|
||||||
|
</script>
|
Loading…
x
Reference in New Issue
Block a user