royalcat refactoring
This commit is contained in:
parent
1da835cea6
commit
b245c9f451
81 changed files with 1476 additions and 1580 deletions
|
@ -1,176 +1,162 @@
|
|||
Handlebars.registerHelper('ibytes', function (bytesSec, timePassed) {
|
||||
return Humanize.ibytes(bytesSec / timePassed, 1024);
|
||||
Handlebars.registerHelper("ibytes", function (bytesSec, timePassed) {
|
||||
return Humanize.ibytes(bytesSec / timePassed, 1024);
|
||||
});
|
||||
Handlebars.registerHelper('bytes', function (bytes) {
|
||||
return Humanize.bytes(bytes, 1024);
|
||||
Handlebars.registerHelper("bytes", function (bytes) {
|
||||
return Humanize.bytes(bytes, 1024);
|
||||
});
|
||||
|
||||
var tstor = tstor || {};
|
||||
|
||||
var Distribyted = Distribyted || {};
|
||||
tstor.message = {
|
||||
_toastr: function () {
|
||||
toastr.options = {
|
||||
closeButton: true,
|
||||
debug: false,
|
||||
newestOnTop: false,
|
||||
progressBar: true,
|
||||
positionClass: "toast-top-right",
|
||||
preventDuplicates: false,
|
||||
onclick: null,
|
||||
showDuration: "300",
|
||||
hideDuration: "1000",
|
||||
timeOut: "5000",
|
||||
extendedTimeOut: "1000",
|
||||
showEasing: "swing",
|
||||
hideEasing: "linear",
|
||||
showMethod: "fadeIn",
|
||||
hideMethod: "fadeOut",
|
||||
};
|
||||
|
||||
Distribyted.message = {
|
||||
return toastr;
|
||||
},
|
||||
|
||||
_toastr: function () {
|
||||
toastr.options = {
|
||||
closeButton: true,
|
||||
debug: false,
|
||||
newestOnTop: false,
|
||||
progressBar: true,
|
||||
positionClass: "toast-top-right",
|
||||
preventDuplicates: false,
|
||||
onclick: null,
|
||||
showDuration: "300",
|
||||
hideDuration: "1000",
|
||||
timeOut: "5000",
|
||||
extendedTimeOut: "1000",
|
||||
showEasing: "swing",
|
||||
hideEasing: "linear",
|
||||
showMethod: "fadeIn",
|
||||
hideMethod: "fadeOut"
|
||||
};
|
||||
error: function (message) {
|
||||
this._toastr().error(message);
|
||||
},
|
||||
|
||||
return toastr;
|
||||
},
|
||||
|
||||
|
||||
error: function (message) {
|
||||
this._toastr().error(message);
|
||||
},
|
||||
|
||||
info: function (message) {
|
||||
this._toastr().info(message);
|
||||
}
|
||||
}
|
||||
info: function (message) {
|
||||
this._toastr().info(message);
|
||||
},
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
"use strict";
|
||||
"use strict";
|
||||
|
||||
/*======== 1. SCROLLBAR SIDEBAR ========*/
|
||||
var sidebarScrollbar = $(".sidebar-scrollbar");
|
||||
if (sidebarScrollbar.length != 0) {
|
||||
sidebarScrollbar.slimScroll({
|
||||
opacity: 0,
|
||||
height: "100%",
|
||||
color: "#808080",
|
||||
size: "5px",
|
||||
touchScrollStep: 50
|
||||
})
|
||||
.mouseover(function () {
|
||||
$(this)
|
||||
.next(".slimScrollBar")
|
||||
.css("opacity", 0.5);
|
||||
});
|
||||
/*======== 1. SCROLLBAR SIDEBAR ========*/
|
||||
var sidebarScrollbar = $(".sidebar-scrollbar");
|
||||
if (sidebarScrollbar.length != 0) {
|
||||
sidebarScrollbar
|
||||
.slimScroll({
|
||||
opacity: 0,
|
||||
height: "100%",
|
||||
color: "#808080",
|
||||
size: "5px",
|
||||
touchScrollStep: 50,
|
||||
})
|
||||
.mouseover(function () {
|
||||
$(this).next(".slimScrollBar").css("opacity", 0.5);
|
||||
});
|
||||
}
|
||||
|
||||
/*======== 2. MOBILE OVERLAY ========*/
|
||||
if ($(window).width() < 768) {
|
||||
$(".sidebar-toggle").on("click", function () {
|
||||
$("body").css("overflow", "hidden");
|
||||
$("body").prepend('<div class="mobile-sticky-body-overlay"></div>');
|
||||
});
|
||||
|
||||
$(document).on("click", ".mobile-sticky-body-overlay", function (e) {
|
||||
$(this).remove();
|
||||
$("#body")
|
||||
.removeClass("sidebar-mobile-in")
|
||||
.addClass("sidebar-mobile-out");
|
||||
$("body").css("overflow", "auto");
|
||||
});
|
||||
}
|
||||
|
||||
/*======== 3. SIDEBAR MENU ========*/
|
||||
var sidebar = $(".sidebar");
|
||||
if (sidebar.length != 0) {
|
||||
$(".sidebar .nav > .has-sub > a").click(function () {
|
||||
$(this).parent().siblings().removeClass("expand");
|
||||
$(this).parent().toggleClass("expand");
|
||||
});
|
||||
|
||||
$(".sidebar .nav > .has-sub .has-sub > a").click(function () {
|
||||
$(this).parent().toggleClass("expand");
|
||||
});
|
||||
}
|
||||
|
||||
/*======== 4. SIDEBAR TOGGLE FOR MOBILE ========*/
|
||||
if ($(window).width() < 768) {
|
||||
$(document).on("click", ".sidebar-toggle", function (e) {
|
||||
e.preventDefault();
|
||||
var min = "sidebar-mobile-in",
|
||||
min_out = "sidebar-mobile-out",
|
||||
body = "#body";
|
||||
$(body).hasClass(min)
|
||||
? $(body).removeClass(min).addClass(min_out)
|
||||
: $(body).addClass(min).removeClass(min_out);
|
||||
});
|
||||
}
|
||||
|
||||
/*======== 5. SIDEBAR TOGGLE FOR VARIOUS SIDEBAR LAYOUT ========*/
|
||||
var body = $("#body");
|
||||
if ($(window).width() >= 768) {
|
||||
if (typeof window.isMinified === "undefined") {
|
||||
window.isMinified = false;
|
||||
}
|
||||
if (typeof window.isCollapsed === "undefined") {
|
||||
window.isCollapsed = false;
|
||||
}
|
||||
|
||||
/*======== 2. MOBILE OVERLAY ========*/
|
||||
if ($(window).width() < 768) {
|
||||
$(".sidebar-toggle").on("click", function () {
|
||||
$("body").css("overflow", "hidden");
|
||||
$('body').prepend('<div class="mobile-sticky-body-overlay"></div>')
|
||||
});
|
||||
|
||||
$(document).on("click", '.mobile-sticky-body-overlay', function (e) {
|
||||
$(this).remove();
|
||||
$("#body").removeClass("sidebar-mobile-in").addClass("sidebar-mobile-out");
|
||||
$("body").css("overflow", "auto");
|
||||
});
|
||||
}
|
||||
|
||||
/*======== 3. SIDEBAR MENU ========*/
|
||||
var sidebar = $(".sidebar")
|
||||
if (sidebar.length != 0) {
|
||||
$(".sidebar .nav > .has-sub > a").click(function () {
|
||||
$(this).parent().siblings().removeClass('expand')
|
||||
$(this).parent().toggleClass('expand')
|
||||
})
|
||||
|
||||
$(".sidebar .nav > .has-sub .has-sub > a").click(function () {
|
||||
$(this).parent().toggleClass('expand')
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/*======== 4. SIDEBAR TOGGLE FOR MOBILE ========*/
|
||||
if ($(window).width() < 768) {
|
||||
$(document).on("click", ".sidebar-toggle", function (e) {
|
||||
e.preventDefault();
|
||||
var min = "sidebar-mobile-in",
|
||||
min_out = "sidebar-mobile-out",
|
||||
body = "#body";
|
||||
$(body).hasClass(min)
|
||||
? $(body)
|
||||
.removeClass(min)
|
||||
.addClass(min_out)
|
||||
: $(body)
|
||||
.addClass(min)
|
||||
.removeClass(min_out)
|
||||
});
|
||||
}
|
||||
|
||||
/*======== 5. SIDEBAR TOGGLE FOR VARIOUS SIDEBAR LAYOUT ========*/
|
||||
var body = $("#body");
|
||||
if ($(window).width() >= 768) {
|
||||
|
||||
if (typeof window.isMinified === "undefined") {
|
||||
window.isMinified = false;
|
||||
$("#sidebar-toggler").on("click", function () {
|
||||
if (
|
||||
body.hasClass("sidebar-fixed-offcanvas") ||
|
||||
body.hasClass("sidebar-static-offcanvas")
|
||||
) {
|
||||
$(this)
|
||||
.addClass("sidebar-offcanvas-toggle")
|
||||
.removeClass("sidebar-toggle");
|
||||
if (window.isCollapsed === false) {
|
||||
body.addClass("sidebar-collapse");
|
||||
window.isCollapsed = true;
|
||||
window.isMinified = false;
|
||||
} else {
|
||||
body.removeClass("sidebar-collapse");
|
||||
body.addClass("sidebar-collapse-out");
|
||||
setTimeout(function () {
|
||||
body.removeClass("sidebar-collapse-out");
|
||||
}, 300);
|
||||
window.isCollapsed = false;
|
||||
}
|
||||
if (typeof window.isCollapsed === "undefined") {
|
||||
window.isCollapsed = false;
|
||||
}
|
||||
|
||||
if (body.hasClass("sidebar-fixed") || body.hasClass("sidebar-static")) {
|
||||
$(this)
|
||||
.addClass("sidebar-toggle")
|
||||
.removeClass("sidebar-offcanvas-toggle");
|
||||
if (window.isMinified === false) {
|
||||
body
|
||||
.removeClass("sidebar-collapse sidebar-minified-out")
|
||||
.addClass("sidebar-minified");
|
||||
window.isMinified = true;
|
||||
window.isCollapsed = false;
|
||||
} else {
|
||||
body.removeClass("sidebar-minified");
|
||||
body.addClass("sidebar-minified-out");
|
||||
window.isMinified = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#sidebar-toggler").on("click", function () {
|
||||
if (
|
||||
body.hasClass("sidebar-fixed-offcanvas") ||
|
||||
body.hasClass("sidebar-static-offcanvas")
|
||||
) {
|
||||
$(this)
|
||||
.addClass("sidebar-offcanvas-toggle")
|
||||
.removeClass("sidebar-toggle");
|
||||
if (window.isCollapsed === false) {
|
||||
body.addClass("sidebar-collapse");
|
||||
window.isCollapsed = true;
|
||||
window.isMinified = false;
|
||||
} else {
|
||||
body.removeClass("sidebar-collapse");
|
||||
body.addClass("sidebar-collapse-out");
|
||||
setTimeout(function () {
|
||||
body.removeClass("sidebar-collapse-out");
|
||||
}, 300);
|
||||
window.isCollapsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
body.hasClass("sidebar-fixed") ||
|
||||
body.hasClass("sidebar-static")
|
||||
) {
|
||||
$(this)
|
||||
.addClass("sidebar-toggle")
|
||||
.removeClass("sidebar-offcanvas-toggle");
|
||||
if (window.isMinified === false) {
|
||||
body
|
||||
.removeClass("sidebar-collapse sidebar-minified-out")
|
||||
.addClass("sidebar-minified");
|
||||
window.isMinified = true;
|
||||
window.isCollapsed = false;
|
||||
} else {
|
||||
body.removeClass("sidebar-minified");
|
||||
body.addClass("sidebar-minified-out");
|
||||
window.isMinified = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
if ($(window).width() >= 768 && $(window).width() < 992) {
|
||||
if (body.hasClass("sidebar-fixed") || body.hasClass("sidebar-static")) {
|
||||
body
|
||||
.removeClass("sidebar-collapse sidebar-minified-out")
|
||||
.addClass("sidebar-minified");
|
||||
window.isMinified = true;
|
||||
}
|
||||
|
||||
if ($(window).width() >= 768 && $(window).width() < 992) {
|
||||
if (
|
||||
body.hasClass("sidebar-fixed") ||
|
||||
body.hasClass("sidebar-static")
|
||||
) {
|
||||
body
|
||||
.removeClass("sidebar-collapse sidebar-minified-out")
|
||||
.addClass("sidebar-minified");
|
||||
window.isMinified = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,157 +1,160 @@
|
|||
Distribyted.config = {
|
||||
_editor: null,
|
||||
_infoDiv: document.getElementById("distribyted-reload-info-text"),
|
||||
_loadingInfoDom: document.getElementById("distribyted-reload-info-loading"),
|
||||
_valid: function () {
|
||||
if (this._editor == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
let getYamlCodeValidationErrors = (code) => {
|
||||
var error = "";
|
||||
try {
|
||||
jsyaml.safeLoad(code);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
let code = this._editor.getValue();
|
||||
let error = getYamlCodeValidationErrors(code);
|
||||
if (error) {
|
||||
this._editor.getSession().setAnnotations([
|
||||
{
|
||||
row: error.mark.line,
|
||||
column: error.mark.column,
|
||||
text: error.reason,
|
||||
type: "error",
|
||||
},
|
||||
]);
|
||||
|
||||
return false;
|
||||
} else {
|
||||
this._editor.getSession().setAnnotations([]);
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
save: function () {
|
||||
fetch("/api/config", {
|
||||
method: "POST",
|
||||
body: this._editor.getValue(),
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
Distribyted.message.info("Configuration saved");
|
||||
} else {
|
||||
Distribyted.message.error(
|
||||
"Error saving configuration file. Response: " + response.status
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
Distribyted.message.error("Error saving configuration file: " + error.message);
|
||||
});
|
||||
},
|
||||
|
||||
reload: function () {
|
||||
this.cleanInfo();
|
||||
fetch("/api/reload", {
|
||||
method: "POST",
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
Distribyted.config.showInfo("Error reloading server. Response: " + response.status, "ko");
|
||||
}
|
||||
})
|
||||
.then(function (json) {
|
||||
Distribyted.config.showInfo(json.message, "ok");
|
||||
})
|
||||
.catch(function (error) {
|
||||
Distribyted.message.error("Error reloading server: " + error.message);
|
||||
});
|
||||
},
|
||||
|
||||
cleanInfo: function () {
|
||||
this._loadingInfoDom.style.display = "block";
|
||||
this._infoDiv.innerText = ""
|
||||
},
|
||||
|
||||
showInfo: function (message, flag) {
|
||||
const li = document.createElement("li");
|
||||
li.innerText = message;
|
||||
li.className = "list-group-item";
|
||||
if (flag == "ok") {
|
||||
li.className += " list-group-item-success";
|
||||
} else if (flag == "ko") {
|
||||
li.className += " list-group-item-danger";
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
this._loadingInfoDom.style.display = "none";
|
||||
}
|
||||
|
||||
this._infoDiv.appendChild(li);
|
||||
},
|
||||
|
||||
loadView: function () {
|
||||
this._editor = ace.edit("editor");
|
||||
this._editor.getSession().setMode("ace/mode/yaml");
|
||||
this._editor.setShowPrintMargin(false);
|
||||
this._editor.setOptions({
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: false,
|
||||
|
||||
autoScrollEditorIntoView: true,
|
||||
fontSize: "16px",
|
||||
maxLines: 100,
|
||||
wrap: true,
|
||||
});
|
||||
|
||||
this._editor.commands.addCommand({
|
||||
name: "save",
|
||||
bindKey: { win: "Ctrl-S", mac: "Command-S" },
|
||||
exec: function (editor) {
|
||||
if (Distribyted.config._valid()) {
|
||||
Distribyted.config.save();
|
||||
} else {
|
||||
Distribyted.message.error("Check file format errors before saving");
|
||||
}
|
||||
},
|
||||
readOnly: false,
|
||||
});
|
||||
|
||||
this._editor.on("change", () => {
|
||||
Distribyted.config._valid();
|
||||
});
|
||||
|
||||
fetch("/api/config")
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.text();
|
||||
} else {
|
||||
Distribyted.message.error(
|
||||
"Error getting data from server. Response: " + response.status
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(function (yaml) {
|
||||
Distribyted.config._editor.setValue(yaml);
|
||||
})
|
||||
.catch(function (error) {
|
||||
Distribyted.message.error("Error getting yaml from server: " + error.message);
|
||||
});
|
||||
|
||||
var stream = new EventSource("/api/events");
|
||||
stream.addEventListener("event", function (e) {
|
||||
Distribyted.config.showInfo(e.data);
|
||||
});
|
||||
tstor.config = {
|
||||
_editor: null,
|
||||
_infoDiv: document.getElementById("tstor-reload-info-text"),
|
||||
_loadingInfoDom: document.getElementById("tstor-reload-info-loading"),
|
||||
_valid: function () {
|
||||
if (this._editor == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let getYamlCodeValidationErrors = (code) => {
|
||||
var error = "";
|
||||
try {
|
||||
jsyaml.safeLoad(code);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
return error;
|
||||
};
|
||||
|
||||
}
|
||||
let code = this._editor.getValue();
|
||||
let error = getYamlCodeValidationErrors(code);
|
||||
if (error) {
|
||||
this._editor.getSession().setAnnotations([
|
||||
{
|
||||
row: error.mark.line,
|
||||
column: error.mark.column,
|
||||
text: error.reason,
|
||||
type: "error",
|
||||
},
|
||||
]);
|
||||
|
||||
return false;
|
||||
} else {
|
||||
this._editor.getSession().setAnnotations([]);
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
save: function () {
|
||||
fetch("/api/config", {
|
||||
method: "POST",
|
||||
body: this._editor.getValue(),
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
tstor.message.info("Configuration saved");
|
||||
} else {
|
||||
tstor.message.error(
|
||||
"Error saving configuration file. Response: " + response.status
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
tstor.message.error(
|
||||
"Error saving configuration file: " + error.message
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
reload: function () {
|
||||
this.cleanInfo();
|
||||
fetch("/api/reload", {
|
||||
method: "POST",
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
tstor.config.showInfo(
|
||||
"Error reloading server. Response: " + response.status,
|
||||
"ko"
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(function (json) {
|
||||
tstor.config.showInfo(json.message, "ok");
|
||||
})
|
||||
.catch(function (error) {
|
||||
tstor.message.error("Error reloading server: " + error.message);
|
||||
});
|
||||
},
|
||||
|
||||
cleanInfo: function () {
|
||||
this._loadingInfoDom.style.display = "block";
|
||||
this._infoDiv.innerText = "";
|
||||
},
|
||||
|
||||
showInfo: function (message, flag) {
|
||||
const li = document.createElement("li");
|
||||
li.innerText = message;
|
||||
li.className = "list-group-item";
|
||||
if (flag == "ok") {
|
||||
li.className += " list-group-item-success";
|
||||
} else if (flag == "ko") {
|
||||
li.className += " list-group-item-danger";
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
this._loadingInfoDom.style.display = "none";
|
||||
}
|
||||
|
||||
this._infoDiv.appendChild(li);
|
||||
},
|
||||
|
||||
loadView: function () {
|
||||
this._editor = ace.edit("editor");
|
||||
this._editor.getSession().setMode("ace/mode/yaml");
|
||||
this._editor.setShowPrintMargin(false);
|
||||
this._editor.setOptions({
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: false,
|
||||
|
||||
autoScrollEditorIntoView: true,
|
||||
fontSize: "16px",
|
||||
maxLines: 100,
|
||||
wrap: true,
|
||||
});
|
||||
|
||||
this._editor.commands.addCommand({
|
||||
name: "save",
|
||||
bindKey: { win: "Ctrl-S", mac: "Command-S" },
|
||||
exec: function (editor) {
|
||||
if (tstor.config._valid()) {
|
||||
tstor.config.save();
|
||||
} else {
|
||||
tstor.message.error("Check file format errors before saving");
|
||||
}
|
||||
},
|
||||
readOnly: false,
|
||||
});
|
||||
|
||||
this._editor.on("change", () => {
|
||||
tstor.config._valid();
|
||||
});
|
||||
|
||||
fetch("/api/config")
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.text();
|
||||
} else {
|
||||
tstor.message.error(
|
||||
"Error getting data from server. Response: " + response.status
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(function (yaml) {
|
||||
tstor.config._editor.setValue(yaml);
|
||||
})
|
||||
.catch(function (error) {
|
||||
tstor.message.error("Error getting yaml from server: " + error.message);
|
||||
});
|
||||
|
||||
var stream = new EventSource("/api/events");
|
||||
stream.addEventListener("event", function (e) {
|
||||
tstor.config.showInfo(e.data);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,31 +1,39 @@
|
|||
GeneralChart.init();
|
||||
|
||||
Distribyted.dashboard = {
|
||||
_cacheChart: new CacheChart("main-cache-chart", "Cache disk"),
|
||||
loadView: function () {
|
||||
fetch('/api/status')
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
Distribyted.message.error('Error getting data from server. Response: ' + response.status)
|
||||
}
|
||||
}).then(function (stats) {
|
||||
var download = stats.torrentStats.downloadedBytes / stats.torrentStats.timePassed;
|
||||
var upload = stats.torrentStats.uploadedBytes / stats.torrentStats.timePassed;
|
||||
tstor.dashboard = {
|
||||
_cacheChart: new CacheChart("main-cache-chart", "Cache disk"),
|
||||
loadView: function () {
|
||||
fetch("/api/status")
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
tstor.message.error(
|
||||
"Error getting data from server. Response: " + response.status
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(function (stats) {
|
||||
var download =
|
||||
stats.torrentStats.downloadedBytes / stats.torrentStats.timePassed;
|
||||
var upload =
|
||||
stats.torrentStats.uploadedBytes / stats.torrentStats.timePassed;
|
||||
|
||||
GeneralChart.update(download, upload);
|
||||
GeneralChart.update(download, upload);
|
||||
|
||||
Distribyted.dashboard._cacheChart.update(stats.cacheFilled, stats.cacheCapacity - stats.cacheFilled);
|
||||
tstor.dashboard._cacheChart.update(
|
||||
stats.cacheFilled,
|
||||
stats.cacheCapacity - stats.cacheFilled
|
||||
);
|
||||
|
||||
document.getElementById("general-download-speed").innerText =
|
||||
Humanize.ibytes(download, 1024) + "/s";
|
||||
document.getElementById("general-download-speed").innerText =
|
||||
Humanize.ibytes(download, 1024) + "/s";
|
||||
|
||||
document.getElementById("general-upload-speed").innerText =
|
||||
Humanize.ibytes(upload, 1024) + "/s";
|
||||
})
|
||||
.catch(function (error) {
|
||||
Distribyted.message.error('Error getting status info: ' + error.message)
|
||||
});
|
||||
}
|
||||
}
|
||||
document.getElementById("general-upload-speed").innerText =
|
||||
Humanize.ibytes(upload, 1024) + "/s";
|
||||
})
|
||||
.catch(function (error) {
|
||||
tstor.message.error("Error getting status info: " + error.message);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,69 +1,88 @@
|
|||
Distribyted.logs = {
|
||||
loadView: function () {
|
||||
fetch("/api/log")
|
||||
.then(response => {
|
||||
if (response.ok) {
|
||||
return response.body.getReader();
|
||||
} else {
|
||||
response.json().then(json => {
|
||||
Distribyted.message.error('Error getting logs from server. Error: ' + json.error);
|
||||
}).catch(error => {
|
||||
Distribyted.message.error('Error getting logs from server. Error: ' + error);
|
||||
})
|
||||
}
|
||||
tstor.logs = {
|
||||
loadView: function () {
|
||||
fetch("/api/log")
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.body.getReader();
|
||||
} else {
|
||||
response
|
||||
.json()
|
||||
.then((json) => {
|
||||
tstor.message.error(
|
||||
"Error getting logs from server. Error: " + json.error
|
||||
);
|
||||
})
|
||||
.then(reader => {
|
||||
var decoder = new TextDecoder()
|
||||
var lastString = ''
|
||||
reader.read().then(function processText({ done, value }) {
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
.catch((error) => {
|
||||
tstor.message.error(
|
||||
"Error getting logs from server. Error: " + error
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
.then((reader) => {
|
||||
var decoder = new TextDecoder();
|
||||
var lastString = "";
|
||||
reader
|
||||
.read()
|
||||
.then(function processText({ done, value }) {
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
const string = `${lastString}${decoder.decode(value)}`
|
||||
const lines = string.split(/\r\n|[\r\n]/g)
|
||||
this.lastString = lines.pop() || ''
|
||||
const string = `${lastString}${decoder.decode(value)}`;
|
||||
const lines = string.split(/\r\n|[\r\n]/g);
|
||||
this.lastString = lines.pop() || "";
|
||||
|
||||
lines.forEach(element => {
|
||||
try {
|
||||
var json = JSON.parse(element)
|
||||
var properties = ""
|
||||
for (let [key, value] of Object.entries(json)) {
|
||||
if (key == "level" || key == "component" || key == "message" || key == "time") {
|
||||
continue
|
||||
}
|
||||
lines.forEach((element) => {
|
||||
try {
|
||||
var json = JSON.parse(element);
|
||||
var properties = "";
|
||||
for (let [key, value] of Object.entries(json)) {
|
||||
if (
|
||||
key == "level" ||
|
||||
key == "component" ||
|
||||
key == "message" ||
|
||||
key == "time"
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
properties += `<b>${key}</b>=${value} `
|
||||
}
|
||||
properties += `<b>${key}</b>=${value} `;
|
||||
}
|
||||
|
||||
var tableClass = "table-primary"
|
||||
switch (json.level) {
|
||||
case "info":
|
||||
tableClass = ""
|
||||
break;
|
||||
case "error":
|
||||
tableClass = "table-danger"
|
||||
break;
|
||||
case "warn":
|
||||
tableClass = "table-warning"
|
||||
break;
|
||||
case "debug":
|
||||
tableClass = "table-info"
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
template = `<tr class="${tableClass}"><td>${new Date(json.time*1000).toLocaleString()}</td><td>${json.level}</td><td>${json.component}</td><td>${json.message}</td><td>${properties}</td></tr>`;
|
||||
document.getElementById("log_table").innerHTML += template;
|
||||
} catch (err) {
|
||||
// server can send some corrupted json line
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
var tableClass = "table-primary";
|
||||
switch (json.level) {
|
||||
case "info":
|
||||
tableClass = "";
|
||||
break;
|
||||
case "error":
|
||||
tableClass = "table-danger";
|
||||
break;
|
||||
case "warn":
|
||||
tableClass = "table-warning";
|
||||
break;
|
||||
case "debug":
|
||||
tableClass = "table-info";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
template = `<tr class="${tableClass}"><td>${new Date(
|
||||
json.time * 1000
|
||||
).toLocaleString()}</td><td>${json.level}</td><td>${
|
||||
json.component
|
||||
}</td><td>${json.message}</td><td>${properties}</td></tr>`;
|
||||
document.getElementById("log_table").innerHTML += template;
|
||||
} catch (err) {
|
||||
// server can send some corrupted json line
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return reader.read().then(processText);
|
||||
}).catch(err => console.log(err));
|
||||
}).catch(err => console.log(err));
|
||||
}
|
||||
}
|
||||
return reader.read().then(processText);
|
||||
})
|
||||
.catch((err) => console.log(err));
|
||||
})
|
||||
.catch((err) => console.log(err));
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,186 +1,204 @@
|
|||
Handlebars.registerHelper("torrent_status", function (chunks, totalPieces) {
|
||||
const pieceStatus = {
|
||||
"H": { class: "bg-warning", tooltip: "checking pieces" },
|
||||
"P": { class: "bg-info", tooltip: "" },
|
||||
"C": { class: "bg-success", tooltip: "downloaded pieces" },
|
||||
"W": { class: "bg-transparent" },
|
||||
"?": { class: "bg-danger", tooltip: "erroed pieces" },
|
||||
};
|
||||
const chunksAsHTML = chunks.map(chunk => {
|
||||
const percentage = totalPieces * chunk.numPieces / 100;
|
||||
const pcMeta = pieceStatus[chunk.status]
|
||||
const pieceStatusClass = pcMeta.class;
|
||||
const pieceStatusTip = pcMeta.tooltip;
|
||||
const pieceStatus = {
|
||||
H: { class: "bg-warning", tooltip: "checking pieces" },
|
||||
P: { class: "bg-info", tooltip: "" },
|
||||
C: { class: "bg-success", tooltip: "downloaded pieces" },
|
||||
W: { class: "bg-transparent" },
|
||||
"?": { class: "bg-danger", tooltip: "erroed pieces" },
|
||||
};
|
||||
const chunksAsHTML = chunks.map((chunk) => {
|
||||
const percentage = (totalPieces * chunk.numPieces) / 100;
|
||||
const pcMeta = pieceStatus[chunk.status];
|
||||
const pieceStatusClass = pcMeta.class;
|
||||
const pieceStatusTip = pcMeta.tooltip;
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.className = "progress-bar " + pieceStatusClass;
|
||||
div.setAttribute("role", "progressbar");
|
||||
const div = document.createElement("div");
|
||||
div.className = "progress-bar " + pieceStatusClass;
|
||||
div.setAttribute("role", "progressbar");
|
||||
|
||||
if (pieceStatusTip) {
|
||||
div.setAttribute("data-toggle", "tooltip");
|
||||
div.setAttribute("data-placement", "top");
|
||||
div.setAttribute("title", pieceStatusTip);
|
||||
}
|
||||
if (pieceStatusTip) {
|
||||
div.setAttribute("data-toggle", "tooltip");
|
||||
div.setAttribute("data-placement", "top");
|
||||
div.setAttribute("title", pieceStatusTip);
|
||||
}
|
||||
|
||||
div.style.cssText = "width: " + percentage + "%";
|
||||
div.style.cssText = "width: " + percentage + "%";
|
||||
|
||||
return div.outerHTML;
|
||||
});
|
||||
return div.outerHTML;
|
||||
});
|
||||
|
||||
return '<div class="progress mb-3">' + chunksAsHTML.join("\n"); + '</div>'
|
||||
return '<div class="progress mb-3">' + chunksAsHTML.join("\n");
|
||||
+"</div>";
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("torrent_info", function (peers, seeders, pieceSize) {
|
||||
const MB = 1048576;
|
||||
const MB = 1048576;
|
||||
|
||||
var messages = [];
|
||||
var messages = [];
|
||||
|
||||
var errorLevels = [];
|
||||
const seedersMsg = "- Number of seeders is too low (" + seeders + ")."
|
||||
if (seeders < 2) {
|
||||
errorLevels[0] = 2;
|
||||
messages.push(seedersMsg);
|
||||
} else if (seeders >= 2 && seeders < 4) {
|
||||
errorLevels[0] = 1;
|
||||
messages.push(seedersMsg);
|
||||
} else {
|
||||
errorLevels[0] = 0;
|
||||
}
|
||||
var errorLevels = [];
|
||||
const seedersMsg = "- Number of seeders is too low (" + seeders + ").";
|
||||
if (seeders < 2) {
|
||||
errorLevels[0] = 2;
|
||||
messages.push(seedersMsg);
|
||||
} else if (seeders >= 2 && seeders < 4) {
|
||||
errorLevels[0] = 1;
|
||||
messages.push(seedersMsg);
|
||||
} else {
|
||||
errorLevels[0] = 0;
|
||||
}
|
||||
|
||||
const pieceSizeMsg = "- Piece size is too big (" + Humanize.bytes(pieceSize, 1024) + "). Recommended size is 1MB or less."
|
||||
if (pieceSize <= MB) {
|
||||
errorLevels[1] = 0;
|
||||
} else if (pieceSize > MB && pieceSize < (MB * 4)) {
|
||||
errorLevels[1] = 1;
|
||||
messages.push(pieceSizeMsg);
|
||||
} else {
|
||||
errorLevels[2] = 2;
|
||||
messages.push(pieceSizeMsg);
|
||||
}
|
||||
const pieceSizeMsg =
|
||||
"- Piece size is too big (" +
|
||||
Humanize.bytes(pieceSize, 1024) +
|
||||
"). Recommended size is 1MB or less.";
|
||||
if (pieceSize <= MB) {
|
||||
errorLevels[1] = 0;
|
||||
} else if (pieceSize > MB && pieceSize < MB * 4) {
|
||||
errorLevels[1] = 1;
|
||||
messages.push(pieceSizeMsg);
|
||||
} else {
|
||||
errorLevels[2] = 2;
|
||||
messages.push(pieceSizeMsg);
|
||||
}
|
||||
|
||||
const level = ["text-success", "text-warning", "text-danger"];
|
||||
const icon = ["mdi-check", "mdi-alert", "mdi-alert-octagram"];
|
||||
const div = document.createElement("div");
|
||||
const i = document.createElement("i");
|
||||
const level = ["text-success", "text-warning", "text-danger"];
|
||||
const icon = ["mdi-check", "mdi-alert", "mdi-alert-octagram"];
|
||||
const div = document.createElement("div");
|
||||
const i = document.createElement("i");
|
||||
|
||||
const errIndex = Math.max(...errorLevels);
|
||||
const errIndex = Math.max(...errorLevels);
|
||||
|
||||
i.className = "mdi " + icon[errIndex];
|
||||
i.title = messages.join("\n");
|
||||
i.className = "mdi " + icon[errIndex];
|
||||
i.title = messages.join("\n");
|
||||
|
||||
const text = document.createTextNode(peers + "/" + seeders + " (" + Humanize.bytes(pieceSize, 1024) + " chunks) ");
|
||||
const text = document.createTextNode(
|
||||
peers + "/" + seeders + " (" + Humanize.bytes(pieceSize, 1024) + " chunks) "
|
||||
);
|
||||
|
||||
div.className = level[errIndex];
|
||||
div.appendChild(text);
|
||||
div.appendChild(i);
|
||||
div.className = level[errIndex];
|
||||
div.appendChild(text);
|
||||
div.appendChild(i);
|
||||
|
||||
return div.outerHTML;
|
||||
return div.outerHTML;
|
||||
});
|
||||
|
||||
Distribyted.routes = {
|
||||
_template: null,
|
||||
tstor.routes = {
|
||||
_template: null,
|
||||
|
||||
_getTemplate: function () {
|
||||
if (this._template != null) {
|
||||
return this._template
|
||||
}
|
||||
|
||||
const tTemplate = fetch('/assets/templates/routes.html')
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.text();
|
||||
} else {
|
||||
Distribyted.message.error('Error getting data from server. Response: ' + response.status);
|
||||
}
|
||||
})
|
||||
.then((t) => {
|
||||
return Handlebars.compile(t);
|
||||
})
|
||||
.catch(error => {
|
||||
Distribyted.message.error('Error getting routes template: ' + error.message);
|
||||
});
|
||||
|
||||
this._template = tTemplate;
|
||||
return tTemplate;
|
||||
},
|
||||
|
||||
_getRoutesJson: function () {
|
||||
return fetch('/api/routes')
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
Distribyted.message.error('Error getting data from server. Response: ' + response.status)
|
||||
}
|
||||
}).then(function (routes) {
|
||||
return routes;
|
||||
})
|
||||
.catch(function (error) {
|
||||
Distribyted.message.error('Error getting status info: ' + error.message)
|
||||
});
|
||||
},
|
||||
|
||||
deleteTorrent: function (route, torrentHash) {
|
||||
var url = '/api/routes/' + route + '/torrent/' + torrentHash
|
||||
|
||||
return fetch(url, {
|
||||
method: 'DELETE'
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
Distribyted.message.info('Torrent deleted.')
|
||||
Distribyted.routes.loadView();
|
||||
} else {
|
||||
response.json().then(json => {
|
||||
Distribyted.message.error('Error deletting torrent. Response: ' + json.error)
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
Distribyted.message.error('Error deletting torrent: ' + error.message)
|
||||
});
|
||||
},
|
||||
|
||||
loadView: function () {
|
||||
this._getTemplate()
|
||||
.then(t =>
|
||||
this._getRoutesJson().then(routes => {
|
||||
document.getElementById('template_target').innerHTML = t(routes);
|
||||
})
|
||||
);
|
||||
_getTemplate: function () {
|
||||
if (this._template != null) {
|
||||
return this._template;
|
||||
}
|
||||
}
|
||||
|
||||
const tTemplate = fetch("/assets/templates/routes.html")
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.text();
|
||||
} else {
|
||||
tstor.message.error(
|
||||
"Error getting data from server. Response: " + response.status
|
||||
);
|
||||
}
|
||||
})
|
||||
.then((t) => {
|
||||
return Handlebars.compile(t);
|
||||
})
|
||||
.catch((error) => {
|
||||
tstor.message.error("Error getting routes template: " + error.message);
|
||||
});
|
||||
|
||||
this._template = tTemplate;
|
||||
return tTemplate;
|
||||
},
|
||||
|
||||
_getRoutesJson: function () {
|
||||
return fetch("/api/routes")
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
tstor.message.error(
|
||||
"Error getting data from server. Response: " + response.status
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(function (routes) {
|
||||
return routes;
|
||||
})
|
||||
.catch(function (error) {
|
||||
tstor.message.error("Error getting status info: " + error.message);
|
||||
});
|
||||
},
|
||||
|
||||
deleteTorrent: function (route, torrentHash) {
|
||||
var url = "/api/routes/" + route + "/torrent/" + torrentHash;
|
||||
|
||||
return fetch(url, {
|
||||
method: "DELETE",
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
tstor.message.info("Torrent deleted.");
|
||||
tstor.routes.loadView();
|
||||
} else {
|
||||
response.json().then((json) => {
|
||||
tstor.message.error(
|
||||
"Error deletting torrent. Response: " + json.error
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
tstor.message.error("Error deletting torrent: " + error.message);
|
||||
});
|
||||
},
|
||||
|
||||
loadView: function () {
|
||||
this._getTemplate().then((t) =>
|
||||
this._getRoutesJson().then((routes) => {
|
||||
document.getElementById("template_target").innerHTML = t(routes);
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
$("#new-magnet").submit(function (event) {
|
||||
event.preventDefault();
|
||||
event.preventDefault();
|
||||
|
||||
let route = $("#route-string :selected").val()
|
||||
let magnet = $("#magnet-url").val()
|
||||
let route = $("#route-string :selected").val();
|
||||
let magnet = $("#magnet-url").val();
|
||||
|
||||
let url = '/api/routes/' + route + '/torrent'
|
||||
let body = JSON.stringify({ magnet: magnet })
|
||||
let url = "/api/routes/" + route + "/torrent";
|
||||
let body = JSON.stringify({ magnet: magnet });
|
||||
|
||||
document.getElementById("submit_magnet_loading").style = "display:block"
|
||||
document.getElementById("submit_magnet_loading").style = "display:block";
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
body: body
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
body: body,
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
tstor.message.info("New magnet added.");
|
||||
tstor.routes.loadView();
|
||||
} else {
|
||||
response
|
||||
.json()
|
||||
.then((json) => {
|
||||
tstor.message.error(
|
||||
"Error adding new magnet. Response: " + json.error
|
||||
);
|
||||
})
|
||||
.catch(function (error) {
|
||||
tstor.message.error("Error adding new magnet: " + response.status);
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
Distribyted.message.info('New magnet added.')
|
||||
Distribyted.routes.loadView();
|
||||
} else {
|
||||
response.json().then(json => {
|
||||
Distribyted.message.error('Error adding new magnet. Response: ' + json.error)
|
||||
}).catch(function (error) {
|
||||
Distribyted.message.error('Error adding new magnet: ' + response.status)
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
Distribyted.message.error('Error adding torrent: ' + error.message)
|
||||
}).then(function () {
|
||||
document.getElementById("submit_magnet_loading").style = "display:none"
|
||||
});
|
||||
});
|
||||
.catch(function (error) {
|
||||
tstor.message.error("Error adding torrent: " + error.message);
|
||||
})
|
||||
.then(function () {
|
||||
document.getElementById("submit_magnet_loading").style = "display:none";
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,54 +1,57 @@
|
|||
Handlebars.registerHelper("to_date", function (timestamp) {
|
||||
return new Date(timestamp * 1000).toLocaleString()
|
||||
return new Date(timestamp * 1000).toLocaleString();
|
||||
});
|
||||
|
||||
Distribyted.servers = {
|
||||
_template: null,
|
||||
tstor.servers = {
|
||||
_template: null,
|
||||
|
||||
_getTemplate: function () {
|
||||
if (this._template != null) {
|
||||
return this._template
|
||||
}
|
||||
|
||||
const tTemplate = fetch('/assets/templates/servers.html')
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.text();
|
||||
} else {
|
||||
Distribyted.message.error('Error getting data from server. Response: ' + response.status);
|
||||
}
|
||||
})
|
||||
.then((t) => {
|
||||
return Handlebars.compile(t);
|
||||
})
|
||||
.catch(error => {
|
||||
Distribyted.message.error('Error getting servers template: ' + error.message);
|
||||
});
|
||||
|
||||
this._template = tTemplate;
|
||||
return tTemplate;
|
||||
},
|
||||
|
||||
_getRoutesJson: function () {
|
||||
return fetch('/api/servers')
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
Distribyted.message.error('Error getting data from server. Response: ' + response.status)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
Distribyted.message.error('Error getting status info: ' + error.message)
|
||||
});
|
||||
},
|
||||
|
||||
loadView: function () {
|
||||
this._getTemplate()
|
||||
.then(t =>
|
||||
this._getRoutesJson().then(routes => {
|
||||
document.getElementById('template_target').innerHTML = t(routes);
|
||||
})
|
||||
);
|
||||
_getTemplate: function () {
|
||||
if (this._template != null) {
|
||||
return this._template;
|
||||
}
|
||||
}
|
||||
|
||||
const tTemplate = fetch("/assets/templates/servers.html")
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.text();
|
||||
} else {
|
||||
tstor.message.error(
|
||||
"Error getting data from server. Response: " + response.status
|
||||
);
|
||||
}
|
||||
})
|
||||
.then((t) => {
|
||||
return Handlebars.compile(t);
|
||||
})
|
||||
.catch((error) => {
|
||||
tstor.message.error("Error getting servers template: " + error.message);
|
||||
});
|
||||
|
||||
this._template = tTemplate;
|
||||
return tTemplate;
|
||||
},
|
||||
|
||||
_getRoutesJson: function () {
|
||||
return fetch("/api/servers")
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
tstor.message.error(
|
||||
"Error getting data from server. Response: " + response.status
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
tstor.message.error("Error getting status info: " + error.message);
|
||||
});
|
||||
},
|
||||
|
||||
loadView: function () {
|
||||
this._getTemplate().then((t) =>
|
||||
this._getRoutesJson().then((routes) => {
|
||||
document.getElementById("template_target").innerHTML = t(routes);
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue