iobroker.backitup
Version:
ioBroker.backitup allows you to backup and restore your ioBroker installation and other systems, such as databases, Zigbee, scripts and many more.
417 lines (378 loc) • 15.7 kB
JavaScript
/*global $, location, socket, document, window, io, alert, load, systemDictionary, systemLang, translateAll*/
var path = location.pathname;
var parts = path.split('/');
parts.splice(-3);
const socket = io.connect('/', { path: parts.join('/') + '/socket.io' });
var query = (window.location.search || '').replace(/^\?/, '').replace(/#.*$/, '');
var args = {};
let theme = null;
// parse parameters
query.trim().split('&').filter(function (t) { return t.trim(); }).forEach(function (b, i) {
const parts = b.split('=');
if (!i && parts.length === 1 && !isNaN(parseInt(b, 10))) {
args.instance = parseInt(b, 10);
}
var name = parts[0];
args[name] = parts.length === 2 ? parts[1] : true;
if (name === 'instance') {
args.instance = parseInt(args.instance, 10) || 0;
}
if (args[name] === 'true') {
args[name] = true;
} else if (args[name] === 'false') {
args[name] = false;
}
});
var instance = args.instance;
let common = null; // common information of adapter
const host = null; // host object on which the adapter runs
const changed = false;
let systemConfig;
let certs = [];
let adapter = '';
const onChangeSupported = false;
var isMaterialize = true;
const tmp = window.location.pathname.split('/');
adapter = tmp[tmp.length - 2];
const id = 'system.adapter.' + adapter + '.' + instance;
$(document).ready(function () {
'use strict';
loadSystemConfig(function () {
if (typeof translateAll === 'function') translateAll();
loadSettings(prepareTooltips);
});
});
function currentTheme() {
return theme;
}
// Read language settings
function loadSystemConfig(callback) {
socket.emit('getObject', 'system.config', function (err, res) {
if (!err && res && res.common) {
systemLang = res.common.language || systemLang;
systemConfig = res;
}
socket.emit('getObject', 'system.certificates', function (err, res) {
if (!err && res) {
if (res.native && res.native.certificates) {
certs = [];
for (const c in res.native.certificates) {
if (res.native.certificates.hasOwnProperty(c) && !res.native.certificates[c]) continue;
const _cert = {
name: c,
type: (res.native.certificates[c].substring(0, '-----BEGIN RSA PRIVATE KEY'.length) === '-----BEGIN RSA PRIVATE KEY' || res.native.certificates[c].substring(0, '-----BEGIN PRIVATE KEY'.length) === '-----BEGIN PRIVATE KEY') ? 'private' : 'public'
};
if (_cert.type === 'public') {
const m = res.native.certificates[c].split('-----END CERTIFICATE-----');
let count = 0;
for (let _m = 0; _m < m.length; _m++) {
if (m[_m].replace(/[\r\n|\r|\n]+/, '').trim()) count++;
}
if (count > 1) _cert.type = 'chained';
}
certs.push(_cert);
}
}
}
if (callback) callback();
});
});
}
function loadSettings(callback) {
socket.emit('getObject', id, function (err, res) {
if (!err && res && res.native) {
$('.adapter-instance').html(adapter + '.' + instance);
$('.adapter-config').html('system.adapter.' + adapter + '.' + instance);
common = res.common;
res.common && res.common.name && $('.adapter-name').html(res.common.name);
if (typeof load === 'undefined') {
alert('Please implement save function in your admin/index.html');
} else {
// decode all native attributes listed in res.encryptedNative
if (res.encryptedNative && typeof res.encryptedNative === 'object' && res.encryptedNative instanceof Array) {
for (var i = 0; i < res.encryptedNative.length; i++) {
if (res.native[res.encryptedNative[i]]) {
res.native[res.encryptedNative[i]] = decrypt(res.native[res.encryptedNative[i]]);
}
}
} else {
var idx = supportedFeatures.indexOf('ADAPTER_AUTO_DECRYPT_NATIVE');
if (idx !== -1) {
// if no encryptedNative exists the feature is irrelevant, remove for compatibility reasons
supportedFeatures.splice(idx, 1);
}
}
// detect, that we are now in react container (themeNames = ['dark', 'blue', 'colored', 'light'])
//query += '&react=dark'; // this is only for theme testing
const _query = query.split('&');
for (var q = 0; q < _query.length; q++) {
if (_query[q].indexOf('react=') !== -1) {
$('.adapter-container').addClass('react-' + _query[q].substring(6));
theme = 'react-' + _query[q].substring(6);
}
}
load(res.native, onChange);
// init selects
if (isMaterialize) {
$('select').select();
M.updateTextFields();
// workaround for materialize checkbox problem
$('input[type="checkbox"]+span').off('click').on('click', function (event) {
var $input = $(this).prev();
if (!$input.prop('disabled')) {
$input.prop('checked', !$input.prop('checked')).trigger('change');
// prevent propagation to prevent original handling from reverting our value change
event.preventDefault();
event.stopImmediatePropagation();
}
});
}
}
if (typeof callback === 'function') {
callback();
}
} else {
if (typeof callback === 'function') {
callback();
}
alert('error loading settings for ' + id + '\n\n' + err);
}
});
}
function confirmMessage(message, title, icon, buttons, callback) {
if (!isMaterialize) {
return confirmMessageJQ(message, title, icon, buttons, callback);
}
var $dialogConfirm;
// noinspection JSJQueryEfficiency
$dialogConfirm = $('#dialog-confirm');
if (!$dialogConfirm.length) {
$('body').append(
`<div class="${theme ? 'm ' + theme : 'm'}"><div id="dialog-confirm" class="modal modal-fixed-footer">` +
' <div class="modal-content">' +
' <h6 class="dialog-title title"></h6>' +
' <p><i class="large material-icons dialog-icon"></i><span class="dialog-text"></span></p>' +
' </div>' +
' <div class="modal-footer">' +
' </div>' +
'</div></div>'
);
$dialogConfirm = $('#dialog-confirm');
}
if (typeof buttons === 'function') {
callback = buttons;
$dialogConfirm.find('.modal-footer').html(
'<a class="modal-action modal-close waves-effect waves-green btn-flat translate" data-result="true">' + _('Ok') + '</a>' +
'<a class="modal-action modal-close waves-effect waves-green btn-flat translate">' + _('Cancel') + '</a>');
$dialogConfirm.find('.modal-footer .modal-action').on('click', function () {
var cb = $dialogConfirm.data('callback');
cb && cb($(this).data('result'));
});
} else if (typeof buttons === 'object') {
var tButtons = '';
for (var b = buttons.length - 1; b >= 0; b--) {
tButtons += '<a class="modal-action modal-close waves-effect waves-green btn-flat translate" data-id="' + b + '">' + buttons[b] + '</a>';
}
$dialogConfirm.find('.modal-footer').html(tButtons);
$dialogConfirm.find('.modal-footer .modal-action').on('click', function () {
var cb = $dialogConfirm.data('callback');
cb && cb($(this).data('id'));
});
}
$dialogConfirm.find('.dialog-title').text(title || _('Please confirm'));
if (icon) {
$dialogConfirm.find('.dialog-icon')
.show()
.html(icon);
} else {
$dialogConfirm.find('.dialog-icon').hide();
}
if (title) {
$dialogConfirm.find('.dialog-title').html(title).show();
} else {
$dialogConfirm.find('.dialog-title').hide();
}
$dialogConfirm.find('.dialog-text').html(message);
$dialogConfirm.data('callback', callback);
$dialogConfirm.modal({
dismissible: false
}).modal('open');
}
function showError(error) {
showMessage(_(error), _('Error'), 'error_outline');
}
function showToast(parent, message, icon, duration, isError, classes) {
if (typeof parent === 'string') {
classes = isError;
isError = duration;
icon = message;
message = parent;
parent = null;
}
if (parent && parent instanceof jQuery) {
parent = parent[0];
}
classes = classes || [];
if (typeof classes === 'string') {
classes = [classes];
}
isError && classes.push('dropZone-error');
M.toast({
parentSelector: parent || $('body')[0],
html: message + (icon ? '<i class="material-icons">' + icon + '</i>' : ''),
displayLength: duration || 3000,
classes: classes
});
}
function getState(id, callback) {
socket.emit('getState', id, function (err, res) {
if (!err && res) {
callback && callback(err, res);
} else {
callback && callback(null);
}
});
}
function getAdapterInstances(_adapter, callback) {
if (typeof _adapter === 'function') {
callback = _adapter;
_adapter = null;
}
socket.emit('getObjectView', 'system', 'instance', { startkey: 'system.adapter.' + (_adapter || adapter), endkey: 'system.adapter.' + (_adapter || adapter) + '.\u9999' }, function (err, doc) {
if (err) {
callback && callback([]);
} else {
if (doc.rows.length === 0) {
callback && callback([]);
} else {
var res = [];
for (var i = 0; i < doc.rows.length; i++) {
res.push(doc.rows[i].value);
}
callback && callback(res);
}
}
});
}
function getIsAdapterAlive(adapter, callback) {
if (typeof adapter === 'function') {
callback = adapter;
adapter = null;
}
getState(id + '.alive', function (err, obj) {
if (!obj || !obj.val) {
callback(false);
} else {
callback(true);
}
});
}
function prepareTooltips() {
$('.admin-icon').each(function () {
let id = $(this).data('id');
if (!id) {
let $prev = $(this).prev();
let $input = $prev.find('input');
if (!$input.length) $input = $prev.find('select');
if (!$input.length) $input = $prev.find('textarea');
if (!$input.length) {
$prev = $prev.parent();
$input = $prev.find('input');
if (!$input.length) $input = $prev.find('select');
if (!$input.length) $input = $prev.find('textarea');
}
if ($input.length) id = $input.attr('id');
}
if (!id) return;
let tooltip = '';
if (systemDictionary['tooltip_' + id]) {
tooltip = systemDictionary['tooltip_' + id][systemLang] || systemDictionary['tooltip_' + id].en;
}
let icon = '';
let link = $(this).data('link');
if (link) {
if (link === true) {
if (common.readme) {
link = common.readme + '#' + id;
} else {
link = 'https://github.com/ioBroker/ioBroker.' + common.name + '#' + id;
}
}
if (!link.match('^https?:\/\/')) {
if (common.readme) {
link = common.readme + '#' + link;
} else {
link = 'https://github.com/ioBroker/ioBroker.' + common.name + '#' + link;
}
}
icon += '<a class="admin-tooltip-link" target="config_help" href="' + link + '" title="' + (tooltip || systemDictionary.htooltip[systemLang]) + '"><img class="admin-tooltip-icon" src="../../img/info.png" /></a>';
} else if (tooltip) {
icon += '<img class="admin-tooltip-icon" title="' + tooltip + '" src="../../img/info.png"/>';
}
if (icon) {
$(this).html(icon);
}
});
$('.admin-text').each(function () {
let id = $(this).data('id');
if (!id) {
let $prev = $(this).prev();
let $input = $prev.find('input');
if (!$input.length) $input = $prev.find('select');
if (!$input.length) $input = $prev.find('textarea');
if (!$input.length) {
$prev = $prev.parent();
$input = $prev.find('input');
if (!$input.length) $input = $prev.find('select');
if (!$input.length) $input = $prev.find('textarea');
}
if ($input.length) id = $input.attr('id');
}
if (!id) return;
// check if translation for this exist
if (systemDictionary['info_' + id]) {
$(this).html('<span class="admin-tooltip-text">' + (systemDictionary['info_' + id][systemLang] || systemDictionary['info_' + id].en) + '</span>');
}
});
}
function sendTo(_adapter_instance, command, message, callback) {
socket.emit('sendTo', (_adapter_instance || adapter + '.' + instance), command, message, callback);
}
function sendToHost(host, command, message, callback) {
socket.emit('sendToHost', host || common.host, command, message, callback);
}
function onChange(isChanged) {
//
}
function showMessage(message, title, icon) {
var $dialogMessage;
// noinspection JSJQueryEfficiency
$dialogMessage = $('#dialog-message');
if (!$dialogMessage.length) {
$('body').append(
`<div class="${theme ? 'm ' + theme : 'm'}"><div id="dialog-message" class="modal modal-fixed-footer">` +
' <div class="modal-content">' +
' <h6 class="dialog-title title"></h6>' +
' <p><i class="large material-icons dialog-icon"></i><span class="dialog-text"></span></p>' +
' </div>' +
' <div class="modal-footer">' +
' <a class="modal-action modal-close waves-effect waves-green btn-flat translate">Ok</a>' +
' </div>' +
'</div></div>');
$dialogMessage = $('#dialog-message');
}
if (icon) {
$dialogMessage.find('.dialog-icon')
.show()
.html(icon);
} else {
$dialogMessage.find('.dialog-icon').hide();
}
if (title) {
$dialogMessage.find('.dialog-title').html(title).show();
} else {
$dialogMessage.find('.dialog-title').hide();
}
$dialogMessage.find('.dialog-text').html(message);
$dialogMessage.modal().modal('open');
}