UNPKG

yunkong2.admin

Version:

The adapter opens a webserver for the yunkong2 admin UI.

1,156 lines (1,051 loc) 85.5 kB
var path = location.pathname; var parts = path.split('/'); parts.splice(-3); if (location.pathname.match(/^\/admin\//)) { parts = []; } var systemConfig; var socket = io.connect('/', {path: parts.join('/') + '/socket.io'}); var instance = window.location.search.slice(1); var common = null; // common information of adapter var host = null; // host object on which the adapter runs var changed = false; var certs = []; var adapter = ''; var onChangeSupported = false; var isMaterialize = false; var ___onChange = null; function preInit () { 'use strict'; var tmp = window.location.pathname.split('/'); adapter = tmp[tmp.length - 2]; var id = 'system.adapter.' + adapter + '.' + instance; // Extend dictionary with standard words for adapter if (typeof systemDictionary === 'undefined') systemDictionary = {}; systemDictionary.save = {"en": "Save", "cn": "保存", "nl": "Opslaan", "es": "Salvar", "pt": "Salve", "it": "Salvare", "de": "Speichern", "pl": "Zapisać", "ru": "Сохранить"}; systemDictionary.saveclose = {"en": "Save and close", "cn": "保存并退出", "nl": "Opslaan en afsluiten","es": "Guardar y cerrar", "pt": "Salvar e fechar", "it": "Salva e chiudi", "de": "Speichern und schließen", "pl": "Zapisz i zamknij", "ru": "Сохранить и выйти"}; systemDictionary.none = {"en": "none", "cn": "none", "nl": "geen", "es": "ninguna", "pt": "Nenhum", "it": "nessuna", "de": "keins", "pl": "Żaden", "ru": ""}; systemDictionary.nonerooms = {"en": "", "cn": "", "nl": "", "es": "", "pt": "", "it": "", "de": "", "pl": "", "ru": ""}; systemDictionary.nonefunctions = {"en": "", "cn": "", "nl": "", "es": "", "pt": "", "it": "", "de": "", "pl": "", "ru": ""}; systemDictionary.all = {"en": "all", "cn": "全部", "nl": "alle", "es": "todas", "pt": "todos", "it": "tutti", "de": "alle", "pl": "wszystko", "ru": "все"}; systemDictionary['Device list'] = {"en": "Device list", "cn": "设备列表", "nl": "Lijst met apparaten", "es": "Lista de dispositivos", "pt": "Lista de dispositivos", "it": "Elenco dispositivi", "de": "Geräteliste", "pl": "Lista urządzeń", "ru": "Список устройств"}; systemDictionary['new device'] = {"en": "new device", "cn": "新设备", "nl": "nieuw apparaat", "es": "Nuevo dispositivo", "pt": "Novo dispositivo", "it": "nuovo dispositivo", "de": "Neues Gerät", "pl": "nowe urządzenie", "ru": "Новое устройство"}; systemDictionary.edit = {"en": "edit", "cn": "编辑", "nl": "Bewerk", "es": "editar", "pt": "editar", "it": "modificare", "de": "Ändern", "pl": "edytować", "ru": "Изменить"}; systemDictionary.delete = {"en": "delete", "cn": "删除", "nl": "Delete", "es": "borrar", "pt": "excluir", "it": "Elimina", "de": "Löschen", "pl": "kasować", "ru": "Удалить"}; systemDictionary.pair = {"en": "pair", "cn": "paire", "nl": "paar", "es": "par", "pt": "par", "it": "paio", "de": "Verbinden", "pl": "para", "ru": "Связать"}; systemDictionary.unpair = {"en": "unpair", "cn": "unpair", "nl": "Unpair", "es": "desvincular", "pt": "unpair", "it": "Disaccoppia", "de": "Trennen", "pl": "unpair", "ru": "Разорвать связь"}; systemDictionary.ok = {"en": "Ok", "cn": "确认", "nl": "OK", "es": "De acuerdo", "pt": "Está bem", "it": "Ok", "de": "Ok", "pl": "Ok", "ru": "Ok"}; systemDictionary.cancel = {"en": "Cancel", "cn": "取消", "nl": "Annuleer", "es": "Cancelar", "pt": "Cancelar", "it": "Annulla", "de": "Abbrechen", "pl": "Anuluj", "ru": "Отмена"}; systemDictionary.Message = {"en": "Message", "cn": "信息", "nl": "Bericht", "es": "Mensaje", "pt": "Mensagem", "it": "Messaggio", "de": "Mitteilung", "pl": "Wiadomość", "ru": "Сообщение"}; systemDictionary.close = {"en": "Close", "cn": "关闭", "nl": "Dichtbij", "es": "Cerca", "pt": "Fechar", "it": "Vicino", "de": "Schließen", "pl": "Blisko", "ru": "Закрыть"}; systemDictionary.htooltip = {"en": "Click for help", "cn": "帮助", "nl": "Klik voor hulp", "es": "Haz clic para obtener ayuda", "pt": "Clique para ajuda", "it": "Fai clic per chiedere aiuto", "de": "Anklicken", "pl": "Kliknij, aby uzyskać pomoc", "ru": "Перейти по ссылке"}; systemDictionary.saveConfig = { "en": "Save configuration to file", "cn": "Save configuration to file" }; systemDictionary.loadConfig = { "en": "Load configuration from file", "cn": "Load configuration from file" }; systemDictionary.otherConfig = { "en": "Configuration from other adapter %s", "cn": "Configuration from other adapter %s" }; systemDictionary.invalidConfig = { "en": "Invalid JSON file" }; systemDictionary.configLoaded = { "en": "Configuration was successfully loaded", "cn": "Configuration was successfully loaded" }; systemDictionary.maxTableRaw = { "en": "Maximum number of allowed raws", "cn": "Maximum number of allowed raws" }; systemDictionary.maxTableRawInfo = {"en": "Warning", "cn": "提示"}; systemDictionary["Main settings"] = { "en": "Main settings", "cn": "基本设置" }; systemDictionary["Let's Encrypt SSL"] = { "en": "Let's Encrypt Certificates", "cn": "Let's Encrypt Certificates" }; systemDictionary["Please activate secure communication"] = { "en": "Please activate secure communication", "cn": "Please activate secure communication" }; //socket.on('connection', function () { loadSystemConfig(function () { if (typeof translateAll === 'function') translateAll(); loadSettings(prepareTooltips); }); //}); var $body = $('body'); $body.wrapInner('<div class="adapter-body"></div>'); /*$body.prepend('<div class="header ui-tabs-nav ui-widget ui-widget-header ui-corner-all" style="padding: 2px" >' + '<button id="save" class="translateB">save</button>&nbsp;' + '<button id="saveclose" class="translateB">saveclose</button>&nbsp;' + '<button id="close" class="translateB" style="float: right;">cancel</button>&nbsp;' + '</div>'); */ $body.append( '<div class="m"><nav class="dialog-config-buttons nav-wrapper footer">' + ' <a class="btn btn-active btn-save"><i class="material-icons left">save</i><span class="translate">save</span></a> ' + ' <a class="btn btn-save-close"><i class="material-icons left">save</i><i class="material-icons left">close</i><span class="translate">saveclose</span></a> ' + ' <a class="btn btn-cancel"><i class="material-icons left">close</i><span class="translate">close</span></a>' + '</nav></div>'); var $navButtons = $('.dialog-config-buttons'); $navButtons.find('.btn-save').on('click', function () { if (typeof save === 'undefined') { alert('Please implement save function in your admin/index.html'); return; } save(function (obj, common, redirect) { if (redirect && parent && parent.adapterRedirect) { parent.adapterRedirect(redirect); } saveSettings(obj, common); }); }); $navButtons.find('.btn-save-close').on('click', function () { if (typeof save === 'undefined') { alert('Please implement save function in your admin/index.html'); return; } save(function (obj, common, redirect) { if (redirect && parent && parent.adapterRedirect) { parent.adapterRedirect(redirect); } saveSettings(obj, common, function () { // window.close(); if (typeof parent !== 'undefined' && parent && parent.$iframeDialog && typeof parent.$iframeDialog.close === 'function') { parent.$iframeDialog.close(); } }); }); }); $navButtons.find('.btn-cancel').on('click', function () { if (typeof parent !== 'undefined' && parent && parent.$iframeDialog && typeof parent.$iframeDialog.close === 'function') { parent.$iframeDialog.close(); } }); function saveSettings(native, common, callback) { if (typeof common === 'function') { callback = common; common = null; } socket.emit('getObject', id, function (err, oldObj) { if (!oldObj) oldObj = {}; for (var a in native) { if (native.hasOwnProperty(a)) { oldObj.native[a] = native[a]; } } if (common) { for (var b in common) { if (common.hasOwnProperty(b)) { oldObj.common[b] = common[b]; } } } if (onChangeSupported) { $navButtons.find('.btn-save').addClass('disabled'); $navButtons.find('.btn-save-close').addClass('disabled'); $navButtons.find('.btn-cancel').find('span').html(_('close')); } socket.emit('setObject', id, oldObj, function (err) { if (err) { showMessage(err, _('Error'), 'alert'); return; } changed = false; if (callback) callback(); }); }); } // 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 (var c in res.native.certificates) { if (!res.native.certificates.hasOwnProperty(c) || !res.native.certificates[c]) continue; // If it is filename, it could be everything if (res.native.certificates[c].length < 700 && (res.native.certificates[c].indexOf('/') !== -1 || res.native.certificates[c].indexOf('\\') !== -1)) { var __cert = { name: c, type: '' }; if (c.toLowerCase().indexOf('private') !== -1) { __cert.type = 'private'; } else if (res.native.certificates[c].toLowerCase().indexOf('private') !== -1) { __cert.type = 'private'; } else if (c.toLowerCase().indexOf('public') !== -1) { __cert.type = 'public'; } else if (res.native.certificates[c].toLowerCase().indexOf('public') !== -1) { __cert.type = 'public'; } certs.push(__cert); continue; } var _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') { var m = res.native.certificates[c].split('-----END CERTIFICATE-----'); var count = 0; for (var _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(); }); }); } // callback if something changed function onChange(isChanged) { onChangeSupported = true; if (typeof isChanged === 'boolean' && isChanged === false) { changed = false; $navButtons.find('.btn-save').addClass('disabled'); $navButtons.find('.btn-save-close').addClass('disabled'); $navButtons.find('.btn-cancel').find('span').html(_('close')); } else { changed = true; $navButtons.find('.btn-save').removeClass('disabled'); $navButtons.find('.btn-save-close').removeClass('disabled'); $navButtons.find('.btn-cancel').find('span').html(_('cancel')); } } 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; if (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 { 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 () { var $input = $(this).prev(); if (!$input.prop('disabled')) { $input.prop('checked', !$input.prop('checked')).trigger('change'); } }); } } if (typeof callback === 'function') { callback(); } } else { if (typeof callback === 'function') { callback(); } alert('error loading settings for ' + id + '\n\n' + err); } }); } ___onChange = onChange; } $(document).ready(function () { 'use strict'; if (window.location.pathname.indexOf('/index_m.html') === -1) { // load materialize var cssLink = document.createElement('link'); cssLink.href = '../../lib/css/materialize.css'; cssLink.type = 'text/css'; cssLink.rel = 'stylesheet'; cssLink.media = 'screen,print'; document.getElementsByTagName('head')[0].appendChild(cssLink); // load materialize.js var jsLink = document.createElement('script'); jsLink.onload = preInit; jsLink.src = '../../lib/js/materialize.js'; document.head.appendChild(jsLink); } else { isMaterialize = true; preInit(); } }); function handleFileSelect(evt) { var f = evt.target.files[0]; if (f) { var r = new FileReader(); r.onload = function(e) { var contents = e.target.result; try { var json = JSON.parse(contents); if (json.native && json.common) { if (json.common.name !== common.name) { showError(_('otherConfig', json.common.name)); } else { load(json.native, ___onChange); // init selects if (isMaterialize) { $('select').select(); M.updateTextFields(); // workaround for materialize checkbox problem $('input[type="checkbox"]+span').off('click').on('click', function () { var $input = $(this).prev(); if (!$input.prop('disabled')) { $input.prop('checked', !$input.prop('checked')).trigger('change'); } }); } ___onChange(); showToast(null, _('configLoaded')); } } else { showError(_('invalidConfig')); } } catch (e) { showError(e.toString()); } }; r.readAsText(f); } else { alert('Failed to open JSON File'); } } function generateFile(filename, obj) { var el = document.createElement('a'); el.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(obj, null, 2))); el.setAttribute('download', filename); el.style.display = 'none'; document.body.appendChild(el); el.click(); document.body.removeChild(el); } function prepareTooltips() { if (isMaterialize) { // init tabs $('.tabs').mtabs(); var buttonsText = ''; if (common && common.readme) { buttonsText += ' <a class="btn-floating btn-small waves-effect waves-light" href="' + common.readme +'" target="_blank">' + ' <i class="material-icons">live_help</i>' + ' </a>'; } buttonsText += ' <a class="btn-floating btn-small waves-effect waves-light adapter-config-load" title="' + _('loadConfig') + '">' + ' <i class="material-icons">file_upload</i>' + ' </a>'; buttonsText += ' <a class="btn-floating btn-small waves-effect waves-light adapter-config-save" title="' + _('saveConfig') + '">' + ' <i class="material-icons">file_download</i>' + ' </a>'; if (buttonsText) { // add help link after logo var $logo = $('.logo').first().parent(); if ($logo.length) { $('<div class="col s6 help-link">' + buttonsText + '</div>').insertAfter($logo); } $('.adapter-config-load').click(function () { var input = document.createElement('input'); input.setAttribute('type', 'file'); input.setAttribute('id', 'files'); input.setAttribute('opacity', 0); input.addEventListener('change', function (e) { handleFileSelect(e, function () {}); }, false); (input.click)(); }); $('.adapter-config-save').click(function () { save(function (native, cmn) { var result = { _id: 'system.adapter.' + common.name + '.' + instance, common: JSON.parse(JSON.stringify(common)), native: native }; // remove unimportant information if (result.common.news) { delete result.common.news; } if (result.common.titleLang) { delete result.common.titleLang; } if (result.common.desc) { delete result.common.desc; } if (cmn) { for (var b in cmn) { if (cmn.hasOwnProperty(b)) { result.common[b] = cmn[b]; } } } //window.open('data:application/yunkong2; content-disposition=attachment; filename=' + result._id + '.json,' + JSON.stringify(result, null, 2)); generateFile(result._id + '.json', result); }); }) } $('.value').each(function () { var $this = $(this); // replace all labels after checkboxes to span (bug in materialize) if ($this.attr('type') === 'checkbox') { $this.addClass('filled-in'); var $label = $this.next(); if ($label.prop('tagName') === 'LABEL') { $label.replaceWith('<span style="' + ($label.attr('style') || '') + '" class="' + ($label.attr('class') || '') + '">' + $label.html() +'</span>'); $label = $this.next(); } $label.off('click').on('click', function () { var $input = $(this).prev(); if (!$input.prop('disabled')) { $input.prop('checked', !$input.prop('checked')).trigger('change'); } }); } var id = $this.data('id'); var tooltip = ''; if (systemDictionary['tooltip_' + id]) { tooltip = systemDictionary['tooltip_' + id][systemLang] || systemDictionary['tooltip_' + id].en; } var link = $this.data('link'); if (link && common) { if (link === true) { if (common.readme) { link = common.readme + '#' + id; } else { link = 'https://github.com/yunkong2/yunkong2.' + common.name + '#' + id; } } if (!link.match('^https?:\/\/')) { if (common.readme) { link = common.readme + '#' + link; } else { link = 'https://github.com/yunkong2/yunkong2.' + common.name + '#' + link; } } } if (link) { $('<a class="tooltip" href="' + link + '" title="' + (tooltip || systemDictionary.htooltip[systemLang]) + '" target="_blank"><i class="material-icons tooltip">live_help</i></a>').insertBefore($this); } else if (tooltip) { $('<i class="material-icons tooltip" title="' + tooltip + '">help_outline</i>').insertBefore($this); } }); } else { $('.admin-icon').each(function () { var id = $(this).data('id'); if (!id) { var $prev = $(this).prev(); var $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; var tooltip = ''; if (systemDictionary['tooltip_' + id]) { tooltip = systemDictionary['tooltip_' + id][systemLang] || systemDictionary['tooltip_' + id].en; } var icon = ''; var link = $(this).data('link'); if (link && common) { if (link === true) { if (common.readme) { link = common.readme + '#' + id; } else { link = 'https://github.com/yunkong2/yunkong2.' + common.name + '#' + id; } } if (!link.match('^https?:\/\/')) { if (common.readme) { link = common.readme + '#' + link; } else { link = 'https://github.com/yunkong2/yunkong2.' + 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 () { var id = $(this).data('id'); if (!id) { var $prev = $(this).prev(); var $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 showMessageJQ(message, title, icon, width) { var $dialogMessage = $('#dialog-message-settings'); if (!$dialogMessage.length) { $('body').append('<div id="dialog-message-settings" title="Message" style="display: none">\n' + '<p>' + '<span id="dialog-message-icon-settings" class="ui-icon ui-icon-circle-check" style="float :left; margin: 0 7px 50px 0;"></span>\n' + '<span id="dialog-message-text-settings"></span>\n' + '</p>\n' + '</div>'); $dialogMessage = $('#dialog-message-settings'); $dialogMessage.dialog({ autoOpen: false, modal: true, buttons: [ { text: _('Ok'), click: function () { $(this).dialog('close'); } } ] }); } $dialogMessage.dialog('option', 'width', width + 500); if (typeof _ !== 'undefined') { $dialogMessage.dialog('option', 'title', title || _('Message')); } else { $dialogMessage.dialog('option', 'title', title || 'Message'); } $('#dialog-message-text-settings').html(message); if (icon) { $('#dialog-message-icon-settings') .show() .attr('class', '') .addClass('ui-icon ui-icon-' + icon); } else { $('#dialog-message-icon-settings').hide(); } $dialogMessage.dialog('open'); } function showMessage(message, title, icon) { if (!isMaterialize) { return showMessageJQ(message, title, icon); } var $dialogMessage; // noinspection JSJQueryEfficiency $dialogMessage = $('#dialog-message'); if (!$dialogMessage.length) { $('body').append( '<div class="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'); } function confirmMessageJQ(message, title, icon, buttons, callback) { var $dialogConfirm = $('#dialog-confirm-settings'); if (!$dialogConfirm.length) { $('body').append('<div id="dialog-confirm-settings" title="Message" style="display: none">\n' + '<p>' + '<span id="dialog-confirm-icon-settings" class="ui-icon ui-icon-circle-check" style="float :left; margin: 0 7px 50px 0;"></span>\n' + '<span id="dialog-confirm-text-settings"></span>\n' + '</p>\n' + '</div>'); $dialogConfirm = $('#dialog-confirm-settings'); $dialogConfirm.dialog({ autoOpen: false, modal: true }); } if (typeof buttons === 'function') { callback = buttons; $dialogConfirm.dialog('option', 'buttons', [ { text: _('Ok'), click: function () { var cb = $(this).data('callback'); $(this).data('callback', null); $(this).dialog('close'); if (cb) cb(true); } }, { text: _('Cancel'), click: function () { var cb = $(this).data('callback'); $(this).data('callback', null); $(this).dialog('close'); if (cb) cb(false); } } ]); } else if (typeof buttons === 'object') { for (var b = 0; b < buttons.length; b++) { buttons[b] = { text: buttons[b], id: 'dialog-confirm-button-' + b, click: function (e) { var id = parseInt(e.currentTarget.id.substring('dialog-confirm-button-'.length), 10); var cb = $(this).data('callback'); $(this).data('callback', null); $(this).dialog('close'); if (cb) cb(id); } } } $dialogConfirm.dialog('option', 'buttons', buttons); } $dialogConfirm.dialog('option', 'title', title || _('Message')); $('#dialog-confirm-text-settings').html(message); if (icon) { $('#dialog-confirm-icon-settings') .show() .attr('class', '') .addClass('ui-icon ui-icon-' + icon); } else { $('#dialog-confirm-icon-settings').hide(); } $dialogConfirm.data('callback', callback); $dialogConfirm.dialog('open'); } 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="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 getObject(id, callback) { socket.emit('getObject', id, function (err, res) { if (!err && res) { if (callback) callback(err, res); } else { if (callback) callback(null); } }); } function getState(id, callback) { socket.emit('getState', id, function (err, res) { if (!err && res) { if (callback) callback(err, res); } else { if (callback) callback(null); } }); } function getEnums(_enum, callback) { socket.emit('getObjectView', 'system', 'enum', {startkey: 'enum.' + _enum, endkey: 'enum.' + _enum + '.\u9999'}, function (err, res) { if (!err && res) { var _res = {}; for (var i = 0; i < res.rows.length; i++) { if (res.rows[i].id === 'enum.' + _enum) continue; _res[res.rows[i].id] = res.rows[i].value; } if (callback) callback(null, _res); } else { if (callback) callback(err, []); } }); } function getGroups(callback) { socket.emit('getObjectView', 'system', 'group', {startkey: 'system.group.', endkey: 'system.group.\u9999'}, function (err, res) { if (!err && res) { var _res = {}; for (var i = 0; i < res.rows.length; i++) { _res[res.rows[i].id] = res.rows[i].value; } if (callback) callback(null, _res); } else { if (callback) callback(err, []); } }); } function getUsers(callback) { socket.emit('getObjectView', 'system', 'user', {startkey: 'system.user.', endkey: 'system.user.\u9999'}, function (err, res) { if (!err && res) { var _res = {}; for (var i = 0; i < res.rows.length; i++) { _res[res.rows[i].id] = res.rows[i].value; } if (callback) callback(null, _res); } else { if (callback) callback(err, []); } }); } function fillUsers(elemId, current, callback) { getUsers(function (err, users) { // Answer is like // { // "admin": { <<=== This is a common.name! // "type": "user", // "common": { // "name": "admin", // "password": "aaa", // "dontDelete": true, // "enabled": true, // "icon": "data:image/png;base64,xxx", // "color": "#ca0808", // "desc": "" // }, // "_id": "system.user.admin" // }, // ... // } var text = ''; // Warning u is name of user and not ID. var len = 'system.user.'.length; for (var u in users) { if (users.hasOwnProperty(u)) { var id = users[u]._id.substring(len); text += '<option value="' + id + '" ' + (current === id ? 'selected' : '') + ' >' + u[0].toUpperCase() + u.substring(1) + '</option>\n'; } } $(elemId).html(text); if (isMaterialize) { $(elemId).select(); } }); } function getIPs(host, callback) { if (typeof host === 'function') { callback = host; host = null; } socket.emit('getHostByIp', host || common.host, function (ip, _host) { if (_host) { host = _host; var IPs4 = [{name: '[IPv4] 0.0.0.0 - ' + _('Listen on all IPs'), address: '0.0.0.0', family: 'ipv4'}]; var IPs6 = [{name: '[IPv6] ::', address: '::', family: 'ipv6'}]; if (host.native.hardware && host.native.hardware.networkInterfaces) { for (var eth in host.native.hardware.networkInterfaces) { if (!host.native.hardware.networkInterfaces.hasOwnProperty(eth)) continue; for (var num = 0; num < host.native.hardware.networkInterfaces[eth].length; num++) { if (host.native.hardware.networkInterfaces[eth][num].family !== 'IPv6') { IPs4.push({name: '[' + host.native.hardware.networkInterfaces[eth][num].family + '] ' + host.native.hardware.networkInterfaces[eth][num].address + ' - ' + eth, address: host.native.hardware.networkInterfaces[eth][num].address, family: 'ipv4'}); } else { IPs6.push({name: '[' + host.native.hardware.networkInterfaces[eth][num].family + '] ' + host.native.hardware.networkInterfaces[eth][num].address + ' - ' + eth, address: host.native.hardware.networkInterfaces[eth][num].address, family: 'ipv6'}); } } } } for (var i = 0; i < IPs6.length; i++) { IPs4.push(IPs6[i]); } callback(IPs4); } }); } function fillSelectIPs(id, actualAddr, noIPv4, noIPv6, callback) { getIPs(function (ips) { var str = ''; for (var i = 0; i < ips.length; i++) { if (noIPv4 && ips[i].family === 'ipv4') continue; if (noIPv6 && ips[i].family === 'ipv6') continue; str += '<option value="' + ips[i].address + '" ' + ((ips[i].address === actualAddr) ? 'selected' : '') + '>' + ips[i].name + '</option>'; } $(id).html(str); if (isMaterialize) { $(id).select(); } if (typeof callback === 'function') { callback(); } }); } 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 getInterfaces(onlyNames, callback) { if (typeof onlyNames === 'function') { callback = onlyNames; onlyNames = false; } socket.emit('sendToHost', common.host, 'getInterfaces', null, function (result) { if (result && result.result) { if (onlyNames) { callback(null, Object.keys(result.result)); } else { callback(null, result); } } else { callback((result && result.error) || 'cannot read'); } }); } // fills select with names of the certificates and preselect it function fillSelectCertificates(id, type, actualValued) { var str = '<option value="">' + _('none') + '</option>'; for (var i = 0; i < certs.length; i++) { if (certs[i].type && certs[i].type !== type) continue; str += '<option value="' + certs[i].name + '" ' + ((certs[i].name === actualValued) ? 'selected' : '') + '>' + certs[i].name + '</option>'; } $(id).html(str); if (isMaterialize) { $(id).select(); } } 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) { if (callback) callback ([]); } else { if (doc.rows.length === 0) { if (callback) callback ([]); } else { var res = []; for (var i = 0; i < doc.rows.length; i++) { res.push(doc.rows[i].value); } if (callback) callback(res); } } }); } function getExtendableInstances(_adapter, callback) { if (typeof _adapter === 'function') { callback = _adapter; _adapter = null; } socket.emit('getObjectView', 'system', 'instance', null, function (err, doc) { if (err) { if (callback) callback ([]); } else { if (doc.rows.length === 0) { if (callback) callback ([]); } else { var res = []; for (var i = 0; i < doc.rows.length; i++) { if (doc.rows[i].value.common.webExtendable) { res.push(doc.rows[i].value); } } if (callback) callback (res); } } }); } function getIsAdapterAlive(_adapter, callback) { if (typeof _adapter === 'function') { callback = _adapter; _adapter = null; } getState('system.adapter.' + (_adapter || adapter) + '.' + instance + '.alive', function (err, obj) { if (!obj || !obj.val) { callback(false); } else { callback(true); } }); } // Adds one entry to the created with editTable table // tabId - the id of the table used by editTable // value - is one object to add in form {ip: '3.3.3.3', room: 'enum.room.bla3', desc: 'Bla3'} // $grid - [optional] - object returned by editTable to speed up the addition // _isInitial - [optional] - if it is initial fill of the table. To not trigger the onChange function addToTable(tabId, value, $grid, _isInitial) { $grid = $grid || $('#' + tabId); var obj = {_id: $grid[0]._maxIdx++}; var cols = $grid[0]._cols; for (var i = 0; i < cols.length; i++) { if (cols[i] === 'room') { obj[cols[i]] = ($grid[0]._rooms[value[cols[i]]]) ? $grid[0]._rooms[value[cols[i]]].common.name : value[cols[i]]; } else { obj[cols[i]] = value[cols[i]]; } } obj._commands = '<button data-' + tabId + '-id="' + obj._id + '" class="' + tabId + '-edit-submit">' + _('edit') + '</button>' + '<button data-' + tabId + '-id="' + obj._id + '" class="' + tabId + '-delete-submit">' + _('delete') + '</button>' + '<button data-' + tabId + '-id="' + obj._id + '" class="' + tabId + '-ok-submit" style="display:none">' + _('ok') + '</button>' + '<button data-' + tabId + '-id="' + obj._id + '" class="' + tabId + '-cancel-submit" style="display:none">' + _('cancel') + '</button>'; $grid.jqGrid('addRowData', tabId + '_' + obj._id, obj); _editInitButtons($grid, tabId, obj._id); if (!_isInitial && $grid[0]._onChange) $grid[0]._onChange('add', value); } function _editInitButtons($grid, tabId, objId) { var search = objId ? '[data-' + tabId + '-id="' + objId + '"]' : ''; $('.' + tabId + '-edit-submit' + search).off('click').button({ icons: {primary: 'ui-icon-pencil'}, text: false }).on('click', function () { var id = $(this).attr('data-' + tabId + '-id'); $('.' + tabId + '-edit-submit').hide(); $('.' + tabId + '-delete-submit').hide(); $('.' + tabId + '-ok-submit[data-' + tabId + '-id="' + id + '"]').show(); $('.' + tabId + '-cancel-submit[data-' + tabId + '-id="' + id + '"]').show(); $grid.jqGrid('editRow', tabId + '_' + id, {url: 'clientArray'}); if ($grid[0]._edited.indexOf(id) === -1) { $grid[0]._edited.push(id); } changed = true; var $navButtons = $('.dialog-config-buttons'); $navButtons.find('.btn-save').removeClass('disabled'); $navButtons.find('.btn-save-close').removeClass('disabled'); if (onChangeSupported) { $navButtons.find('.btn-cancel').find('span').html(_('cancel')); } }).css({'height': '18px', width: '22px'}); $('.' + tabId + '-delete-submit' + search).off('click').button({ icons: {primary: 'ui-icon-trash'}, text: false }).on('click', function () { var id = $(this).attr('data-' + tabId + '-id'); $grid.jqGrid('delRowData', tabId + '_' + id); changed = true; var $navButtons = $('.dialog-config-buttons'); $navButtons.find('.btn-save').removeClass('disabled'); $navButtons.find('.btn-save-close').removeClass('disabled'); if (onChangeSupported) { $navButtons.find('.btn-cancel').find('span').html(_('cancel')); } var pos = $grid[0]._edited.indexOf(id); if (pos !== -1) { $grid[0]._edited.splice(pos, 1); } if ($grid[0]._onChange) $grid[0]._onChange('del', id); }).css({'height': '18px', width: '22px'}); $('.' + tabId + '-ok-submit' + search).off('click').button({ icons: {primary: 'ui-icon-check'}, text: false }).on('click', function () { var id = $(this).attr('data-' + tabId + '-id'); $('.' + tabId + '-edit-submit').show(); $('.' + tabId + '-delete-submit').show(); $('.' + tabId + '-ok-submit').hide(); $('.' + tabId + '-cancel-submit').hide(); $grid.jqGrid('saveRow', tabId + '_' + id, {url: 'clientArray'}); changed = true; var $navButtons = $('.dialog-config-buttons'); $navButtons.find('.btn-save').removeClass('disabled'); $navButtons.find('.btn-save-close').removeClass('disabled'); if (onChangeSupp