mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
762 lines
29 KiB
HTML
762 lines
29 KiB
HTML
{% extends ../base.html %}
|
||
|
||
{% block meta %}
|
||
{% end %}
|
||
|
||
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}
|
||
|
||
{% block content %}
|
||
|
||
<div class="content-wrapper">
|
||
|
||
<!-- Page Title Header Starts-->
|
||
<div class="row page-title-header">
|
||
<div class="col-12">
|
||
<div class="page-header">
|
||
<h4 class="page-title">
|
||
{{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{
|
||
data['server_stats']['server_id']['server_name'] }}
|
||
<br />
|
||
<small>UUID: {{ data['server_stats']['server_id']['server_id'] }}</small>
|
||
</h4>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
<!-- Page Title Header Ends-->
|
||
|
||
{% include "parts/details_stats.html %}
|
||
|
||
<div class="row">
|
||
|
||
<div class="col-sm-12 grid-margin">
|
||
<div class="card">
|
||
<div class="card-body pt-0">
|
||
|
||
<span class="d-none d-sm-block">
|
||
{% include "parts/server_controls_list.html %}
|
||
</span>
|
||
<span class="d-block d-sm-none">
|
||
{% include "parts/m_server_controls_list.html %}
|
||
</span>
|
||
<div class="row">
|
||
<div class="col-md-6 col-sm-12">
|
||
<br>
|
||
<br>
|
||
<div id="{{data['backup_config'].get('backup_id', None)}}_status" class="progress"
|
||
style="height: 15px; display: none;">
|
||
</div>
|
||
{% if data['backing_up'] %}
|
||
<p>Backing up <i class="fas fa-spin fa-spinner"></i> <span
|
||
id="total_files">{{data['server_stats']['world_size']}}</span></p>
|
||
{% end %}
|
||
|
||
<br>
|
||
{% if not data['backing_up'] %}
|
||
<div id="backup_button" class="form-group">
|
||
<button class="btn btn-primary" id="backup_now_button">{{ translate('serverBackups', 'backupNow',
|
||
data['lang']) }}</button>
|
||
</div>
|
||
{% end %}
|
||
<form id="backup-form" class="forms-sample">
|
||
<div class="form-group">
|
||
<label for="backup_name">{{ translate('serverBackups', 'name', data['lang']) }}
|
||
{% if data["backup_config"].get("default", None) %}
|
||
<span class="badge-pill badge-outline-warning">{{ translate('serverBackups', 'default',
|
||
data['lang']) }}</span><small><button class="badge-pill badge-outline-info backup-explain"
|
||
data-explain="{{ translate('serverBackups', 'defaultExplain', data['lang'])}}"><i
|
||
class="fa-solid fa-question"></i></button></small>
|
||
{% end %}
|
||
</label>
|
||
{% if data["backup_config"].get("backup_id", None) %}
|
||
<input type="text" class="form-control" name="backup_name" id="backup_name"
|
||
value="{{ data['backup_config']['backup_name'] }}">
|
||
{% else %}
|
||
<input type="text" class="form-control" name="backup_name" id="backup_name"
|
||
placeholder="{{ translate('serverBackups', 'myBackup', data['lang']) }}">
|
||
{% end %}
|
||
<br>
|
||
<input type="radio" class="form-check-input" name="backup_type" id="zip_archive" value="zip_archive" checked>
|
||
<label for="True">Full Zip Archive</label><br>
|
||
<input type="radio" class="form-check-input" name="backup_type" id="zip_archive" value="snapshot">
|
||
<label for="True">Snapshot</label><br>
|
||
<br>
|
||
{% if data['super_user'] %}
|
||
<label for="server_name">{{ translate('serverBackups', 'storageLocation', data['lang']) }} <small
|
||
class="text-muted ml-1"> - {{ translate('serverBackups', 'storageLocationDesc', data['lang'])
|
||
}}</small> </label>
|
||
<input type="text" class="form-control" name="backup_location" id="backup_location"
|
||
value="{{ data['backup_config']['backup_location'] }}"
|
||
placeholder="{{ translate('serverBackups', 'storageLocation', data['lang']) }}">
|
||
{% end %}
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="server_path">{{ translate('serverBackups', 'maxBackups', data['lang']) }} <small
|
||
class="text-muted ml-1"> - {{ translate('serverBackups', 'maxBackupsDesc', data['lang'])
|
||
}}</small> </label>
|
||
<input type="text" class="form-control" name="max_backups" id="max_backups"
|
||
value="{{ data['backup_config']['max_backups'] }}"
|
||
placeholder="{{ translate('serverBackups', 'maxBackups', data['lang']) }}">
|
||
</div>
|
||
<div class="form-group">
|
||
<div class="custom-control custom-switch">
|
||
{% if data['backup_config']['compress'] %}
|
||
<input type="checkbox" class="custom-control-input" id="compress" name="compress" checked=""
|
||
value="True">
|
||
{% else %}
|
||
<input type="checkbox" class="custom-control-input" id="compress" name="compress" value="True">
|
||
{% end %}
|
||
<label for="compress" class="custom-control-label">{{ translate('serverBackups', 'compress',
|
||
data['lang']) }}</label>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<div class="custom-control custom-switch">
|
||
{% if data['backup_config']['shutdown']%}
|
||
<input type="checkbox" class="custom-control-input" id="shutdown" name="shutdown" checked=""
|
||
value="True">
|
||
{% else %}
|
||
<input type="checkbox" class="custom-control-input" id="shutdown" name="shutdown" value="True">
|
||
{% end %}
|
||
<label for="shutdown" class="custom-control-label">{{ translate('serverBackups', 'shutdown',
|
||
data['lang']) }}</label>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<div class="custom-control custom-switch">
|
||
{% if data['backup_config']['before'] %}
|
||
<input type="checkbox" class="custom-control-input" id="before-check" name="before-check" checked>
|
||
<input type="text" class="form-control hidden-input" name="before" id="backup_before"
|
||
value="{{ data['backup_config']['before'] }}" placeholder="We enter the / for you"
|
||
style="display: inline-block;">
|
||
{% else %}
|
||
<input type="checkbox" class="custom-control-input" id="before-check" name="before-check">
|
||
<input type="text" class="form-control hidden-input" name="before" id="backup_before" value=""
|
||
placeholder="We enter the / for you." style="display: none;">
|
||
{% end %}
|
||
<label for="before-check" class="custom-control-label">{{
|
||
translate('serverBackups', 'before', data['lang']) }}</label>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<div class="custom-control custom-switch">
|
||
{% if data['backup_config']['after'] %}
|
||
<input type="checkbox" class="custom-control-input" id="after-check" name="after-check" checked>
|
||
<input type="text" class="form-control hidden-input" name="after" id="backup_after"
|
||
value="{{ data['backup_config']['after'] }}" placeholder="We enter the / for you"
|
||
style="display: inline-block;">
|
||
<br>
|
||
{% else %}
|
||
<input type="checkbox" class="custom-control-input" id="after-check" name="after-check">
|
||
<input type="text" class="form-control hidden-input" name="after" id="backup_after" value=""
|
||
placeholder="We enter the / for you." style="display: none;">
|
||
{% end %}
|
||
<label for="after-check" class="custom-control-label">{{
|
||
translate('serverBackups', 'after', data['lang']) }}</label>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="server">{{ translate('serverBackups', 'exclusionsTitle', data['lang']) }} <small> - {{
|
||
translate('serverBackups', 'excludedChoose', data['lang']) }}</small></label>
|
||
<br>
|
||
<button class="btn btn-primary mr-2" id="root_files_button"
|
||
data-server_path="{{ data['server_stats']['server_id']['path']}}" type="button">{{
|
||
translate('serverBackups', 'clickExclude', data['lang']) }}</button>
|
||
</div>
|
||
<div class="modal fade" id="dir_select" tabindex="-1" aria-labelledby="dir_select" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="exampleModalLongTitle">{{ translate('serverBackups',
|
||
'excludedChoose', data['lang']) }}</h5>
|
||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||
<span aria-hidden="true">×</span>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="tree-ctx-item" id="main-tree-div" data-path=""
|
||
style="overflow: scroll; max-height:75%;">
|
||
<input type="checkbox" id="main-tree-input" name="root_path" value="" disabled>
|
||
<span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path="">
|
||
<i class="far fa-folder"></i>
|
||
<i class="far fa-folder-open"></i>
|
||
{{ translate('serverFiles', 'files', data['lang']) }}
|
||
</span>
|
||
</input>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" id="modal-cancel" class="btn btn-secondary" data-dismiss="modal"><i
|
||
class="fa-solid fa-xmark"></i></button>
|
||
<button type="button" id="modal-okay" data-dismiss="modal" class="btn btn-primary"><i
|
||
class="fa-solid fa-thumbs-up"></i></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<button type="submit" class="btn btn-success mr-2">{{ translate('serverBackups', 'save', data['lang'])
|
||
}}</button>
|
||
<button type="reset" class="btn btn-light cancel-button">{{ translate('serverBackups', 'cancel',
|
||
data['lang'])
|
||
}}</button>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="col-md-6 col-sm-12">
|
||
<div class="text-center">
|
||
|
||
<table class="table table-responsive dataTable" id="backup_table">
|
||
<h4 class="card-title">{{ translate('serverBackups', 'currentBackups', data['lang']) }}</h4>
|
||
<thead>
|
||
<tr>
|
||
<th>{{ translate('serverBackups', 'options', data['lang']) }}</th>
|
||
<th>{{ translate('serverBackups', 'path', data['lang']) }}</th>
|
||
<th>{{ translate('serverBackups', 'size', data['lang']) }}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for backup in data['backup_list'] %}
|
||
<tr>
|
||
<td>
|
||
<a href="/panel/download_backup?file={{ backup['path'] }}&id={{ data['server_stats']['server_id']['server_id'] }}&backup_id={{ data['backup_config']['backup_id']}}"
|
||
class="btn btn-primary">
|
||
<i class="fas fa-download" aria-hidden="true"></i>
|
||
{{ translate('serverBackups', 'download', data['lang']) }}
|
||
</a>
|
||
<br>
|
||
<br>
|
||
<button data-file="{{ backup['path'] }}"
|
||
data-backup_location="{{ data['backup_config']['backup_location'] }}"
|
||
class="btn btn-danger del_button">
|
||
<i class="fas fa-trash" aria-hidden="true"></i>
|
||
{{ translate('serverBackups', 'delete', data['lang']) }}
|
||
</button>
|
||
<button data-file="{{ backup['path'] }}" class="btn btn-warning restore_button">
|
||
<i class="fas fa-undo-alt" aria-hidden="true"></i>
|
||
{{ translate('serverBackups', 'restore', data['lang']) }}
|
||
</button>
|
||
</td>
|
||
<td>{{ backup['path'] }}</td>
|
||
<td>{{ backup['size'] }}</td>
|
||
</tr>
|
||
{% end %}
|
||
|
||
</tbody>
|
||
</table>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-12 col-sm-12">
|
||
<br>
|
||
<br>
|
||
<div class="card-header header-sm d-flex justify-content-between align-items-center">
|
||
<h4 class="card-title"><i class="fas fa-server"></i> {{ translate('serverBackups', 'excludedBackups',
|
||
data['lang']) }} <small class="text-muted ml-1"></small> </h4>
|
||
</div>
|
||
<br>
|
||
<ul>
|
||
{% for item in data['exclusions'] %}
|
||
<li>{{item}}</li>
|
||
<br>
|
||
{% end %}
|
||
</ul>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
</div>
|
||
<style>
|
||
/* Remove default bullets */
|
||
.tree-view,
|
||
.tree-nested {
|
||
list-style-type: none;
|
||
margin: 0;
|
||
padding: 0;
|
||
margin-left: 10px;
|
||
}
|
||
|
||
/* Style the items */
|
||
.tree-item,
|
||
.files-tree-title {
|
||
cursor: pointer;
|
||
user-select: none;
|
||
/* Prevent text selection */
|
||
}
|
||
|
||
/* Create the caret/arrow with a unicode, and style it */
|
||
.tree-caret .fa-folder {
|
||
display: inline-block;
|
||
}
|
||
|
||
.tree-caret .fa-folder-open {
|
||
display: none;
|
||
}
|
||
|
||
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
|
||
.tree-caret-down .fa-folder {
|
||
display: none;
|
||
}
|
||
|
||
.tree-caret-down .fa-folder-open {
|
||
display: inline-block;
|
||
}
|
||
|
||
/* Hide the nested list */
|
||
.tree-nested {
|
||
display: none;
|
||
}
|
||
</style>
|
||
<!-- content-wrapper ends -->
|
||
|
||
{% end %}
|
||
|
||
{% block js %}
|
||
<script>
|
||
|
||
const server_id = new URLSearchParams(document.location.search).get('id')
|
||
const backup_id = new URLSearchParams(document.location.search).get('backup_id')
|
||
|
||
|
||
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
|
||
function getCookie(name) {
|
||
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
|
||
return r ? r[1] : undefined;
|
||
}
|
||
|
||
async function backup_started() {
|
||
const token = getCookie("_xsrf")
|
||
let res = await fetch(`/api/v2/servers/${server_id}/action/backup_server/${backup_id}`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'X-XSRFToken': token
|
||
}
|
||
});
|
||
let responseData = await res.json();
|
||
if (responseData.status === "ok") {
|
||
console.log(responseData);
|
||
$("#backup_button").prop('disabled', true)
|
||
} else {
|
||
|
||
bootbox.alert({
|
||
title: responseData.status,
|
||
message: responseData.error
|
||
});
|
||
}
|
||
return;
|
||
}
|
||
async function del_backup(filename, id) {
|
||
const token = getCookie("_xsrf")
|
||
let contents = JSON.stringify({ "filename": filename })
|
||
let res = await fetch(`/api/v2/servers/${server_id}/backups/backup/${backup_id}/files/`, {
|
||
method: 'DELETE',
|
||
headers: {
|
||
'token': token,
|
||
},
|
||
body: contents
|
||
});
|
||
let responseData = await res.json();
|
||
if (responseData.status === "ok") {
|
||
window.location.reload();
|
||
} else {
|
||
bootbox.alert({
|
||
"title": responseData.status,
|
||
"message": responseData.error
|
||
})
|
||
}
|
||
}
|
||
|
||
async function restore_backup(filename, id) {
|
||
const token = getCookie("_xsrf")
|
||
let contents = JSON.stringify({ "filename": filename })
|
||
var dialog = bootbox.dialog({
|
||
message: "<i class='fa fa-spin fa-spinner'></i> {{ translate('serverBackups', 'restoring', data['lang']) }}",
|
||
closeButton: false
|
||
});
|
||
let res = await fetch(`/api/v2/servers/${server_id}/backups/backup/${backup_id}/`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'token': token,
|
||
},
|
||
body: contents
|
||
});
|
||
let responseData = await res.json();
|
||
if (responseData.status === "ok") {
|
||
window.location.href = "/panel/dashboard";
|
||
} else {
|
||
bootbox.alert({
|
||
"title": responseData.status,
|
||
"message": responseData.error
|
||
})
|
||
}
|
||
}
|
||
|
||
$("#before-check").on("click", function () {
|
||
if ($("#before-check:checked").val()) {
|
||
$("#backup_before").css("display", "inline-block");
|
||
} else {
|
||
$("#backup_before").css("display", "none");
|
||
$("#backup_before").val("");
|
||
}
|
||
});
|
||
$("#after-check").on("click", function () {
|
||
if ($("#after-check:checked").val()) {
|
||
$("#backup_after").css("display", "inline-block");
|
||
} else {
|
||
$("#backup_after").css("display", "none");
|
||
$("#backup_after").val("");
|
||
}
|
||
});
|
||
|
||
function replacer(key, value) {
|
||
if (key === "excluded_dirs") {
|
||
if (value == 0) {
|
||
return []
|
||
} else {
|
||
return value
|
||
}
|
||
}
|
||
if (key != "before" && key != "after") {
|
||
if (typeof value == "boolean" || key === "executable_update_url") {
|
||
return value
|
||
} else {
|
||
return (isNaN(value) ? value : +value);
|
||
}
|
||
} else {
|
||
return value;
|
||
}
|
||
}
|
||
|
||
$(document).ready(function () {
|
||
$(".backup-explain").on("click", function (e) {
|
||
e.preventDefault();
|
||
bootbox.alert($(this).data("explain"));
|
||
});
|
||
$(".cancel-button").on("click", function () {
|
||
location.href = `/panel/server_detail?id=${server_id}&subpage=backup`
|
||
});
|
||
webSocket.on('backup_status', function (backup) {
|
||
text = ``;
|
||
$(`#${backup.backup_id}_status`).show();
|
||
if (backup.percent >= 100) {
|
||
$(`#${backup.backup_id}_status`).hide()
|
||
setTimeout(function () {
|
||
window.location.reload(1);
|
||
}, 5000);
|
||
} else {
|
||
text = `<div class="progress-bar progress-bar-striped progress-bar-animated"
|
||
role="progressbar" style="width:${backup.percent}%;"
|
||
aria-valuenow="${backup.percent}" aria-valuemin="0" aria-valuemax="100">${backup.percent}%</div>`
|
||
|
||
$(`#${backup.backup_id}_status`).html(text);
|
||
}
|
||
});
|
||
$("#backup-form").on("submit", async function (e) {
|
||
e.preventDefault();
|
||
const token = getCookie("_xsrf")
|
||
let backupForm = document.getElementById("backup-form");
|
||
|
||
let formData = new FormData(backupForm);
|
||
//Remove checks that we don't need in form data.
|
||
formData.delete("after-check");
|
||
formData.delete("before-check");
|
||
//Create an object from the form data entries
|
||
let formDataObject = Object.fromEntries(formData.entries());
|
||
//We need to make sure these are sent regardless of whether or not they're checked
|
||
formDataObject.compress = $("#compress").prop('checked');
|
||
formDataObject.shutdown = $("#shutdown").prop('checked');
|
||
if ($("#root_files_button").hasClass("clicked")) {
|
||
excluded = []
|
||
$('input.excluded:checkbox:checked').each(function () {
|
||
excluded.push($(this).val());
|
||
});
|
||
formDataObject.excluded_dirs = excluded;
|
||
}
|
||
delete formDataObject.root_path
|
||
console.log(formDataObject);
|
||
// Format the plain form data as JSON
|
||
let formDataJsonString = JSON.stringify(formDataObject, replacer);
|
||
|
||
console.log(formDataJsonString);
|
||
let url = `/api/v2/servers/${server_id}/backups/backup/${backup_id}/`
|
||
let method = "PATCH"
|
||
if (!backup_id) {
|
||
url = `/api/v2/servers/${server_id}/backups/`
|
||
method = "POST";
|
||
}
|
||
let res = await fetch(url, {
|
||
method: method,
|
||
headers: {
|
||
'X-XSRFToken': token
|
||
},
|
||
body: formDataJsonString,
|
||
});
|
||
let responseData = await res.json();
|
||
if (responseData.status === "ok") {
|
||
window.location.href = `/panel/server_detail?id=${server_id}&subpage=backup`;
|
||
} else {
|
||
|
||
bootbox.alert({
|
||
title: responseData.error,
|
||
message: responseData.error_data
|
||
});
|
||
}
|
||
});
|
||
|
||
try {
|
||
if ($('#backup_location').val() == '') {
|
||
console.log('true')
|
||
try {
|
||
document.getElementById('backup_now_button').disabled = true;
|
||
} catch {
|
||
|
||
}
|
||
} else {
|
||
document.getElementById('backup_now_button').disabled = false;
|
||
}
|
||
} catch {
|
||
try {
|
||
document.getElementById('backup_now_button').disabled = false;
|
||
} catch {
|
||
|
||
}
|
||
}
|
||
console.log("ready!");
|
||
$("#backup_config_box").hide();
|
||
$("#backup_save_note").hide();
|
||
|
||
$("#show_config").click(function () {
|
||
$("#backup_config_box").toggle();
|
||
$('#backup_button').hide();
|
||
$('#backup_save_note').show();
|
||
$('#backup_data').hide();
|
||
});
|
||
|
||
$('#backup_table').DataTable({
|
||
"order": [[1, "desc"]],
|
||
"paging": false,
|
||
"lengthChange": false,
|
||
"searching": true,
|
||
"ordering": true,
|
||
"info": true,
|
||
"autoWidth": false,
|
||
"responsive": true,
|
||
});
|
||
|
||
$(".del_button").click(function () {
|
||
var file_to_del = $(this).data("file");
|
||
var backup_location = $(this).data('backup_location');
|
||
|
||
console.log("file to delete is" + file_to_del);
|
||
|
||
bootbox.confirm({
|
||
title: "{% raw translate('serverBackups', 'destroyBackup', data['lang']) %}",
|
||
message: "{{ translate('serverBackups', 'confirmDelete', data['lang']) }}",
|
||
buttons: {
|
||
cancel: {
|
||
label: '<i class="fas fa-times"></i> {{ translate("serverBackups", "cancel", data['lang']) }}'
|
||
},
|
||
confirm: {
|
||
label: '<i class="fas fa-check"></i> {{ translate("serverBackups", "confirm", data['lang']) }}'
|
||
}
|
||
},
|
||
callback: function (result) {
|
||
console.log(result);
|
||
if (result == true) {
|
||
var full_path = backup_location + '/' + file_to_del;
|
||
del_backup(file_to_del, server_id);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
$(".restore_button").click(function () {
|
||
var file_to_restore = $(this).data("file");
|
||
|
||
|
||
bootbox.confirm({
|
||
title: "{{ translate('serverBackups', 'restore', data['lang']) }} " + file_to_restore,
|
||
message: "{{ translate('serverBackups', 'confirmRestore', data['lang']) }}",
|
||
buttons: {
|
||
cancel: {
|
||
label: '<i class="fas fa-times"></i> {{ translate("serverBackups", "cancel", data['lang']) }}'
|
||
},
|
||
confirm: {
|
||
label: '<i class="fas fa-check"></i> {{ translate("serverBackups", "restore", data['lang']) }}',
|
||
className: 'btn-outline-danger'
|
||
}
|
||
},
|
||
callback: function (result) {
|
||
console.log(result);
|
||
if (result == true) {
|
||
restore_backup(file_to_restore, server_id);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
$("#backup_now_button").click(function () {
|
||
backup_started();
|
||
});
|
||
|
||
});
|
||
|
||
document.getElementById("modal-cancel").addEventListener("click", function () {
|
||
document.getElementById("root_files_button").classList.remove('clicked');
|
||
document.getElementById("main-tree-div").innerHTML = '<input type="checkbox" id="main-tree-input" name="root_path" value="" disabled><span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path=""><i class="far fa-folder"></i><i class="far fa-folder-open"></i>{{ translate("serverFiles", "files", data["lang"]) }}</span></input>'
|
||
})
|
||
|
||
document.getElementById("root_files_button").addEventListener("click", function () {
|
||
if ($("#root_files_button").data('server_path') != "") {
|
||
if (document.getElementById('root_files_button').classList.contains('clicked')) {
|
||
show_file_tree();
|
||
return;
|
||
} else {
|
||
document.getElementById('root_files_button').classList.add('clicked');
|
||
}
|
||
path = $("#root_files_button").data('server_path')
|
||
console.log($("#root_files_button").data('server_path'))
|
||
const token = getCookie("_xsrf");
|
||
var dialog = bootbox.dialog({
|
||
message: '<p class="text-center mb-0"><i class="fa fa-spin fa-cog"></i> Please wait while we gather your files...</p>',
|
||
closeButton: false
|
||
});
|
||
|
||
setTimeout(function () {
|
||
var x = document.querySelector('.bootbox');
|
||
if (x) {
|
||
x.remove()
|
||
}
|
||
var x = document.querySelector('.modal-backdrop');
|
||
if (x) {
|
||
x.remove()
|
||
}
|
||
document.getElementById('main-tree-input').setAttribute('value', path)
|
||
getTreeView(path);
|
||
show_file_tree();
|
||
|
||
}, 5000);
|
||
} else {
|
||
bootbox.alert("You must input a path before selecting this button");
|
||
}
|
||
});
|
||
|
||
function getDirView(event) {
|
||
let path = event.target.parentElement.getAttribute("data-path");
|
||
if (document.getElementById(path).classList.contains('clicked')) {
|
||
return;
|
||
} else {
|
||
getTreeView(path);
|
||
}
|
||
|
||
}
|
||
async function getTreeView(path) {
|
||
console.log(path)
|
||
const token = getCookie("_xsrf");
|
||
let url = `/api/v2/servers/${server_id}/files/${backup_id}`
|
||
if (!backup_id) {
|
||
url = `/api/v2/servers/${server_id}/files/`
|
||
console.log("NEW URL")
|
||
}
|
||
console.log(url);
|
||
let res = await fetch(url, {
|
||
method: 'POST',
|
||
headers: {
|
||
'X-XSRFToken': token
|
||
},
|
||
body: JSON.stringify({ "page": "backups", "path": path }),
|
||
});
|
||
let responseData = await res.json();
|
||
if (responseData.status === "ok") {
|
||
console.log(responseData);
|
||
process_tree_response(responseData);
|
||
|
||
} else {
|
||
|
||
bootbox.alert({
|
||
title: responseData.status,
|
||
message: responseData.error
|
||
});
|
||
}
|
||
}
|
||
|
||
function process_tree_response(response) {
|
||
let path = response.data.root_path.path;
|
||
let text = `<ul class="tree-nested d-block" id="${path}ul">`;
|
||
Object.entries(response.data).forEach(([key, value]) => {
|
||
if (key === "root_path" || key === "db_stats") {
|
||
//continue is not valid in for each. Return acts as a continue.
|
||
return;
|
||
}
|
||
let checked = ""
|
||
let dpath = value.path;
|
||
let filename = key;
|
||
if (value.excluded) {
|
||
checked = "checked"
|
||
}
|
||
if (value.dir) {
|
||
text += `<li class="tree-item" data-path="${dpath}">
|
||
\n<div id="${dpath}" data-path="${dpath}" data-name="${filename}" class="tree-caret tree-ctx-item tree-folder">
|
||
<input type="checkbox" class="checkBoxClass excluded" value="${dpath}" ${checked}>
|
||
<span id="${dpath}span" class="files-tree-title" data-path="${dpath}" data-name="${filename}" onclick="getDirView(event)">
|
||
<i style="color: var(--info);" class="far fa-folder"></i>
|
||
<i style="color: var(--info);" class="far fa-folder-open"></i>
|
||
<strong>${filename}</strong>
|
||
</span>
|
||
</input></div><li>`
|
||
} else {
|
||
text += `<li
|
||
class="d-block tree-ctx-item tree-file"
|
||
data-path="${dpath}"
|
||
data-name="${filename}"
|
||
onclick=""><input type='checkbox' class="checkBoxClass excluded" name='root_path' value="${dpath}" ${checked}><span style="margin-right: 6px;">
|
||
<i class="far fa-file"></i></span></input>${filename}</li>`
|
||
}
|
||
});
|
||
text += `</ul>`;
|
||
if (response.data.root_path.top) {
|
||
try {
|
||
document.getElementById('main-tree-div').innerHTML += text;
|
||
document.getElementById('main-tree').parentElement.classList.add("clicked");
|
||
} catch {
|
||
document.getElementById('files-tree').innerHTML = text;
|
||
}
|
||
} else {
|
||
try {
|
||
document.getElementById(path + "span").classList.add('tree-caret-down');
|
||
document.getElementById(path).innerHTML += text;
|
||
document.getElementById(path).classList.add("clicked");
|
||
} catch {
|
||
console.log("Bad")
|
||
}
|
||
|
||
var toggler = document.getElementById(path + "span");
|
||
|
||
if (toggler.classList.contains('files-tree-title')) {
|
||
document.getElementById(path + "span").addEventListener("click", function caretListener() {
|
||
document.getElementById(path + "ul").classList.toggle("d-block");
|
||
document.getElementById(path + "span").classList.toggle("tree-caret-down");
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
function getToggleMain(event) {
|
||
path = event.target.parentElement.getAttribute('data-path');
|
||
document.getElementById("files-tree").classList.toggle("d-block");
|
||
document.getElementById(path + "span").classList.toggle("tree-caret-down");
|
||
document.getElementById(path + "span").classList.toggle("tree-caret");
|
||
}
|
||
function show_file_tree() {
|
||
$("#dir_select").modal();
|
||
}
|
||
|
||
</script>
|
||
|
||
{% end %} |