yunkong2.owntracks/admin/index.html

482 lines
20 KiB
HTML
Raw Normal View History

2018-10-02 21:20:21 +08:00
<html>
<link rel="stylesheet" type="text/css" href="../../lib/css/themes/jquery-ui/redmond/jquery-ui.min.css"/>
<script type="text/javascript" src="../../lib/js/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="../../socket.io/socket.io.js"></script>
<script type="text/javascript" src="../../lib/js/jquery-ui-1.10.3.full.min.js"></script>
<link rel="stylesheet" type="text/css" href="../../css/adapter.css"/>
<script type="text/javascript" src="../../js/translate.js"></script>
<script type="text/javascript" src="../../js/adapter-settings.js"></script>
<style>
#drop-zone {
width: calc(100% - 10px);
height: calc(100% - 10px);
position: absolute;
opacity: 0.8;
top: 0;
left: 0;
background: #eee;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
z-index: 1;
font-size: 32px;
font-weight: bold;
text-align: center;
border: 5px dashed darkgray;
}
.dropZone-error {
background: #faa !important;
color: #f00;
}
</style>
<script type="text/javascript">
var onChange;
systemDictionary = {
"OwnTracks adapter settings": {
"en": "OwnTracks adapter settings",
"de": "OwnTracks adapter settings",
"ru": "Настройки драйвера OwnTracks"
},
"Server settings": {"en": "Server settings", "de": "Server settings", "ru": "Настройки сервера settings"},
"User:": {"en": "User:", "de": "Anwender:", "ru": "Пользователь:"},
"Password:": {"en": "Password:", "de": "Kennwort:", "ru": "Пароль:"},
"Password repeat:": {"en": "Password repeat:", "de": "Kennwort-Wiederholung:", "ru": "Повтор пароля:"},
"Empty name not allowed!": {
"en": "Empty name not allowed!",
"de": "Ohne Namen ist nicht erlaubt!",
"ru": "Пустое имя пользователя не разрешено!"
},
"Ok": {"en": "Ok", "de": "Ok", "ru": "Ok"},
"IP:": {"de": "IP:", "ru": "IP:"},
"Port:": {"de": "Port:", "ru": "Порт:"},
"Secure(HTTPS):": {"de": "Verschlüsselung(HTTPS):", "ru": "Шифрование(HTTPS):"},
"Authentication:": {"de": "Authentifikation:", "ru": "Аутентификация:"},
"Listen on all IPs": {"en": "Listen on all IPs", "de": "An allen IP Adressen hören", "ru": "Открыть сокет на всех IP адресах"},
"help_tip": {
"en": "On save the adapter restarts with new configuration immediately",
"de": "Beim Speichern von Einstellungen der Adapter wird sofort neu gestartet.",
"ru": "Сразу после сохранения настроек драйвер перезапуститься с новыми значениями"
},
"Public certificate:": {"en": "Public certificate:", "de": "Publikzertifikat:", "ru": "'Public' сертификат:"},
"Private certificate:": {"en": "Private certificate:", "de": "Privatzertifikat:", "ru": "'Private' сертификат:"},
"Chained certificate:": {"en": "Chained certificate:", "de": "Kettenzertifikat:", "ru": "'Chained' сертификат:"},
"Let's Encrypt settings": {
"en": "Let's Encrypt settings",
"de": "Einstellungen Let's Encrypt",
"ru": "Настройкт Let's Encrypt"
},
"Use Lets Encrypt certificates:": {
"en": "Use Let's Encrypt certificates:",
"de": "Benutzen Let's Encrypt Zertifikate:",
"ru": "Использовать сертификаты Let's Encrypt:"
},
"Use this instance for automatic update:": {
"en": "Use this instance for automatic update:",
"de": "Benutze diese Instanz für automatische Updates:",
"ru": "Обновлять сертификаты в этом драйвере:"
},
"Port to check the domain:": {
"en": "Port to check the domain:",
"de": "Port um die Domain zu prüfen:",
"ru": "Порт для проверки доменного имени:"
},
"Drop the files here": {"en": "Drop the files here", "de": "Die Datei hier platzieren", "ru": "Перетащить файлы сюда"},
"Unknown file format!": {"en": "Unknown file format!", "de": "Unbekannter Dateiformat!", "ru": "Неизвестный формат файла"},
"Cannot read file!": {"en": "Cannot read file!", "de": "Kann die Datei nicht lesen!", "ru": "Невозможно прочитать файл!"},
"File is too big!": {"en": "File is too big!", "de": "Datei ist zu groß!", "ru": "Слишком большой файл!"}
};
function encrypt(key, value) {
var result = '';
for(var i = 0; i < value.length; i++) {
result += String.fromCharCode(key[i % key.length].charCodeAt(0) ^ value.charCodeAt(i));
}
return result;
}
function decrypt(key, value) {
var result = '';
for(var i = 0; i < value.length; i++) {
result += String.fromCharCode(key[i % key.length].charCodeAt(0) ^ value.charCodeAt(i));
}
return result;
}
function showHideSettings() {
if ($('#secure').prop('checked')) {
$('#_certPublic').show();
$('#_certPrivate').show();
$('#_certChained').show();
$('.le-settings').show();
if ($('#leEnabled').prop('checked')) {
$('.le-sub-settings').show();
if ($('#leUpdate').prop('checked')) {
$('.le-sub-settings-update').show();
} else {
$('.le-sub-settings-update').hide();
}
} else {
$('.le-sub-settings').hide();
}
} else {
$('#_certPublic').hide();
$('#_certPrivate').hide();
$('#_certChained').hide();
$('.le-settings').hide();
}
}
function fileHandler(event) {
event.preventDefault();
var file = event.dataTransfer ? event.dataTransfer.files[0] : event.target.files[0];
var $dz = $('#drop-zone');
if (file.size > 1000000) {
$('#drop-text').html(_('File is too big!'));
$dz.addClass('dropZone-error').animate({opacity: 0}, 1000, function () {
$dz.hide().removeClass('dropZone-error').css({opacity: 1});
showMessage(_('File is too big!'));
$('#drop-text').html(_('Drop the files here'));
});
return false;
}
$dz.show();
var reader = new FileReader();
reader.onload = function (evt) {
var text;
try {
text = evt.target.result; // string has form data:;base64,TEXT==
if ($('#drop-file').data('index') !== null) {
resizeImage(text, function (result) {
var pictures = getPictures();
pictures[$('#drop-file').data('index')].base64 = result;
onChange();
showPictures(pictures);
});
} else {
resizeImage(text, function (result) {
addPicture(null, result);
});
}
$dz.hide().removeClass('dropZone-error').css({opacity: 1});
} catch (err) {
console.error(err);
$('#drop-text').html(_('Cannot read file!'));
$dz.addClass('dropZone-error').animate({opacity: 0}, 1000, function () {
$dz.hide().removeClass('dropZone-error').css({opacity: 1});
showMessage(_('Cannot read file!'));
$('#drop-text').html(_('Drop the files here'));
});
}
};
reader.readAsDataURL(file);
}
function showPictureLine(pictures, i) {
var text = '<tr>';
text += '<td><input type="text" style="width: 100%" class="pictures-value" data-name="name" value="' + pictures[i].name + '" data-index="' + i +'"></td>';
text += '<td>' +
'<img width="64" src="' + pictures[i].base64 + '" class="pictures-value" data-name="base64" data-index="' + i +'" />' +
'<button class="pictures-upload" data-index="' + i +'"></td>';
text += '<td><button class="pictures-delete" data-index="' + i +'"></td>';
text += '</tr>';
return text;
}
function resizeImage(srcBase64, callback) {
var maxW = 64;
var maxH = 64;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var cw = canvas.width;
var ch = canvas.height;
var img = new Image;
img.onload = function() {
var iw = img.width;
var ih = img.height;
var scale = Math.min((maxW / iw), (maxH / ih));
var iwScaled = iw*scale;
var ihScaled = ih*scale;
canvas.width = iwScaled;
canvas.height = ihScaled;
ctx.drawImage(img,0,0,iwScaled,ihScaled);
callback(canvas.toDataURL());
};
try {
img.src = srcBase64;
} catch (e) {
callback(srcBase64);
}
}
function showPictures(pictures) {
var text = '';
for (var i = 0; i < pictures.length; i++) {
text += showPictureLine(pictures, i);
}
$('#pictures').html(text);
// init inputs and buttons
$('.pictures-value').change(function () {
onChange();
}).keyup(function () {
$(this).trigger('change');
});
$('.pictures-delete').button({
icons: {
primary: 'ui-icon-trash'
},
text: false
})
.css({width: 18, height: 18, float: 'right', 'margin-top': -5})
.attr('title', _('Delete picture and person'))
.click(function () {
// todo are you sure
var index = $(this).data('index');
var pictures = getPictures();
pictures.splice(index, 1);
showPictures(pictures);
});
$('.pictures-upload').button({
icons: {
primary: 'ui-icon-arrowthickstop-1-s'
},
text: false
})
.attr('title', _('Upload picture'))
.css({width: 18, height: 18, float: 'right', 'margin-top': 20})
.click(function () {
$('#drop-file').data('index', $(this).data('index'));
$('#drop-file').trigger('click');
});
}
function getPictures() {
var pictures = [];
$('.pictures-value').each(function () {
var index = $(this).data('index');
var name = $(this).data('name');
pictures[index] = pictures[index] || {};
if ($(this).prop('tagName') === 'IMG') {
pictures[index][name] = $(this).attr('src');
} else {
pictures[index][name] = $(this).val();
}
});
return pictures;
}
function addPicture(name, base64) {
var pictures = getPictures();
var id = 1;
if (!name) {
var found;
do {
found = false;
name = _('User') + ' ' + id;
for (var i = 0; i < pictures.length; i++) {
if (pictures[i].name === name) {
found = true;
id++
}
}
} while (found);
}
pictures.push({name: name, base64: base64 || ''});
onChange();
showPictures(pictures);
}
// the function loadSettings has to exist ...
function load(settings, _onChange) {
if (!settings) return;
onChange = _onChange;
$('#tabs').tabs({
activate: function (event, ui) {
if (ui.newPanel.selector == '#tabs-2') {
$('#drop-zone').show().css({opacity: 1}).animate({opacity: 0}, 2000, function () {
$('#drop-zone').hide().css({opacity: 1});
});
}
}
});
var $dropZone = $('#adapter-container');
if (typeof(window.FileReader) !== 'undefined' && !$dropZone.data('installed')) {
$dropZone.data('installed', true);
var $dz = $('#drop-zone');
$('#drop-text').html(_('Drop the files here'));
$dropZone[0].ondragover = function() {
$dz.unbind('click');
$dz.show();
return false;
};
$dz.click(function () {
$dz.hide();
});
$dz[0].ondragleave = function() {
$dz.hide();
return false;
};
$dz[0].ondrop = function (e) {
$('#drop-file').data('index', null);
fileHandler(e);
};
}
$('#drop-file').change(fileHandler);
// this functions are loaded from library
getIPs(function(ips) {
for (var i = 0; i < ips.length; i++) {
$('#bind').append('<option value="' + ips[i].address + '">' + ips[i].name + '</option>');
}
$('#bind.value').val(settings.bind);
});
$('.value').each(function () {
var key = $(this).attr('id');
if ($('#' + key + '.value').attr('type') === 'checkbox') {
$('#' + key + '.value').prop('checked', settings[key]).change(function() {
_onChange();
});
} else {
if (key === 'pass') settings[key] = decrypt('Zgfr56gFe87jJOM', settings[key]);
$('#' + key + '.value').val(settings[key]).change(function() {
_onChange();
}).keyup(function() {
_onChange();
});
}
});
settings.pictures = settings.pictures || [];
$('#passRepeat').val($('#pass').val());
// Signal to admin, that no changes yet
_onChange(false);
// this functions are loaded from library
fillSelectCertificates('#certPublic', 'public', settings.certPublic);
fillSelectCertificates('#certPrivate', 'private', settings.certPrivate);
fillSelectCertificates('#certChained', 'chained', settings.certChained);
fillUsers('#defaultUser', settings.defaultUser);
$('#secure').change(showHideSettings);
showPictures(settings.pictures);
$('#add').button({
icons: {
primary: 'ui-icon-plus'
},
text: false
})
.css({width: 18, height: 18, margin: 5})
.attr('title', _('Add picture for person'))
.click(function () {
addPicture();
});
showHideSettings();
}
function save(callback) {
var obj = {};
$('.value').each(function () {
var $this = $(this);
var key = $this.attr('id');
if ($this.attr('type') === 'checkbox') {
obj[key] = $this.prop('checked');
} else {
if (key === 'pass') {
obj[key] = encrypt('Zgfr56gFe87jJOM', $this.val());
} else {
obj[key] = $this.val()
}
}
});
if (!obj.user) {
showMessage(_('Empty name not allowed!'));
return;
}
obj.pictures = getPictures();
callback(obj);
}
</script>
<div id="adapter-container">
<table><tr>
<td><img src="owntracks.png"/></td>
<td><h3 class="translate">OwnTracks adapter settings</h3></td>
</tr></table>
<div id="tabs">
<ul>
<li><a href="#tabs-1" class="translate">General</a></li>
<li><a href="#tabs-2" class="translate">Pictures</a></li>
</ul>
<div id="tabs-1">
<table>
<tr><td colspan="2"><h4 class="translate">Server settings</h4></td></tr>
<tr><td><label class="translate" for="bind">IP:</label></td><td> <select class="value" id="bind"></select></td></tr>
<tr><td><label class="translate" for="port">Port:</label></td><td> <input class="value" id="port" size="5" maxlength="5"/></td></tr>
<tr><td><label class="translate" for="user">User:</label></td><td> <input class="value" id="user"/></td></tr>
<tr><td><label class="translate" for="pass">Password:</label></td><td> <input class="value" id="pass" type="password"/></td></tr>
<tr><td><label class="translate" for="passRepeat">Password repeat:</label></td><td><input id="passRepeat" type="password"/></td></tr>
<!--
<tr><td><label class="translate" for="secure">Secure(HTTPS):</label></td><td> <input class="value" id="secure" type="checkbox" /></td></tr>
<tr id="_certPublic">
<td><label class="translate" for="certPublic">Public certificate:</label></td>
<td><select id="certPublic" class="value"></select></td>
</tr>
<tr id="_certPrivate">
<td><label class="translate" for="certPrivate">Private certificate:</label></td>
<td><select id="certPrivate" class="value"></select></td>
</tr>
<tr id="_certChained">
<td><label class="translate" for="certChained">Chained certificate:</label></td>
<td><select id="certChained" class="value"></select></td>
</tr>
<tr><td colspan="2">&nbsp;</td></tr>
<tr class="le-settings"><td colspan="2"><h3 class="translate">Let's Encrypt settings</h3></tr>
<tr class="le-settings"><td><label for="leEnabled" class="translate">Use Lets Encrypt certificates:</label></td><td><input class="value" id="leEnabled" type="checkbox" /></td></tr>
<tr class="le-settings le-sub-settings"><td><label for="leUpdate" class="translate">Use this instance for automatic update:</label></td><td><input class="value" id="leUpdate" type="checkbox" /></td></tr>
<tr class="le-settings le-sub-settings le-sub-settings-update"><td><label for="lePort" class="translate">Port to check the domain:</label></td><td><input class="value number" id="lePort" type="number" size="5" maxlength="5" /></td></tr>
-->
</table>
</div>
<div id="tabs-2">
<div id="drop-zone" style="display: none"><div style="padding-top: 15%" class="translate" id="drop-text"></div>
<input type="file" id="drop-file" style="display: none">
</div>
<button id="add"></button>
<table style="width: 330px">
<thead>
<tr class="ui-widget-header">
<td class="translate" style="width: 200px">Name</td>
<td class="translate">Picture</td>
<td></td>
</tr>
</thead>
<tbody id="pictures"></tbody>
</table>
</div>
</div>
</div>
</html>