All checks were successful
continuous-integration/drone/push Build is passing
606 lines
21 KiB
JavaScript
606 lines
21 KiB
JavaScript
var SERVER = new Object();
|
|
var BULK_EDIT = false;
|
|
var COLUMN_TO_SORT;
|
|
var SEARCH_MAPPING = new Object();
|
|
var UNDO = new Object();
|
|
var SERVER_CONNECTION = false;
|
|
var WS_AVAILABLE = false;
|
|
var ACTIVE_MENU_ID = "";
|
|
var LAST_FOCUSED_ELEMENT = null;
|
|
var LAST_BULK_CHECKBOX = null;
|
|
// Menü
|
|
var menuItems = new Array();
|
|
menuItems.push(new MainMenuItem("playlist", "{{.mainMenu.item.playlist}}", "m3u.png", "{{.mainMenu.headline.playlist}}"));
|
|
//menuItems.push(new MainMenuItem("pmsID", "{{.mainMenu.item.pmsID}}", "number.png", "{{.mainMenu.headline.pmsID}}"))
|
|
menuItems.push(new MainMenuItem("filter", "{{.mainMenu.item.filter}}", "filter.png", "{{.mainMenu.headline.filter}}"));
|
|
menuItems.push(new MainMenuItem("xmltv", "{{.mainMenu.item.xmltv}}", "xmltv.png", "{{.mainMenu.headline.xmltv}}"));
|
|
menuItems.push(new MainMenuItem("mapping", "{{.mainMenu.item.mapping}}", "mapping.png", "{{.mainMenu.headline.mapping}}"));
|
|
menuItems.push(new MainMenuItem("users", "{{.mainMenu.item.users}}", "users.png", "{{.mainMenu.headline.users}}"));
|
|
menuItems.push(new MainMenuItem("settings", "{{.mainMenu.item.settings}}", "settings.png", "{{.mainMenu.headline.settings}}"));
|
|
menuItems.push(new MainMenuItem("log", "{{.mainMenu.item.log}}", "log.png", "{{.mainMenu.headline.log}}"));
|
|
menuItems.push(new MainMenuItem("logout", "{{.mainMenu.item.logout}}", "logout.png", "{{.mainMenu.headline.logout}}"));
|
|
// Kategorien für die Einstellungen
|
|
var settingsCategory = new Array();
|
|
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.general}}", "xteveAutoUpdate,tuner,epgSource,api,use_plexAPI,plex.url,plex.token"));
|
|
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.files}}", "update,files.update,temp.path,cache.images,xepg.replace.missing.images"));
|
|
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.streaming}}", "buffer,udpxy,buffer.size.kb,buffer.timeout,user.agent,ffmpeg.path,ffmpeg.options,vlc.path,vlc.options"));
|
|
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.backup}}", "backup.path,backup.keep"));
|
|
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.authentication}}", "authentication.web,authentication.pms,authentication.m3u,authentication.xml,authentication.api"));
|
|
function showPopUpElement(elm) {
|
|
var allElements = new Array("popup-custom");
|
|
for (var i = 0; i < allElements.length; i++) {
|
|
showElement(allElements[i], false);
|
|
}
|
|
showElement(elm, true);
|
|
setTimeout(function () {
|
|
showElement("popup", true);
|
|
}, 10);
|
|
return;
|
|
}
|
|
function showElement(elmID, type) {
|
|
var cssClass;
|
|
switch (type) {
|
|
case true:
|
|
cssClass = "block";
|
|
break;
|
|
case false:
|
|
cssClass = "none";
|
|
break;
|
|
}
|
|
var element = document.getElementById(elmID);
|
|
if (element == null) {
|
|
return;
|
|
}
|
|
element.className = cssClass;
|
|
element.setAttribute("aria-hidden", type == true ? "false" : "true");
|
|
if (elmID == "loading" && document.body != null) {
|
|
document.body.setAttribute("aria-busy", type == true ? "true" : "false");
|
|
}
|
|
if (elmID == "popup") {
|
|
var popupContent_1 = document.getElementById("popup-custom");
|
|
if (type == true) {
|
|
LAST_FOCUSED_ELEMENT = document.activeElement;
|
|
if (popupContent_1 != null) {
|
|
setTimeout(function () {
|
|
popupContent_1.focus();
|
|
}, 20);
|
|
}
|
|
}
|
|
else {
|
|
if (LAST_FOCUSED_ELEMENT != null && LAST_FOCUSED_ELEMENT.focus != undefined) {
|
|
setTimeout(function () {
|
|
LAST_FOCUSED_ELEMENT.focus();
|
|
}, 20);
|
|
}
|
|
LAST_FOCUSED_ELEMENT = null;
|
|
}
|
|
}
|
|
}
|
|
function announceToScreenReader(message) {
|
|
if (message == undefined || message.length == 0) {
|
|
return;
|
|
}
|
|
var region = document.getElementById("sr-announcer");
|
|
if (region == null) {
|
|
return;
|
|
}
|
|
region.innerText = "";
|
|
setTimeout(function () {
|
|
region.innerText = message;
|
|
}, 20);
|
|
}
|
|
function setConnectionState(state, text) {
|
|
var label = text;
|
|
if (label == undefined || label.length == 0) {
|
|
switch (state) {
|
|
case "online":
|
|
label = "Connected";
|
|
break;
|
|
case "busy":
|
|
label = "Syncing";
|
|
break;
|
|
case "offline":
|
|
label = "Offline";
|
|
break;
|
|
default:
|
|
label = "Connecting";
|
|
break;
|
|
}
|
|
}
|
|
var indicator = document.getElementById("connection-indicator");
|
|
if (indicator == null) {
|
|
return;
|
|
}
|
|
indicator.className = "status-" + state;
|
|
indicator.innerText = label;
|
|
indicator.setAttribute("aria-label", "Connection status: " + label);
|
|
announceToScreenReader("Connection status " + label);
|
|
}
|
|
function changeButtonAction(element, buttonID, attribute) {
|
|
var value = element.options[element.selectedIndex].value;
|
|
document.getElementById(buttonID).setAttribute(attribute, value);
|
|
}
|
|
function getLocalData(dataType, id) {
|
|
var data = new Object();
|
|
switch (dataType) {
|
|
case "m3u":
|
|
data = SERVER["settings"]["files"][dataType][id];
|
|
break;
|
|
case "hdhr":
|
|
data = SERVER["settings"]["files"][dataType][id];
|
|
break;
|
|
case "filter":
|
|
case "custom-filter":
|
|
case "group-title":
|
|
if (id == -1) {
|
|
data["active"] = true;
|
|
data["caseSensitive"] = false;
|
|
data["description"] = "";
|
|
data["exclude"] = "";
|
|
data["filter"] = "";
|
|
data["include"] = "";
|
|
data["name"] = "";
|
|
data["type"] = "group-title";
|
|
SERVER["settings"]["filter"][id] = data;
|
|
}
|
|
data = SERVER["settings"]["filter"][id];
|
|
break;
|
|
case "xmltv":
|
|
data = SERVER["settings"]["files"][dataType][id];
|
|
break;
|
|
case "users":
|
|
data = SERVER["users"][id]["data"];
|
|
break;
|
|
case "mapping":
|
|
data = SERVER["xepg"]["epgMapping"][id];
|
|
break;
|
|
case "m3uGroups":
|
|
data = SERVER["data"]["playlist"]["m3u"]["groups"];
|
|
break;
|
|
}
|
|
return data;
|
|
}
|
|
function getObjKeys(obj) {
|
|
var keys = new Array();
|
|
for (var i in obj) {
|
|
if (obj.hasOwnProperty(i)) {
|
|
keys.push(i);
|
|
}
|
|
}
|
|
return keys;
|
|
}
|
|
function getAllSelectedChannels() {
|
|
var channels = new Array();
|
|
if (BULK_EDIT == false) {
|
|
return channels;
|
|
}
|
|
var trs = document.getElementById("content_table").getElementsByTagName("TR");
|
|
for (var i = 1; i < trs.length; i++) {
|
|
if (trs[i].style.display != "none") {
|
|
if (trs[i].firstChild.firstChild.checked == true) {
|
|
channels.push(trs[i].id);
|
|
}
|
|
}
|
|
}
|
|
return channels;
|
|
}
|
|
function selectChannelRange(checkbox, event) {
|
|
if (BULK_EDIT == false || checkbox == undefined || checkbox == null) {
|
|
return;
|
|
}
|
|
var table = document.getElementById("content_table");
|
|
if (table == null) {
|
|
return;
|
|
}
|
|
var trs = table.getElementsByTagName("TR");
|
|
var visibleCheckboxes = new Array();
|
|
for (var i = 1; i < trs.length; i++) {
|
|
if (trs[i].style.display != "none") {
|
|
var bulkCheckbox = trs[i].querySelector("input.bulk");
|
|
if (bulkCheckbox != null) {
|
|
visibleCheckboxes.push(bulkCheckbox);
|
|
}
|
|
}
|
|
}
|
|
var currentIndex = visibleCheckboxes.indexOf(checkbox);
|
|
var previousIndex = -1;
|
|
if (LAST_BULK_CHECKBOX != null) {
|
|
previousIndex = visibleCheckboxes.indexOf(LAST_BULK_CHECKBOX);
|
|
}
|
|
if (event != undefined && event.shiftKey == true && previousIndex > -1 && currentIndex > -1) {
|
|
var start = Math.min(previousIndex, currentIndex);
|
|
var end = Math.max(previousIndex, currentIndex);
|
|
for (var i = start; i <= end; i++) {
|
|
visibleCheckboxes[i].checked = checkbox.checked;
|
|
}
|
|
}
|
|
LAST_BULK_CHECKBOX = checkbox;
|
|
}
|
|
function selectAllChannels() {
|
|
var bulk = false;
|
|
var trs = document.getElementById("content_table").getElementsByTagName("TR");
|
|
if (trs[0].firstChild.firstChild.checked == true) {
|
|
bulk = true;
|
|
}
|
|
for (var i = 1; i < trs.length; i++) {
|
|
if (trs[i].style.display != "none") {
|
|
switch (bulk) {
|
|
case true:
|
|
trs[i].firstChild.firstChild.checked = true;
|
|
break;
|
|
case false:
|
|
trs[i].firstChild.firstChild.checked = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
LAST_BULK_CHECKBOX = null;
|
|
return;
|
|
}
|
|
function bulkEdit() {
|
|
BULK_EDIT = !BULK_EDIT;
|
|
var className;
|
|
var rows = document.getElementsByClassName("bulk");
|
|
switch (BULK_EDIT) {
|
|
case true:
|
|
className = "bulk showBulk";
|
|
break;
|
|
case false:
|
|
className = "bulk hideBulk";
|
|
break;
|
|
}
|
|
for (var i = 0; i < rows.length; i++) {
|
|
rows[i].className = className;
|
|
rows[i].checked = false;
|
|
}
|
|
LAST_BULK_CHECKBOX = null;
|
|
return;
|
|
}
|
|
function sortTable(column) {
|
|
//console.log(columm);
|
|
if (column == COLUMN_TO_SORT) {
|
|
return;
|
|
}
|
|
var table = document.getElementById("content_table");
|
|
var tableHead = table.getElementsByTagName("TR")[0];
|
|
var tableItems = tableHead.getElementsByTagName("TD");
|
|
for (var h = 0; h < tableItems.length; h++) {
|
|
if (tableItems[h].getAttribute("role") == "columnheader") {
|
|
tableItems[h].setAttribute("aria-sort", "none");
|
|
}
|
|
}
|
|
var sortObj = new Object();
|
|
var x, xValue;
|
|
var tableHeader;
|
|
var sortByString = false;
|
|
if (column > 0 && COLUMN_TO_SORT > 0) {
|
|
tableItems[COLUMN_TO_SORT].classList.remove("sortThis");
|
|
tableItems[COLUMN_TO_SORT].classList.add("pointer");
|
|
tableItems[column].classList.remove("pointer");
|
|
tableItems[column].classList.add("sortThis");
|
|
}
|
|
COLUMN_TO_SORT = column;
|
|
var mobileSort = document.getElementById("mapping-sort-mobile");
|
|
if (mobileSort != null && (column == 1 || column == 3 || column == 4 || column == 5)) {
|
|
mobileSort.value = column.toString();
|
|
}
|
|
if (tableItems[column] != undefined && tableItems[column].getAttribute("role") == "columnheader") {
|
|
tableItems[column].setAttribute("aria-sort", "ascending");
|
|
}
|
|
var rows = table.rows;
|
|
if (rows[1] != undefined) {
|
|
tableHeader = rows[0];
|
|
x = rows[1].getElementsByTagName("TD")[column];
|
|
for (i = 1; i < rows.length; i++) {
|
|
x = rows[i].getElementsByTagName("TD")[column];
|
|
switch (x.childNodes[0].tagName.toLowerCase()) {
|
|
case "input":
|
|
xValue = x.getElementsByTagName("INPUT")[0].value.toLowerCase();
|
|
break;
|
|
case "p":
|
|
xValue = x.getElementsByTagName("P")[0].innerText.toLowerCase();
|
|
break;
|
|
default: console.log(x.childNodes[0].tagName);
|
|
}
|
|
if (xValue == "" || xValue == NaN) {
|
|
xValue = i;
|
|
sortObj[i] = rows[i];
|
|
}
|
|
else {
|
|
switch (isNaN(xValue)) {
|
|
case false:
|
|
xValue = parseFloat(xValue);
|
|
sortObj[xValue] = rows[i];
|
|
break;
|
|
case true:
|
|
sortByString = true;
|
|
sortObj[xValue.toLowerCase() + i] = rows[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while (table.firstChild) {
|
|
table.removeChild(table.firstChild);
|
|
}
|
|
var sortValues = getObjKeys(sortObj);
|
|
if (sortByString == true) {
|
|
sortValues.sort();
|
|
console.log(sortValues);
|
|
}
|
|
else {
|
|
function sortFloat(a, b) {
|
|
return a - b;
|
|
}
|
|
sortValues.sort(sortFloat);
|
|
}
|
|
table.appendChild(tableHeader);
|
|
for (var i = 0; i < sortValues.length; i++) {
|
|
table.appendChild(sortObj[sortValues[i]]);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
function createSearchObj() {
|
|
SEARCH_MAPPING = new Object();
|
|
var data = SERVER["xepg"]["epgMapping"];
|
|
var channels = getObjKeys(data);
|
|
var channelKeys = ["x-active", "x-channelID", "x-name", "_file.m3u.name", "x-group-title", "x-xmltv-file"];
|
|
channels.forEach(function (id) {
|
|
SEARCH_MAPPING[id] = "";
|
|
channelKeys.forEach(function (key) {
|
|
if (key == "x-active") {
|
|
switch (data[id][key]) {
|
|
case true:
|
|
SEARCH_MAPPING[id] = "online ";
|
|
break;
|
|
case false:
|
|
SEARCH_MAPPING[id] = "offline ";
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
if (key == "x-xmltv-file") {
|
|
var xmltvFile = getValueFromProviderFile(data[id][key], "xmltv", "name");
|
|
if (xmltvFile != undefined) {
|
|
SEARCH_MAPPING[id] = SEARCH_MAPPING[id] + xmltvFile + " ";
|
|
}
|
|
}
|
|
else {
|
|
SEARCH_MAPPING[id] = SEARCH_MAPPING[id] + data[id][key] + " ";
|
|
}
|
|
}
|
|
});
|
|
});
|
|
return;
|
|
}
|
|
function searchInMapping() {
|
|
var searchValue = document.getElementById("searchMapping").value;
|
|
var trs = document.getElementById("content_table").getElementsByTagName("TR");
|
|
for (var i = 1; i < trs.length; ++i) {
|
|
var id = trs[i].getAttribute("id");
|
|
var element = SEARCH_MAPPING[id];
|
|
if (element == undefined) {
|
|
continue;
|
|
}
|
|
switch (element.toLowerCase().includes(searchValue.toLowerCase())) {
|
|
case true:
|
|
document.getElementById(id).style.display = "";
|
|
break;
|
|
case false:
|
|
document.getElementById(id).style.display = "none";
|
|
break;
|
|
}
|
|
}
|
|
announceToScreenReader("Search updated");
|
|
return;
|
|
}
|
|
function calculateWrapperHeight() {
|
|
var elm = document.getElementById("box-wrapper");
|
|
var content = document.getElementById("content");
|
|
if (elm != null && content != null) {
|
|
var contentTop = content.getBoundingClientRect().top;
|
|
var freeSpace = window.innerHeight - contentTop - 26;
|
|
if (freeSpace < 180) {
|
|
freeSpace = 180;
|
|
}
|
|
elm.style.height = freeSpace + "px";
|
|
}
|
|
return;
|
|
}
|
|
function changeChannelNumber(element) {
|
|
var dbID = element.parentNode.parentNode.id;
|
|
var newNumber = parseFloat(element.value);
|
|
var channelNumbers = [];
|
|
var data = SERVER["xepg"]["epgMapping"];
|
|
var channels = getObjKeys(data);
|
|
if (isNaN(newNumber)) {
|
|
alert("{{.alert.invalidChannelNumber}}");
|
|
return;
|
|
}
|
|
channels.forEach(function (id) {
|
|
var channelNumber = parseFloat(data[id]["x-channelID"]);
|
|
channelNumbers.push(channelNumber);
|
|
});
|
|
for (var i = 0; i < channelNumbers.length; i++) {
|
|
if (channelNumbers.indexOf(newNumber) == -1) {
|
|
break;
|
|
}
|
|
if (Math.floor(newNumber) == newNumber) {
|
|
newNumber = newNumber + 1;
|
|
}
|
|
else {
|
|
newNumber = newNumber + 0.1;
|
|
newNumber.toFixed(1);
|
|
newNumber = Math.round(newNumber * 10) / 10;
|
|
}
|
|
}
|
|
data[dbID]["x-channelID"] = newNumber.toString();
|
|
element.value = newNumber;
|
|
console.log(data[dbID]["x-channelID"]);
|
|
if (COLUMN_TO_SORT == 1) {
|
|
COLUMN_TO_SORT = -1;
|
|
sortTable(1);
|
|
}
|
|
return;
|
|
}
|
|
function backup() {
|
|
var data = new Object();
|
|
console.log("Backup data");
|
|
var cmd = "xteveBackup";
|
|
console.log("SEND TO SERVER");
|
|
console.log(data);
|
|
var server = new Server(cmd);
|
|
server.request(data);
|
|
return;
|
|
}
|
|
function toggleChannelStatus(id) {
|
|
var element;
|
|
var status;
|
|
if (document.getElementById("active")) {
|
|
var checkbox = document.getElementById("active");
|
|
status = (checkbox).checked;
|
|
}
|
|
var ids = getAllSelectedChannels();
|
|
if (ids.length == 0) {
|
|
ids.push(id);
|
|
}
|
|
ids.forEach(function (id) {
|
|
var channel = SERVER["xepg"]["epgMapping"][id];
|
|
channel["x-active"] = status;
|
|
switch (channel["x-active"]) {
|
|
case true:
|
|
if (channel["x-xmltv-file"] == "-" || channel["x-mapping"] == "-") {
|
|
if (BULK_EDIT == false) {
|
|
alert(channel["x-name"] + ": Missing XMLTV file / channel");
|
|
checkbox.checked = false;
|
|
}
|
|
channel["x-active"] = false;
|
|
}
|
|
break;
|
|
case false:
|
|
// code...
|
|
break;
|
|
}
|
|
if (channel["x-active"] == false) {
|
|
document.getElementById(id).className = "notActiveEPG";
|
|
}
|
|
else {
|
|
document.getElementById(id).className = "activeEPG";
|
|
}
|
|
});
|
|
}
|
|
function restore() {
|
|
if (document.getElementById('upload')) {
|
|
document.getElementById('upload').remove();
|
|
}
|
|
var restore = document.createElement("INPUT");
|
|
restore.setAttribute("type", "file");
|
|
restore.setAttribute("class", "notVisible");
|
|
restore.setAttribute("name", "");
|
|
restore.id = "upload";
|
|
document.body.appendChild(restore);
|
|
restore.click();
|
|
restore.onchange = function () {
|
|
var filename = restore.files[0].name;
|
|
var check = confirm("File: " + filename + "\n{{.confirm.restore}}");
|
|
if (check == true) {
|
|
var reader = new FileReader();
|
|
var file = document.querySelector('input[type=file]').files[0];
|
|
if (file) {
|
|
reader.readAsDataURL(file);
|
|
reader.onload = function () {
|
|
console.log(reader.result);
|
|
var data = new Object();
|
|
var cmd = "xteveRestore";
|
|
data["base64"] = reader.result;
|
|
var server = new Server(cmd);
|
|
server.request(data);
|
|
};
|
|
}
|
|
else {
|
|
alert("File could not be loaded");
|
|
}
|
|
restore.remove();
|
|
return;
|
|
}
|
|
};
|
|
return;
|
|
}
|
|
function uploadLogo() {
|
|
if (document.getElementById('upload')) {
|
|
document.getElementById('upload').remove();
|
|
}
|
|
var upload = document.createElement("INPUT");
|
|
upload.setAttribute("type", "file");
|
|
upload.setAttribute("class", "notVisible");
|
|
upload.setAttribute("name", "");
|
|
upload.id = "upload";
|
|
document.body.appendChild(upload);
|
|
upload.click();
|
|
upload.onblur = function () {
|
|
alert();
|
|
};
|
|
upload.onchange = function () {
|
|
var filename = upload.files[0].name;
|
|
var reader = new FileReader();
|
|
var file = document.querySelector('input[type=file]').files[0];
|
|
if (file) {
|
|
reader.readAsDataURL(file);
|
|
reader.onload = function () {
|
|
console.log(reader.result);
|
|
var data = new Object();
|
|
var cmd = "uploadLogo";
|
|
data["base64"] = reader.result;
|
|
data["filename"] = file.name;
|
|
var server = new Server(cmd);
|
|
server.request(data);
|
|
var updateLogo = document.getElementById('update-icon');
|
|
updateLogo.checked = false;
|
|
updateLogo.className = "changed";
|
|
};
|
|
}
|
|
else {
|
|
alert("File could not be loaded");
|
|
}
|
|
upload.remove();
|
|
return;
|
|
};
|
|
}
|
|
function checkUndo(key) {
|
|
switch (key) {
|
|
case "epgMapping":
|
|
if (UNDO.hasOwnProperty(key)) {
|
|
SERVER["xepg"][key] = JSON.parse(JSON.stringify(UNDO[key]));
|
|
}
|
|
else {
|
|
UNDO[key] = JSON.parse(JSON.stringify(SERVER["xepg"][key]));
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
function sortSelect(elem) {
|
|
var tmpAry = [];
|
|
var selectedValue = elem[elem.selectedIndex].value;
|
|
for (var i = 0; i < elem.options.length; i++)
|
|
tmpAry.push(elem.options[i]);
|
|
tmpAry.sort(function (a, b) { return (a.text < b.text) ? -1 : 1; });
|
|
while (elem.options.length > 0)
|
|
elem.options[0] = null;
|
|
var newSelectedIndex = 0;
|
|
for (var i = 0; i < tmpAry.length; i++) {
|
|
elem.options[i] = tmpAry[i];
|
|
if (elem.options[i].value == selectedValue)
|
|
newSelectedIndex = i;
|
|
}
|
|
elem.selectedIndex = newSelectedIndex; // Set new selected index after sorting
|
|
return;
|
|
}
|
|
function updateLog() {
|
|
console.log("TOKEN");
|
|
var server = new Server("updateLog");
|
|
server.request(new Object());
|
|
}
|