bunkerweb 1.4.0
This commit is contained in:
1780
ui/static/js/939.js
Normal file
1780
ui/static/js/939.js
Normal file
File diff suppressed because it is too large
Load Diff
8
ui/static/js/bootstrap-datepicker.min.js
vendored
Normal file
8
ui/static/js/bootstrap-datepicker.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
5
ui/static/js/bootstrap.bundle.min.js
vendored
5
ui/static/js/bootstrap.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
27
ui/static/js/cache.js
Normal file
27
ui/static/js/cache.js
Normal file
@@ -0,0 +1,27 @@
|
||||
var editor_path = "";
|
||||
|
||||
$(document).ready(function () {
|
||||
$("textarea").numberedtextarea({ allowTabChar: true });
|
||||
|
||||
$("#modal-see-file").on("show.bs.modal", function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var path = button.data("path");
|
||||
var content = button.data("content");
|
||||
$("#modal-see-file-label").html(`File: ${path}`);
|
||||
|
||||
if (editor_path != path) {
|
||||
$("#editor").html(atob(content));
|
||||
}
|
||||
|
||||
editor_path = path;
|
||||
});
|
||||
|
||||
$(".download-button").click(function () {
|
||||
var filepath = $(this).attr("data-path");
|
||||
windows.open(`${location.href}/download?path=${filepath}`, "_blank");
|
||||
});
|
||||
|
||||
$(".collapse-div").click(function () {
|
||||
$(this).find(".rotate-icon").toggleClass("down");
|
||||
});
|
||||
});
|
||||
96
ui/static/js/configs.js
Normal file
96
ui/static/js/configs.js
Normal file
@@ -0,0 +1,96 @@
|
||||
var editor_path = "";
|
||||
var decoder = new TextDecoder("utf-8");
|
||||
|
||||
$(document).ready(function () {
|
||||
$("textarea").numberedtextarea({ allowTabChar: true });
|
||||
|
||||
$("#modal-edit-new-file").on("show.bs.modal", function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var path = button.data("path");
|
||||
$("#file-path").val(path);
|
||||
var new_path = path.split("/");
|
||||
var name = new_path.pop().replace(".conf", "");
|
||||
var action = button.data("action");
|
||||
$("#file-operation").val(action);
|
||||
var content = button.data("content");
|
||||
$("#modal-edit-new-file-label").html(
|
||||
`<div class="d-flex align-items-center"><div class="flex-grow-1">${
|
||||
action == "edit" ? "Editing" : "New"
|
||||
} file: <span class="d-md-inline d-none">${
|
||||
action == "edit" ? new_path.join("/") : path
|
||||
}</span><span class="d-md-none">.../${
|
||||
action == "edit" ? new_path.pop() : path.split("/").pop()
|
||||
}</span>/</div><div class="d-sm-flex align-items-center"><input type="text" class="form-control" id="new-file-name" name="name" value="${
|
||||
action == "edit" ? name : ""
|
||||
}" placeholder="File name" required="" pattern="^[a-zA-Z0-9_-]{1,64}$" title="File name can only contain numbers, letters, underscores and hyphens (min 1 character and max 64)" />.conf</div></div>`
|
||||
);
|
||||
|
||||
var editor = $("#editor");
|
||||
|
||||
if (action == "edit") {
|
||||
if (editor_path != path) {
|
||||
editor.html(atob(content));
|
||||
}
|
||||
} else {
|
||||
editor.html("");
|
||||
}
|
||||
|
||||
editor.keyup();
|
||||
editor_path = path;
|
||||
});
|
||||
|
||||
$("#modal-edit-new-folder").on("show.bs.modal", function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var path = button.data("path");
|
||||
$("#folder-path").val(path);
|
||||
var action = button.data("action");
|
||||
$("#folder-operation").val(action);
|
||||
var foldername = path.split("/").pop();
|
||||
$("#modal-edit-new-folder-label").html(
|
||||
`<div class="d-flex align-items-center"><div class="flex-grow-1">${
|
||||
action == "edit" ? "Editing" : "New"
|
||||
} folder: <span class="d-md-inline d-none">${path}</span><span class="d-md-none">.../${path
|
||||
.split("/")
|
||||
.pop()}</span>/</div><div class="d-sm-flex align-items-center"><input type="text" class="form-control" id="new-folder-name" name="name" placeholder="Folder name" value="${
|
||||
action == "edit" ? foldername : ""
|
||||
}" required="" pattern="^[a-zA-Z0-9_-]{1,64}$" title="Folder name can only contain numbers, letters, underscores and hyphens (min 1 character and max 64)" /></div></div>`
|
||||
);
|
||||
});
|
||||
|
||||
$("#modal-delete").on("show.bs.modal", function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var path = button.data("path");
|
||||
$("#delete-path").val(path);
|
||||
var name = path.split("/").pop();
|
||||
$("#modal-delete-label").html(
|
||||
`Deleting ${name.includes(".") ? "file" : "folder"}`
|
||||
);
|
||||
$("#modal-delete-body").html(
|
||||
`Are you sure you want to delete <b>${path}</b> ?`
|
||||
);
|
||||
});
|
||||
|
||||
$(".collapse-div").click(function () {
|
||||
$(this).find(".rotate-icon").toggleClass("down");
|
||||
});
|
||||
|
||||
$("form").on("focus", ".form-control", function () {
|
||||
if ($(this).attr("type") == "text" && $(this).prop("validity").valid) {
|
||||
$(this).addClass("is-valid");
|
||||
}
|
||||
});
|
||||
|
||||
$("form").on("focusout", ".form-control", function () {
|
||||
if ($(this).attr("type") == "text") {
|
||||
$(this).removeClass("is-valid");
|
||||
}
|
||||
});
|
||||
|
||||
$("form").on("change", ".form-control", function () {
|
||||
if ($(this).attr("type") == "text" && !$(this).prop("validity").valid) {
|
||||
$(this).addClass("is-invalid");
|
||||
} else {
|
||||
$(this).removeClass("is-invalid");
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,122 +0,0 @@
|
||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
||||
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl, { container: 'body' })
|
||||
})
|
||||
|
||||
function post(operation, url, data) {
|
||||
var form = document.createElement("form");
|
||||
form.method = "POST";
|
||||
form.action = url;
|
||||
for (var key in data) {
|
||||
var field = document.createElement("input");
|
||||
field.type = "hidden";
|
||||
field.name = key;
|
||||
field.value = data[key];
|
||||
form.appendChild(field);
|
||||
}
|
||||
var field = document.createElement("input");
|
||||
field.type = "hidden";
|
||||
field.name = "operation";
|
||||
field.value = operation;
|
||||
form.appendChild(field);
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
}
|
||||
|
||||
function getData(id) {
|
||||
var elements = document.getElementById(id).elements;
|
||||
var data = {};
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
element = elements[i];
|
||||
if (element["type"] === "checkbox") {
|
||||
if (element["checked"]) {
|
||||
data[element["name"]] = "yes";
|
||||
}
|
||||
else {
|
||||
data[element["name"]] = "no";
|
||||
}
|
||||
}
|
||||
else {
|
||||
data[element["name"]] = element["value"];
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function newService() {
|
||||
post("new", "services", getData('form-new'));
|
||||
}
|
||||
|
||||
function editService(id) {
|
||||
post("edit", "services", getData('form-edit-' + id));
|
||||
}
|
||||
|
||||
function deleteService(id) {
|
||||
post("delete", "services", getData('form-delete-' + id));
|
||||
}
|
||||
|
||||
function reloadInstance(id) {
|
||||
post("reload", "instances", getData('form-instance-' + id));
|
||||
return false;
|
||||
}
|
||||
|
||||
function startInstance(id) {
|
||||
post("start", "instances", getData('form-instance-' + id));
|
||||
return false;
|
||||
}
|
||||
|
||||
function stopInstance(id) {
|
||||
post("stop", "instances", getData('form-instance-' + id));
|
||||
return false;
|
||||
}
|
||||
|
||||
function restartInstance(id) {
|
||||
post("restart", "instances", getData('form-instance-' + id));
|
||||
return false;
|
||||
}
|
||||
|
||||
function deleteInstance(id) {
|
||||
post("delete", "instances", getData('form-instance-' + id));
|
||||
return false;
|
||||
}
|
||||
|
||||
var multiples = {};
|
||||
function addMultiple(id, paramsEnc) {
|
||||
var params = JSON.parse(paramsEnc);
|
||||
var div = document.getElementById(id);
|
||||
if (!multiples.hasOwnProperty(id)) {
|
||||
multiples[id] = 0;
|
||||
}
|
||||
multiples[id]++;
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var input = "";
|
||||
var input_id = id + "-" + params[i]["id"] + "-" + multiples[id].toString();
|
||||
var input_name = params[i]["env"] + "_" + multiples[id].toString();
|
||||
var input_label = params[i]["label"] + " #" + multiples[id].toString();
|
||||
var input_value = params[i]["default"];
|
||||
var pt = "";
|
||||
if (params[i]["type"] == "text") {
|
||||
input = `<input type="text" class="form-control" id="${input_id}" value="${input_value}" name="${input_name}">`;
|
||||
}
|
||||
else if (params[i]["type"] == "checkbox") {
|
||||
if (input_value == "yes") {
|
||||
input_value = "checked";
|
||||
}
|
||||
input = `<div class="form-check form-switch"><input type="checkbox" class="form-check-input" id="${input_id}" name="${input_name}" ${input_value}></div>`;
|
||||
pt = "pt-0";
|
||||
}
|
||||
div.insertAdjacentHTML('beforeend', `<label for="${input_id}" class="col-4 col-form-label ${pt} mb-3" id="label-${input_id}">${input_label}</label><div class="col-8 mb-3" id="input-${input_id}">${input}</div>`);
|
||||
}
|
||||
}
|
||||
|
||||
function delMultiple(id, paramsEnc) {
|
||||
if (multiples.hasOwnProperty(id) && multiples[id] > 0) {
|
||||
var params = JSON.parse(paramsEnc);
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var input_id = id + "-" + params[i]["id"] + "-" + multiples[id].toString();
|
||||
document.getElementById("label-" + input_id).remove();
|
||||
document.getElementById("input-" + input_id).remove();
|
||||
}
|
||||
multiples[id]--;
|
||||
}
|
||||
}
|
||||
45
ui/static/js/darkmode.js
Normal file
45
ui/static/js/darkmode.js
Normal file
@@ -0,0 +1,45 @@
|
||||
window.onload = init;
|
||||
|
||||
var darkMode = document.getElementById("dark-mode-switch");
|
||||
|
||||
var darkModeIcon = "darkModeIcon";
|
||||
|
||||
function init() {
|
||||
if (darkMode) {
|
||||
initTheme();
|
||||
darkMode.addEventListener("change", function () {
|
||||
resetTheme();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function initTheme() {
|
||||
var darkThemeSelected =
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches ||
|
||||
(localStorage.getItem("dark-mode") !== null &&
|
||||
localStorage.getItem("dark-mode") === "dark");
|
||||
|
||||
darkMode.checked = darkThemeSelected;
|
||||
|
||||
darkThemeSelected
|
||||
? document.body.setAttribute("data-theme", "dark")
|
||||
: document.body.removeAttribute("data-theme");
|
||||
|
||||
darkThemeSelected
|
||||
? document.getElementById(darkModeIcon).classList.add("bi-moon")
|
||||
: document.getElementById(darkModeIcon).classList.add("bi-sun");
|
||||
}
|
||||
|
||||
function resetTheme() {
|
||||
if (darkMode.checked) {
|
||||
document.body.setAttribute("data-theme", "dark");
|
||||
localStorage.setItem("dark-mode", "dark");
|
||||
document.getElementById(darkModeIcon).classList.remove("bi-sun");
|
||||
document.getElementById(darkModeIcon).classList.add("bi-moon");
|
||||
} else {
|
||||
document.body.removeAttribute("data-theme");
|
||||
localStorage.removeItem("dark-mode");
|
||||
document.getElementById(darkModeIcon).classList.remove("bi-moon");
|
||||
document.getElementById(darkModeIcon).classList.add("bi-sun");
|
||||
}
|
||||
}
|
||||
6
ui/static/js/fa.all.min.js
vendored
Normal file
6
ui/static/js/fa.all.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
ui/static/js/jquery.min.js
vendored
Normal file
2
ui/static/js/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
146
ui/static/js/jquery.numberedtextarea.js
Normal file
146
ui/static/js/jquery.numberedtextarea.js
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* NumberedTextarea - jQuery Plugin
|
||||
* Textarea with line numbering
|
||||
*
|
||||
* Copyright (c) 2015 Dariusz Arciszewski
|
||||
*
|
||||
* Requires: jQuery v2.0+
|
||||
*
|
||||
* Licensed under the GPL licenses:
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
$.fn.numberedtextarea = function(options) {
|
||||
|
||||
var settings = $.extend({
|
||||
color: null, // Font color
|
||||
borderColor: null, // Border color
|
||||
class: null, // Add class to the 'numberedtextarea-wrapper'
|
||||
allowTabChar: false, // If true Tab key creates indentation
|
||||
}, options);
|
||||
|
||||
this.each(function() {
|
||||
if(this.nodeName.toLowerCase() !== "textarea") {
|
||||
console.log('This is not a <textarea>, so no way Jose...');
|
||||
return false;
|
||||
}
|
||||
|
||||
addWrapper(this, settings);
|
||||
addLineNumbers(this, settings);
|
||||
|
||||
if(settings.allowTabChar) {
|
||||
$(this).allowTabChar();
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
$.fn.allowTabChar = function() {
|
||||
if (this.jquery) {
|
||||
this.each(function() {
|
||||
if (this.nodeType == 1) {
|
||||
var nodeName = this.nodeName.toLowerCase();
|
||||
if (nodeName == "textarea" || (nodeName == "input" && this.type == "text")) {
|
||||
allowTabChar(this);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
function addWrapper(element, settings) {
|
||||
var wrapper = $('<div class="numberedtextarea-wrapper"></div>').insertAfter(element);
|
||||
$(element).detach().appendTo(wrapper);
|
||||
}
|
||||
|
||||
function addLineNumbers(element, settings) {
|
||||
element = $(element);
|
||||
|
||||
var wrapper = element.parents('.numberedtextarea-wrapper');
|
||||
|
||||
// Get textarea styles to implement it on line numbers div
|
||||
var paddingLeft = parseFloat(element.css('padding-left'));
|
||||
var paddingTop = parseFloat(element.css('padding-top'));
|
||||
var paddingBottom = parseFloat(element.css('padding-bottom'));
|
||||
|
||||
var lineNumbers = $('<div class="numberedtextarea-line-numbers"></div>').insertAfter(element);
|
||||
|
||||
element.css({
|
||||
paddingLeft: paddingLeft + lineNumbers.width() + 'px'
|
||||
}).on('input propertychange change keyup paste', function() {
|
||||
renderLineNumbers(element, settings);
|
||||
}).on('scroll', function() {
|
||||
scrollLineNumbers(element, settings);
|
||||
});
|
||||
|
||||
lineNumbers.css({
|
||||
paddingLeft: paddingLeft + 'px',
|
||||
paddingTop: paddingTop + 'px',
|
||||
lineHeight: element.css('line-height'),
|
||||
fontFamily: element.css('font-family'),
|
||||
width: lineNumbers.width() - paddingLeft + 'px',
|
||||
});
|
||||
|
||||
element.trigger('change');
|
||||
}
|
||||
|
||||
function renderLineNumbers(element, settings) {
|
||||
element = $(element);
|
||||
|
||||
var linesDiv = element.parent().find('.numberedtextarea-line-numbers');
|
||||
var count = element.val().split("\n").length;
|
||||
var paddingBottom = parseFloat(element.css('padding-bottom'));
|
||||
|
||||
linesDiv.find('.numberedtextarea-number').remove();
|
||||
|
||||
for(i = 1; i<=count; i++) {
|
||||
var line = $('<div class="numberedtextarea-number numberedtextarea-number-' + i + '">' + i + '</div>').appendTo(linesDiv);
|
||||
|
||||
if(i === count) {
|
||||
line.css('margin-bottom', paddingBottom + 'px');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scrollLineNumbers(element, settings) {
|
||||
element = $(element);
|
||||
var linesDiv = element.parent().find('.numberedtextarea-line-numbers');
|
||||
linesDiv.scrollTop(element.scrollTop());
|
||||
}
|
||||
|
||||
function pasteIntoInput(el, text) {
|
||||
el.focus();
|
||||
if (typeof el.selectionStart == "number") {
|
||||
var val = el.value;
|
||||
var selStart = el.selectionStart;
|
||||
el.value = val.slice(0, selStart) + text + val.slice(el.selectionEnd);
|
||||
el.selectionEnd = el.selectionStart = selStart + text.length;
|
||||
} else if (typeof document.selection != "undefined") {
|
||||
var textRange = document.selection.createRange();
|
||||
textRange.text = text;
|
||||
textRange.collapse(false);
|
||||
textRange.select();
|
||||
}
|
||||
}
|
||||
|
||||
function allowTabChar(el) {
|
||||
$(el).keydown(function(e) {
|
||||
if (e.which == 9) {
|
||||
pasteIntoInput(this, "\t");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// For Opera, which only allows suppression of keypress events, not keydown
|
||||
$(el).keypress(function(e) {
|
||||
if (e.which == 9) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}(jQuery));
|
||||
165
ui/static/js/logs.js
Normal file
165
ui/static/js/logs.js
Normal file
@@ -0,0 +1,165 @@
|
||||
var current_container_id = null;
|
||||
var last_logs_update = null;
|
||||
var filter = "";
|
||||
var date_filter1 = "";
|
||||
var date_filter2 = "";
|
||||
|
||||
$(document).ready(function () {
|
||||
$("#date-picker").datepicker({ format: "yyyy/mm/dd" });
|
||||
current_container_id = $("#active-nav").data("container-id");
|
||||
const logs_interval = setInterval(load_logs, 1000);
|
||||
|
||||
function clear_filters() {
|
||||
filter = "";
|
||||
date_filter1 = "";
|
||||
date_filter2 = "";
|
||||
$("#logs-list li").filter(function () {
|
||||
$(this).toggle(true);
|
||||
});
|
||||
}
|
||||
|
||||
async function get_logs(container_id, last_update) {
|
||||
const response = await fetch(
|
||||
`${location.href}/${container_id}` +
|
||||
(last_update ? `?last_update=${last_update}` : "")
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
return await response.json();
|
||||
} else {
|
||||
console.log(`Error: ${response.status}`);
|
||||
clearInterval(logs_interval);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function load_logs() {
|
||||
logs = await get_logs(current_container_id, last_logs_update);
|
||||
|
||||
if (logs) {
|
||||
last_logs_update = logs.last_update;
|
||||
logs.logs.forEach((log) => {
|
||||
const log_element = document.createElement("li");
|
||||
log_element.className = "list-group-item";
|
||||
|
||||
if (log.type === "error") {
|
||||
log_element.classList.add("list-group-item-danger");
|
||||
} else if (log.type === "warning") {
|
||||
log_element.classList.add("list-group-item-warning");
|
||||
} else if (log.type === "info") {
|
||||
log_element.classList.add("list-group-item-info");
|
||||
}
|
||||
|
||||
log_element.innerHTML = log.content;
|
||||
|
||||
if (
|
||||
!(
|
||||
log.content.toLowerCase().indexOf(filter) > -1 &&
|
||||
(log.content.toLowerCase().indexOf(date_filter1) > -1 ||
|
||||
log.content.toLowerCase().indexOf(date_filter2) > -1)
|
||||
)
|
||||
) {
|
||||
log_element.style = "display: none;";
|
||||
}
|
||||
|
||||
if (log.separator) log_element.classList.add("pt-1");
|
||||
|
||||
document.getElementById("logs-list").appendChild(log_element);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$("#date-picker").on("changeDate", function () {
|
||||
let date = $(this).datepicker("getFormattedDate");
|
||||
|
||||
if (date) {
|
||||
date_filter1 = date;
|
||||
date_filter2 = date.replaceAll("/", "-");
|
||||
$("#date-input").val(date);
|
||||
$("#date-clear").show();
|
||||
$("#logs-list li").filter(function () {
|
||||
$(this).toggle(
|
||||
$(this).text().toLowerCase().indexOf(filter) > -1 &&
|
||||
($(this).text().toLowerCase().indexOf(date_filter1) > -1 ||
|
||||
$(this).text().toLowerCase().indexOf(date_filter2) > -1)
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#filter-input").on("keyup", function () {
|
||||
var val = $.trim(this.value);
|
||||
|
||||
if (!val) {
|
||||
val = "";
|
||||
|
||||
if (!$("#date-picker").datepicker("getFormattedDate")) {
|
||||
$("#date-clear").hide();
|
||||
}
|
||||
} else {
|
||||
$("#date-clear").show();
|
||||
}
|
||||
|
||||
val = val.toLowerCase();
|
||||
filter = val;
|
||||
$("#logs-list li").filter(function () {
|
||||
$(this).toggle(
|
||||
$(this).text().toLowerCase().indexOf(val) > -1 &&
|
||||
($(this).text().toLowerCase().indexOf(date_filter1) > -1 ||
|
||||
$(this).text().toLowerCase().indexOf(date_filter2) > -1)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
$("#date-clear").click(function () {
|
||||
$("#filter-input").val("");
|
||||
$("#date-input").val("");
|
||||
$(this).hide();
|
||||
clear_filters();
|
||||
});
|
||||
|
||||
$("#refresh-logs").click(function () {
|
||||
if ($(this).find("#rotate-icon").hasClass("rotate")) {
|
||||
$(this).find("#rotate-icon").removeClass("rotate");
|
||||
clearInterval(logs_interval);
|
||||
} else if (!$(this).find("#rotate-icon").hasClass("rotate")) {
|
||||
$(this).find("#rotate-icon").addClass("rotate");
|
||||
logs_interval = setInterval(load_logs, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
$(".container-selector").click(function () {
|
||||
clearInterval(logs_interval);
|
||||
current_container_id = $(this).data("container-id");
|
||||
$("#logs-list").empty();
|
||||
clear_filters();
|
||||
last_logs_update = null;
|
||||
let old_selector = $("#active-nav");
|
||||
old_selector.removeClass("active");
|
||||
old_selector.removeAttr("aria-current");
|
||||
old_selector.removeAttr("id");
|
||||
$(this).addClass("active");
|
||||
$(this).attr("aria-current", "page");
|
||||
$(this).attr("id", "active-nav");
|
||||
|
||||
if (current_container_id == "linux") {
|
||||
$("#date-picker").prop("disabled", true);
|
||||
} else {
|
||||
$("#date-picker").prop("disabled", false);
|
||||
}
|
||||
|
||||
load_logs();
|
||||
setTimeout(function () {
|
||||
logs_interval = setInterval(load_logs, 1000);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
$("#filter-input").on("keypress", function (e) {
|
||||
var code = e.keyCode || e.which;
|
||||
if (code == 13) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
46
ui/static/js/navbar.js
Normal file
46
ui/static/js/navbar.js
Normal file
@@ -0,0 +1,46 @@
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$(function () {
|
||||
var header = $(".start-style");
|
||||
$(window).scroll(function () {
|
||||
var scroll = $(window).scrollTop();
|
||||
|
||||
if (scroll >= 10) {
|
||||
header.removeClass("start-style").addClass("scroll-on");
|
||||
} else {
|
||||
header.removeClass("scroll-on").addClass("start-style");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//Animation
|
||||
|
||||
$(document).ready(function () {
|
||||
$("body.hero-anime").removeClass("hero-anime");
|
||||
});
|
||||
|
||||
//Menu On Hover
|
||||
|
||||
$("body").on("mouseenter mouseleave", ".nav-item", function (e) {
|
||||
if ($(window).width() > 750) {
|
||||
var _d = $(e.target).closest(".nav-item");
|
||||
_d.addClass("show");
|
||||
setTimeout(function () {
|
||||
_d[_d.is(":hover") ? "addClass" : "removeClass"]("show");
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
|
||||
//Switch light/dark
|
||||
|
||||
$("#switch").on("click", function () {
|
||||
if ($("body").hasClass("dark")) {
|
||||
$("body").removeClass("dark");
|
||||
$("#switch").removeClass("switched");
|
||||
} else {
|
||||
$("body").addClass("dark");
|
||||
$("#switch").addClass("switched");
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
124
ui/static/js/plugins.js
Normal file
124
ui/static/js/plugins.js
Normal file
@@ -0,0 +1,124 @@
|
||||
$(document).ready(function () {
|
||||
$("#modal-delete").on("show.bs.modal", function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var path = button.data("path");
|
||||
$("#delete-path").val(path);
|
||||
var name = path.split("/").pop();
|
||||
$("#modal-delete-label").html("Deleting plugin");
|
||||
$("#modal-delete-body").html(
|
||||
`Are you sure you want to delete <b>${path}</b> ?`
|
||||
);
|
||||
});
|
||||
|
||||
$(".collapse-div").click(function () {
|
||||
$(this).find(".rotate-icon").toggleClass("down");
|
||||
});
|
||||
});
|
||||
|
||||
const form = document.querySelector("form"),
|
||||
dropZoneElement = document.querySelector(".drop-zone"),
|
||||
fileInput = document.querySelector(".file-input"),
|
||||
progressArea = document.querySelector(".progress-area"),
|
||||
uploadedArea = document.querySelector(".uploaded-area");
|
||||
|
||||
form.addEventListener("click", () => {
|
||||
fileInput.click();
|
||||
});
|
||||
|
||||
fileInput.onchange = ({ target }) => {
|
||||
timeout = 500;
|
||||
for (let i = 0; i < target.files.length; i++) {
|
||||
setTimeout(() => uploadFile(target.files[i]), timeout * i);
|
||||
}
|
||||
};
|
||||
|
||||
dropZoneElement.addEventListener("dragover", (e) => {
|
||||
e.preventDefault();
|
||||
dropZoneElement.classList.add("drop-zone--over");
|
||||
});
|
||||
|
||||
["dragleave", "dragend"].forEach((type) => {
|
||||
dropZoneElement.addEventListener(type, (e) => {
|
||||
dropZoneElement.classList.remove("drop-zone--over");
|
||||
});
|
||||
});
|
||||
|
||||
dropZoneElement.addEventListener("drop", (e) => {
|
||||
e.preventDefault();
|
||||
fileInput.files = e.dataTransfer.files;
|
||||
fileInput.dispatchEvent(new Event("change"));
|
||||
dropZoneElement.classList.remove("drop-zone--over");
|
||||
});
|
||||
|
||||
function uploadFile(file) {
|
||||
let name = file.name;
|
||||
if (name.length >= 12) {
|
||||
let splitName = name.split(".");
|
||||
name = splitName[0].substring(0, 13) + "... ." + splitName[1];
|
||||
}
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "plugins/upload");
|
||||
let fileSize;
|
||||
|
||||
xhr.upload.addEventListener("progress", ({ loaded, total }) => {
|
||||
let fileLoaded = Math.floor((loaded / total) * 100);
|
||||
let fileTotal = Math.floor(total / 1000);
|
||||
|
||||
fileTotal < 1024
|
||||
? (fileSize = fileTotal + " KB")
|
||||
: (fileSize = (loaded / (1024 * 1024)).toFixed(2) + " MB");
|
||||
|
||||
let progressHTML = `<li class="row">
|
||||
<span class="fa-solid fa-file-zipper"></span>
|
||||
<span class="content">
|
||||
<div class="details">
|
||||
<span class="name">${name} • Uploading</span>
|
||||
<span class="percent">${fileLoaded}%</span>
|
||||
</div>
|
||||
<div class="progress-bar">
|
||||
<div class="progress" style="width: ${fileLoaded}%"></div>
|
||||
</div>
|
||||
</span>
|
||||
</li>`;
|
||||
|
||||
uploadedArea.classList.add("onprogress");
|
||||
progressArea.innerHTML = progressHTML;
|
||||
});
|
||||
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
progressArea.innerHTML = "";
|
||||
let uploadedHTML =
|
||||
xhr.status == 201
|
||||
? `<li class="row">
|
||||
<div class="content upload">
|
||||
<i class="fa-solid fa-file-zipper"></i>
|
||||
<div class="details">
|
||||
<span class="name">${name} • Uploaded</span>
|
||||
<span class="size">${fileSize}</span>
|
||||
</div>
|
||||
</div>
|
||||
<i class="fa-solid fa-check"></i>
|
||||
</li>`
|
||||
: `<li class="row failed">
|
||||
<div class="content upload">
|
||||
<i class="fa-solid fa-file-zipper"></i>
|
||||
<div class="details">
|
||||
<span class="name">${name} • Failed</span>
|
||||
<span class="size">${fileSize}</span>
|
||||
</div>
|
||||
</div>
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</li>`;
|
||||
|
||||
uploadedArea.classList.remove("onprogress");
|
||||
uploadedArea.insertAdjacentHTML("afterbegin", uploadedHTML);
|
||||
}
|
||||
};
|
||||
|
||||
let data = new FormData();
|
||||
data.set("file", file);
|
||||
data.set("csrf_token", $("#csrf_token").val());
|
||||
xhr.send(data);
|
||||
}
|
||||
6
ui/static/js/popper.min.js
vendored
Normal file
6
ui/static/js/popper.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
103
ui/static/js/services.js
Normal file
103
ui/static/js/services.js
Normal file
@@ -0,0 +1,103 @@
|
||||
var multiples = {};
|
||||
function addMultiple(id, paramsEnc) {
|
||||
var params = JSON.parse(paramsEnc);
|
||||
var div = document.getElementById(id);
|
||||
|
||||
if (!multiples.hasOwnProperty(id)) {
|
||||
multiples[id] = 0;
|
||||
}
|
||||
|
||||
multiples[id]++;
|
||||
x = 0;
|
||||
|
||||
for (const param in params) {
|
||||
var input = "";
|
||||
var input_id =
|
||||
id + "-" + params[param]["id"] + "-" + multiples[id].toString();
|
||||
var input_name =
|
||||
params[param]["env"] +
|
||||
(multiples[id] - 1 > 0 ? "_" + (multiples[id] - 1).toString() : "");
|
||||
var input_label = params[param]["label"] + " #" + multiples[id].toString();
|
||||
var input_value = params[param]["default"];
|
||||
var input_help = params[param]["help"];
|
||||
var input_selects = params[param]["select"];
|
||||
var pt = "";
|
||||
var padding_bottom = "";
|
||||
|
||||
if (params[param]["type"] == "text" || params[param]["type"] == "number") {
|
||||
input = `<input type="${params[param]["type"]}" class="form-control" id="${input_id}" value="${input_value}" name="${input_name}">`;
|
||||
} else if (params[param]["type"] == "check") {
|
||||
if (input_value == "yes") {
|
||||
input_value = "checked";
|
||||
} else {
|
||||
input_value = "";
|
||||
}
|
||||
|
||||
input = `<div class="form-check form-switch"><input type="checkbox" class="form-check-input" role="switch" id="${input_id}" name="${input_name}" ${input_value}><input type="hidden" id="${input_id}-hidden" name="${input_name}" value="off"></div>`;
|
||||
pt = "pt-0";
|
||||
} else if (params[param]["type"] == "select") {
|
||||
input = `<select type="form-select" class="form-control form-select" id="${input_id}" name="${input_name}">`;
|
||||
for (const select in input_selects) {
|
||||
selected = "";
|
||||
if (input_value == select) {
|
||||
selected = "selected";
|
||||
}
|
||||
|
||||
input += `<option value="${select}" ${selected}>${select}</option>`;
|
||||
}
|
||||
input += `</select>`;
|
||||
}
|
||||
|
||||
if (x === 0 && multiples[id] > 1) {
|
||||
padding_bottom = "pb-3";
|
||||
}
|
||||
|
||||
div.insertAdjacentHTML(
|
||||
"afterend",
|
||||
`<div class="d-flex flex-row justify-content-between align-items-center mb-3 ${padding_bottom}" id="${input_id}"><div class="px-2 d-sm-inline" data-bs-toggle="tooltip" data-bs-placement="bottom" title="${input_help}"><i class="fas fa-question-circle"></i></div><label for="${input_id}" class="flex-grow-1 d-sm-inline ${pt}" id="${input_id}">${input_label}</label><div class="d-sm-inline" id="${input_id}">${input}</div></div>`
|
||||
);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
function delMultiple(id, paramsEnc) {
|
||||
if (multiples.hasOwnProperty(id) && multiples[id] > 0) {
|
||||
var params = JSON.parse(paramsEnc);
|
||||
for (const param in params) {
|
||||
var input_id =
|
||||
id + "-" + params[param]["id"] + "-" + multiples[id].toString();
|
||||
document.getElementById(input_id).remove();
|
||||
}
|
||||
multiples[id]--;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$("form").on("focus", ".form-control", function () {
|
||||
if (
|
||||
["text", "number"].includes($(this).attr("type")) &&
|
||||
$(this).prop("validity").valid
|
||||
) {
|
||||
$(this).addClass("is-valid");
|
||||
}
|
||||
});
|
||||
|
||||
$("form").on("focusout", ".form-control", function () {
|
||||
if (["text", "number"].includes($(this).attr("type"))) {
|
||||
$(this).removeClass("is-valid");
|
||||
}
|
||||
});
|
||||
|
||||
$("form").on("change", ".form-control", function () {
|
||||
if (["text", "number"].includes($(this).attr("type"))) {
|
||||
if (!$(this).prop("validity").valid) {
|
||||
$("#pills-tab a").addClass("disabled");
|
||||
$(this).addClass("is-invalid");
|
||||
} else {
|
||||
$("#pills-tab a").removeClass("disabled");
|
||||
$(this).removeClass("is-invalid");
|
||||
$(this).addClass("is-valid");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
2
ui/static/js/tsparticles.bundle.min.js
vendored
Normal file
2
ui/static/js/tsparticles.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user