2024-08-26 20:11:03 -05:00
|
|
|
{% extends ../base.html %} {% block meta %} {% end %} {% block title %}Crafty
|
|
|
|
Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{%
|
|
|
|
end %} {% block content %}
|
2021-01-15 14:13:06 +02:00
|
|
|
|
|
|
|
<div class="content-wrapper">
|
2022-04-02 13:06:20 -04:00
|
|
|
<!-- Page Title Header Starts-->
|
2021-01-15 14:13:06 +02:00
|
|
|
<div class="row page-title-header">
|
|
|
|
<div class="col-12">
|
|
|
|
<div class="page-header">
|
|
|
|
<h4 class="page-title">
|
2022-04-02 13:06:20 -04:00
|
|
|
{{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{
|
|
|
|
data['server_stats']['server_id']['server_name'] }}
|
|
|
|
<br />
|
2024-10-04 23:33:54 +02:00
|
|
|
<small>UUID: {{ data['server_stats']['server_id']['server_id'] }}</small>
|
2021-01-15 14:13:06 +02:00
|
|
|
</h4>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Page Title Header Ends-->
|
|
|
|
|
2022-04-02 13:06:20 -04:00
|
|
|
{% include "parts/details_stats.html" %}
|
2021-01-15 14:13:06 +02:00
|
|
|
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-sm-12 grid-margin">
|
|
|
|
<div class="card">
|
2024-08-26 20:11:03 -05:00
|
|
|
<div class="card-body pt-0">
|
2022-06-21 15:59:34 -04:00
|
|
|
<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>
|
2022-04-02 13:06:20 -04:00
|
|
|
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6 col-sm-12">
|
|
|
|
<noscript>
|
|
|
|
{{ translate('serverFiles', 'noscript', data['lang']) }}
|
|
|
|
</noscript>
|
2024-10-04 23:33:54 +02:00
|
|
|
<div id="files-tree-nav" class="overlay">
|
2022-04-02 13:06:20 -04:00
|
|
|
<!-- Button to close the overlay navigation -->
|
|
|
|
|
|
|
|
<!-- Overlay content -->
|
2024-10-04 23:33:54 +02:00
|
|
|
<div id="files-tree-nav-content" class="overlay-content">
|
|
|
|
<h4 id="context-title" class="overlay-title"></h4>
|
|
|
|
<span class="separator"></span>
|
|
|
|
<a onclick="createFileE(event)" href="javascript:void(0)" id="createFile" href="#">{{ translate('serverFiles', 'createFile', data['lang'])
|
|
|
|
}}</a>
|
|
|
|
<a onclick="createDirE(event)" href="javascript:void(0)" id="createDir" href="#">{{ translate('serverFiles', 'createDir', data['lang'])
|
|
|
|
}}</a>
|
|
|
|
<a onclick="renameItemE(event)" href="javascript:void(0)" id="renameItem" href="#">{{ translate('serverFiles', 'rename', data['lang']) }}</a>
|
|
|
|
<a onclick="uploadFilesE(event)" href="javascript:void(0)" id="upload" href="#">{{ translate('serverFiles', 'upload', data['lang']) }}</a>
|
|
|
|
<a onclick="unzipFilesE(event)" href="javascript:void(0)" id="unzip" href="#">{{ translate('serverFiles', 'unzip', data['lang']) }}</a>
|
|
|
|
<a onclick="downloadFileE(event)" href="javascript:void(0)" id="downloadFile" href="#">{{ translate('serverFiles', 'download', data['lang']) }}</a>
|
|
|
|
<a onclick="deleteFileE(event)" href="javascript:void(0)" id="deleteFile" href="#" class="text-danger">{{ translate('serverFiles', 'delete', data['lang']) }}</a>
|
|
|
|
<a onclick="deleteFileE(event)" href="javascript:void(0)" id="deleteDir" href="#" class="text-danger">{{ translate('serverFiles', 'delete', data['lang']) }}</a>
|
2024-10-06 20:54:50 +02:00
|
|
|
<a href="javascript:void(0)" class="closebtn text-info" onclick="document.getElementById('files-tree-nav').style.display = 'none';">{{ translate('serverFiles', 'close', data['lang']) }}</a>
|
2021-01-17 19:20:28 +02:00
|
|
|
</div>
|
2022-04-02 13:06:20 -04:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<ul class="tree-view">
|
|
|
|
<li>
|
2024-10-04 23:33:54 +02:00
|
|
|
<div id="root_dir" class="tree-ctx-item" data-path="{{ data['server_stats']['server_id']['path'] }}">
|
|
|
|
<span id="{{ data['server_stats']['server_id']['path'] }}span" class="files-tree-title tree-caret-down root-dir" data-path="{{ data['server_stats']['server_id']['path'] }}" onclick="getToggleMain(event)">
|
2022-04-02 13:06:20 -04:00
|
|
|
<i class="far fa-folder"></i>
|
|
|
|
<i class="far fa-folder-open"></i>
|
|
|
|
{{ translate('serverFiles', 'files', data['lang']) }}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<ul class="tree-nested d-block" id="files-tree">
|
2024-08-26 20:11:03 -05:00
|
|
|
<li>
|
|
|
|
<i class="fa fa-spin fa-spinner"></i>{{
|
|
|
|
translate('serverFiles', 'loadingRecords', data['lang'])
|
|
|
|
}}
|
|
|
|
</li>
|
2022-04-02 13:06:20 -04:00
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
2022-06-21 16:41:06 -04:00
|
|
|
<div id="editor_container" class="col-md-6 col-sm-12">
|
2024-08-26 20:11:03 -05:00
|
|
|
<br />
|
|
|
|
<br />
|
2022-06-14 01:35:43 +03:00
|
|
|
<div class="editorManager">
|
|
|
|
<h2 id="fileError"></h2>
|
|
|
|
<div id="editorParent">
|
2024-08-26 20:11:03 -05:00
|
|
|
{{ translate('serverFiles', 'editingFile', data['lang']) }}
|
|
|
|
<span id="editingFile"></span>
|
2024-10-04 23:33:54 +02:00
|
|
|
<div id="editor" onresize="editor.resize()" style="resize: both; width: 100%">
|
2024-08-26 20:11:03 -05:00
|
|
|
file_contents
|
|
|
|
</div>
|
2022-06-14 01:35:43 +03:00
|
|
|
<br />
|
|
|
|
</div>
|
|
|
|
{{ translate('serverFiles', 'keybindings', data['lang']) }}:
|
|
|
|
<div class="btn-group" role="group">
|
2024-10-04 23:33:54 +02:00
|
|
|
<button onclick="setKeyboard(event.target)" class="btn btn-primary" data-handler-name="null">
|
2024-08-26 20:11:03 -05:00
|
|
|
{{ translate('serverFiles', 'default', data['lang']) }}
|
|
|
|
</button>
|
2024-10-04 23:33:54 +02:00
|
|
|
<button onclick="setKeyboard(event.target)" class="btn btn-secondary" data-handler-name="ace/keyboard/vim">
|
2024-08-26 20:11:03 -05:00
|
|
|
Vim
|
|
|
|
</button>
|
2024-10-04 23:33:54 +02:00
|
|
|
<button onclick="setKeyboard(event.target)" class="btn btn-secondary" data-handler-name="ace/keyboard/emacs">
|
2024-08-26 20:11:03 -05:00
|
|
|
Emacs
|
|
|
|
</button>
|
2024-10-04 23:33:54 +02:00
|
|
|
<button onclick="setKeyboard(event.target)" class="btn btn-secondary" data-handler-name="ace/keyboard/sublime">
|
2024-08-26 20:11:03 -05:00
|
|
|
Sublime
|
|
|
|
</button>
|
2024-10-04 23:33:54 +02:00
|
|
|
<span class="d-none d-md-block"> <button class="btn btn-info" id="screen-size">
|
2024-08-26 20:11:03 -05:00
|
|
|
{{ translate('serverFiles', 'size', data['lang']) }}
|
2024-10-04 23:33:54 +02:00
|
|
|
</button></span>
|
2022-06-14 01:35:43 +03:00
|
|
|
</div>
|
|
|
|
<h3 id="file_warn"></h3>
|
2024-08-26 20:11:03 -05:00
|
|
|
<button class="btn btn-success" onclick="save()">
|
|
|
|
<i class="fas fa-save"></i> {{ translate('serverFiles',
|
|
|
|
'save', data['lang']) }}
|
|
|
|
</button>
|
2024-10-04 23:33:54 +02:00
|
|
|
<span class="text-success ml-2" id="save_status"></span>
|
2022-04-02 13:06:20 -04:00
|
|
|
</div>
|
2021-01-15 14:13:06 +02:00
|
|
|
</div>
|
2022-04-02 13:06:20 -04:00
|
|
|
</div>
|
2021-01-15 14:13:06 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2024-10-04 23:33:54 +02:00
|
|
|
<link rel="stylesheet" href="/static/assets/css/partial/crafty-filemanager.css" />
|
2021-01-15 14:13:06 +02:00
|
|
|
<!-- content-wrapper ends -->
|
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
{% end %} {% block js %}
|
2024-10-04 23:33:54 +02:00
|
|
|
<script src="/static/assets/vendors/ace-builds/src-min/ace.js" type="text/javascript" charset="utf-8"></script>
|
2021-01-15 14:13:06 +02:00
|
|
|
|
|
|
|
<script>
|
2024-08-26 20:11:03 -05:00
|
|
|
const serverId = new URLSearchParams(document.location.search).get("id");
|
2022-02-27 19:26:54 +02:00
|
|
|
|
|
|
|
//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;
|
|
|
|
}
|
2021-01-15 21:59:58 +02:00
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
let editor = ace.edit("editor");
|
|
|
|
editor.setTheme("ace/theme/dracula");
|
2022-02-27 19:26:54 +02:00
|
|
|
editor.session.setUseSoftTabs(true);
|
2022-06-14 02:45:17 +03:00
|
|
|
editor.commands.addCommand({
|
2024-08-26 20:11:03 -05:00
|
|
|
name: "saveFile",
|
2022-06-14 02:45:17 +03:00
|
|
|
bindKey: {
|
2024-08-26 20:11:03 -05:00
|
|
|
win: "Ctrl-S",
|
|
|
|
mac: "Command-S",
|
|
|
|
sender: "editor|cli",
|
2022-06-14 02:45:17 +03:00
|
|
|
},
|
2022-06-21 16:41:06 -04:00
|
|
|
exec: function (env, args, request) {
|
2024-08-26 20:11:03 -05:00
|
|
|
save();
|
|
|
|
},
|
2022-06-14 02:45:17 +03:00
|
|
|
});
|
2021-01-15 14:13:06 +02:00
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
// mouseup = css resize end
|
2022-04-02 13:06:20 -04:00
|
|
|
document.addEventListener("mouseup", function (e) {
|
|
|
|
editor.resize();
|
|
|
|
});
|
2021-01-20 23:10:25 +02:00
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
let extensionChanges = [
|
|
|
|
{
|
|
|
|
regex: /^js$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/javascript",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^py$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/python",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^html$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/html",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^yml$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/yaml",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^yaml$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/yaml",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^txt$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/text",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^json$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/json",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^java$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/java",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^cpp$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/c_cpp",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^c$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/c_cpp",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^css$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/css",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^scss$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/scss",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^sass$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/sass",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^lua$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/lua",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^php$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/php",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^ps1$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/powershell",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^svg$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/svg",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^sh$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/sh",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^xml$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/xml",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^ts$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/typescript",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^properties$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/properties",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /^log$/,
|
2024-08-26 20:11:03 -05:00
|
|
|
replaceWith: "ace/mode/txt",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
let path = "",
|
|
|
|
serverFileContent = "";
|
2023-09-03 16:15:38 -04:00
|
|
|
|
|
|
|
async function clickOnFile(event) {
|
2023-09-04 19:22:11 -04:00
|
|
|
const token = getCookie("_xsrf");
|
2024-08-26 20:11:03 -05:00
|
|
|
path = event.target.getAttribute("data-path");
|
2023-09-03 16:15:38 -04:00
|
|
|
let res = await fetch(`/api/v2/servers/${serverId}/files`, {
|
2024-08-26 20:11:03 -05:00
|
|
|
method: "POST",
|
2023-09-04 19:22:11 -04:00
|
|
|
headers: {
|
2024-08-26 20:11:03 -05:00
|
|
|
"X-XSRFToken": token,
|
2023-09-04 19:22:11 -04:00
|
|
|
},
|
2024-08-26 20:11:03 -05:00
|
|
|
body: JSON.stringify({ page: "files", path: path }),
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
let responseData = await res.json();
|
2024-08-26 20:11:03 -05:00
|
|
|
console.log(responseData);
|
2023-09-04 19:22:11 -04:00
|
|
|
if (responseData.status === "ok") {
|
2024-08-26 20:11:03 -05:00
|
|
|
console.log("Got File Contents From Server");
|
|
|
|
$("#editorParent").toggle(true); // show
|
|
|
|
$("#fileError").toggle(false); // hide
|
2023-09-04 19:22:11 -04:00
|
|
|
setFileName(event.target.innerText);
|
|
|
|
editor.session.setValue(responseData.data);
|
|
|
|
serverFileContent = responseData.data;
|
|
|
|
setSaveStatus(true);
|
2024-08-26 20:11:03 -05:00
|
|
|
} else {
|
2023-09-04 19:22:11 -04:00
|
|
|
bootbox.alert({
|
|
|
|
title: responseData.status,
|
2024-08-26 20:11:03 -05:00
|
|
|
message: responseData.error,
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-15 21:59:58 +02:00
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
function setFileName(name) {
|
2024-08-26 20:11:03 -05:00
|
|
|
let fileName = name || "default.txt";
|
|
|
|
document.getElementById("editingFile").innerText = fileName;
|
2021-01-15 14:13:06 +02:00
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
if (fileName.match(".")) {
|
2022-02-27 19:26:54 +02:00
|
|
|
// The pop method removes and returns the last element.
|
2024-08-26 20:11:03 -05:00
|
|
|
setMode(fileName.split(".").pop().replace("ace/mode/", ""));
|
2022-02-27 19:26:54 +02:00
|
|
|
} else {
|
2024-08-26 20:11:03 -05:00
|
|
|
setMode("txt");
|
|
|
|
document.querySelector("#file_warn").innerText =
|
|
|
|
"{% raw translate('serverFiles', 'unsupportedLanguage', data['lang']) %}";
|
2021-01-15 14:13:06 +02:00
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-15 14:13:06 +02:00
|
|
|
|
2022-04-02 13:06:20 -04:00
|
|
|
var onlongtouch;
|
2022-03-22 14:24:15 +00:00
|
|
|
var timer;
|
|
|
|
var touchduration = 500; //length of time we want the user to touch before we do something
|
2024-08-26 20:11:03 -05:00
|
|
|
const longtouch = new Event("longtouch");
|
2022-04-02 13:06:20 -04:00
|
|
|
|
2022-03-22 14:24:15 +00:00
|
|
|
function touchstart(event) {
|
2022-04-02 13:06:20 -04:00
|
|
|
if (!timer) {
|
|
|
|
timer = setTimeout(onlongtouch, touchduration, event);
|
|
|
|
}
|
2022-03-22 14:24:15 +00:00
|
|
|
}
|
2022-04-02 13:06:20 -04:00
|
|
|
|
2022-03-22 14:24:15 +00:00
|
|
|
function touchend(event) {
|
2022-04-02 13:06:20 -04:00
|
|
|
//stops short touches from firing the event
|
|
|
|
if (timer) {
|
|
|
|
clearTimeout(timer);
|
2024-08-26 20:11:03 -05:00
|
|
|
console.log("Timer: " + timer);
|
2022-04-02 13:06:20 -04:00
|
|
|
timer = null;
|
|
|
|
}
|
2022-03-22 14:24:15 +00:00
|
|
|
}
|
2022-04-02 13:06:20 -04:00
|
|
|
|
|
|
|
onlongtouch = function (e) {
|
2024-08-26 20:11:03 -05:00
|
|
|
console.log("iOS long touch detected!");
|
|
|
|
if (
|
|
|
|
[
|
|
|
|
"iPad Simulator",
|
|
|
|
"iPhone Simulator",
|
|
|
|
"iPod Simulator",
|
|
|
|
"iPad",
|
|
|
|
"iPhone",
|
|
|
|
"iPod",
|
|
|
|
].includes(navigator.platform) ||
|
2022-04-02 13:06:20 -04:00
|
|
|
// iPad on iOS 13 detection
|
2024-08-26 20:11:03 -05:00
|
|
|
(navigator.userAgent.includes("Mac") && "ontouchend" in document)
|
|
|
|
) {
|
2022-04-02 13:06:20 -04:00
|
|
|
e.preventDefault();
|
|
|
|
e.stopImmediatePropagation();
|
2024-08-26 20:11:03 -05:00
|
|
|
var ctxmenuPath = e.target.getAttribute("data-path");
|
|
|
|
var ctxmenuName = e.target.getAttribute("data-name");
|
2022-05-15 12:38:48 -05:00
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
document.getElementById("context-title").innerHTML = ctxmenuName;
|
2022-04-02 13:06:20 -04:00
|
|
|
if (!ctxmenuPath) {
|
|
|
|
return;
|
|
|
|
}
|
2024-08-26 20:11:03 -05:00
|
|
|
$("#renameItem").show();
|
|
|
|
|
|
|
|
var isDir = e.target.classList.contains("files-tree-title");
|
|
|
|
$("#createFile").toggle(isDir);
|
|
|
|
$("#createDir").toggle(isDir);
|
|
|
|
$("#deleteDir").toggle(isDir);
|
|
|
|
$("#upload").toggle(isDir);
|
|
|
|
|
|
|
|
var isFile = e.target.classList.contains("tree-file");
|
|
|
|
$("#deleteFile").toggle(isFile);
|
|
|
|
$("#downloadFile").toggle(isFile);
|
|
|
|
|
|
|
|
if (e.target.classList.contains("root-dir")) {
|
|
|
|
$("#createFile").show();
|
|
|
|
$("#createDir").show();
|
|
|
|
$("#renameItem").hide();
|
|
|
|
$("#deleteDir").hide();
|
|
|
|
$("#deleteFile").hide();
|
|
|
|
$("#downloadFile").hide();
|
|
|
|
$("#upload").show();
|
2022-03-22 14:24:15 +00:00
|
|
|
}
|
2024-08-26 20:11:03 -05:00
|
|
|
if (e.target.textContent.endsWith(".zip")) {
|
|
|
|
$("#unzip").show();
|
2022-04-02 13:06:20 -04:00
|
|
|
} else {
|
2024-08-26 20:11:03 -05:00
|
|
|
$("#unzip").hide();
|
2022-04-02 13:06:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var clientX = e.layerX + 2;
|
|
|
|
var clientY = e.layerY + 5;
|
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
document
|
|
|
|
.getElementById("files-tree-nav-content")
|
|
|
|
.setAttribute("data-path", ctxmenuPath);
|
|
|
|
document
|
|
|
|
.getElementById("files-tree-nav-content")
|
|
|
|
.setAttribute("data-name", ctxmenuName);
|
2022-04-02 13:06:20 -04:00
|
|
|
document.getElementById("files-tree-nav").style.display = "flex";
|
|
|
|
document.getElementById("files-tree-nav").style.position = "fixed";
|
2024-08-26 20:11:03 -05:00
|
|
|
domRect = document
|
|
|
|
.getElementById("files-tree-nav")
|
|
|
|
.getBoundingClientRect();
|
|
|
|
sum = clientY + domRect["height"] - window.innerHeight;
|
|
|
|
if (domRect["height"] + clientY > window.innerHeight) {
|
2022-04-02 13:06:20 -04:00
|
|
|
clientY = clientY - sum;
|
|
|
|
}
|
2024-08-26 20:11:03 -05:00
|
|
|
document.getElementById("files-tree-nav").style.top = clientY + "px";
|
|
|
|
document.getElementById("files-tree-nav").style.left = clientX + "px";
|
2022-04-02 13:06:20 -04:00
|
|
|
timer = null;
|
2024-08-26 20:11:03 -05:00
|
|
|
}
|
|
|
|
};
|
2022-06-14 03:07:26 +03:00
|
|
|
/**
|
2024-08-26 20:11:03 -05:00
|
|
|
* @param {boolean} saved
|
|
|
|
*/
|
2022-06-14 03:07:26 +03:00
|
|
|
const setSaveStatus = (saved) => {
|
2024-10-04 23:33:54 +02:00
|
|
|
document.getElementById("save_status").innerHTML = `<i class="${saved ? "fa-solid fa-file-circle-check" : "fa-regular fa-file"
|
|
|
|
}"></i>`;
|
2024-08-26 20:11:03 -05:00
|
|
|
document.getElementById("save_status").style.color = saved
|
2024-10-04 23:33:54 +02:00
|
|
|
? "var(--success)"
|
|
|
|
: "var(--gray)";
|
2024-08-26 20:11:03 -05:00
|
|
|
};
|
|
|
|
["change", "undo", "redo"].forEach((event) =>
|
|
|
|
editor.on(event, (event) =>
|
|
|
|
setSaveStatus(serverFileContent === editor.session.getValue())
|
|
|
|
)
|
|
|
|
);
|
|
|
|
$("#screen-size").on("click", function (e) {
|
|
|
|
$("#editor_container").toggleClass(`col-md-6`);
|
2022-06-21 16:41:06 -04:00
|
|
|
});
|
2022-02-27 19:26:54 +02:00
|
|
|
setFileName();
|
2024-08-26 20:11:03 -05:00
|
|
|
$("#editorParent").toggle(false); // show
|
|
|
|
$("#fileError").toggle(false); // hide
|
|
|
|
editor.blur();
|
2022-02-27 19:26:54 +02:00
|
|
|
|
2022-04-02 13:06:20 -04:00
|
|
|
function setMode(extension) {
|
2022-02-27 19:26:54 +02:00
|
|
|
// if the extension matches with the RegEx it will return the replaceWith
|
|
|
|
// property. else it will return the one it has. defaults to the extension.
|
|
|
|
// this runs for each element in extensionChanges.
|
|
|
|
let aceMode = extensionChanges.reduce((output, element) => {
|
2024-08-26 20:11:03 -05:00
|
|
|
return extension.match(element.regex) ? element.replaceWith : output;
|
2022-02-27 19:26:54 +02:00
|
|
|
}, extension);
|
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
if (!aceMode.startsWith("ace/mode/")) {
|
|
|
|
document.querySelector("#file_warn").innerText =
|
|
|
|
"{% raw translate('serverFiles', 'unsupportedLanguage', data['lang']) %}";
|
2022-02-27 19:26:54 +02:00
|
|
|
} else {
|
2024-08-26 20:11:03 -05:00
|
|
|
document.querySelector("#file_warn").innerText = "";
|
2022-02-27 19:26:54 +02:00
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
console.log(aceMode || "ace/mode/text");
|
|
|
|
editor.session.setMode(aceMode || "ace/mode/text");
|
2021-01-15 14:13:06 +02:00
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-15 14:13:06 +02:00
|
|
|
|
2023-09-03 16:15:38 -04:00
|
|
|
async function save() {
|
2022-02-27 19:26:54 +02:00
|
|
|
let text = editor.session.getValue();
|
2021-01-15 21:59:58 +02:00
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
const token = getCookie("_xsrf");
|
2023-09-03 16:15:38 -04:00
|
|
|
let res = await fetch(`/api/v2/servers/${serverId}/files`, {
|
2024-08-26 20:11:03 -05:00
|
|
|
method: "PATCH",
|
2023-09-04 19:22:11 -04:00
|
|
|
headers: {
|
2024-08-26 20:11:03 -05:00
|
|
|
"X-XSRFToken": token,
|
2023-09-04 19:22:11 -04:00
|
|
|
},
|
2024-08-26 20:11:03 -05:00
|
|
|
body: JSON.stringify({ path: path, contents: text }),
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
let responseData = await res.json();
|
|
|
|
if (responseData.status === "ok") {
|
|
|
|
serverFileContent = text;
|
2024-08-26 20:11:03 -05:00
|
|
|
setSaveStatus(true);
|
2023-09-04 19:22:11 -04:00
|
|
|
} else {
|
|
|
|
bootbox.alert({
|
|
|
|
title: responseData.status,
|
2024-08-26 20:11:03 -05:00
|
|
|
message: responseData.error,
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-15 14:13:06 +02:00
|
|
|
|
2023-09-03 16:15:38 -04:00
|
|
|
async function createFile(parent, name, callback) {
|
2024-08-26 20:11:03 -05:00
|
|
|
const token = getCookie("_xsrf");
|
2023-09-03 16:15:38 -04:00
|
|
|
let res = await fetch(`/api/v2/servers/${serverId}/files/create/`, {
|
2024-08-26 20:11:03 -05:00
|
|
|
method: "PUT",
|
2023-09-04 19:22:11 -04:00
|
|
|
headers: {
|
2024-08-26 20:11:03 -05:00
|
|
|
"X-XSRFToken": token,
|
2023-09-04 19:22:11 -04:00
|
|
|
},
|
2024-08-26 20:11:03 -05:00
|
|
|
body: JSON.stringify({ parent: parent, name: name, directory: false }),
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
let responseData = await res.json();
|
|
|
|
if (responseData.status === "ok") {
|
2024-08-26 20:11:03 -05:00
|
|
|
getTreeView($("#root_dir").data("path"));
|
2023-09-04 19:22:11 -04:00
|
|
|
setTreeViewContext();
|
|
|
|
} else {
|
|
|
|
bootbox.alert({
|
|
|
|
title: responseData.status,
|
2024-08-26 20:11:03 -05:00
|
|
|
message: responseData.error,
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2023-09-03 16:15:38 -04:00
|
|
|
async function createDir(parent, name, callback) {
|
2024-08-26 20:11:03 -05:00
|
|
|
const token = getCookie("_xsrf");
|
2023-09-03 16:15:38 -04:00
|
|
|
let res = await fetch(`/api/v2/servers/${serverId}/files/create/`, {
|
2024-08-26 20:11:03 -05:00
|
|
|
method: "PUT",
|
2023-09-04 19:22:11 -04:00
|
|
|
headers: {
|
2024-08-26 20:11:03 -05:00
|
|
|
"X-XSRFToken": token,
|
2023-09-04 19:22:11 -04:00
|
|
|
},
|
2024-08-26 20:11:03 -05:00
|
|
|
body: JSON.stringify({ parent: parent, name: name, directory: true }),
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
let responseData = await res.json();
|
|
|
|
if (responseData.status === "ok") {
|
2024-08-26 20:11:03 -05:00
|
|
|
getTreeView($("#root_dir").data("path"));
|
2023-09-04 19:22:11 -04:00
|
|
|
setTreeViewContext();
|
|
|
|
} else {
|
|
|
|
bootbox.alert({
|
|
|
|
title: responseData.status,
|
2024-08-26 20:11:03 -05:00
|
|
|
message: responseData.error,
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2023-09-03 16:15:38 -04:00
|
|
|
async function renameItem(path, name, callback) {
|
2024-08-26 20:11:03 -05:00
|
|
|
const token = getCookie("_xsrf");
|
2023-09-03 16:15:38 -04:00
|
|
|
let res = await fetch(`/api/v2/servers/${serverId}/files/create/`, {
|
2024-08-26 20:11:03 -05:00
|
|
|
method: "PATCH",
|
2023-09-04 19:22:11 -04:00
|
|
|
headers: {
|
2024-08-26 20:11:03 -05:00
|
|
|
"X-XSRFToken": token,
|
2023-09-04 19:22:11 -04:00
|
|
|
},
|
2024-08-26 20:11:03 -05:00
|
|
|
body: JSON.stringify({ path: path, new_name: name }),
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
let responseData = await res.json();
|
|
|
|
if (responseData.status === "ok") {
|
2024-08-26 20:11:03 -05:00
|
|
|
getTreeView($("#root_dir").data("path"));
|
2023-09-04 19:22:11 -04:00
|
|
|
setTreeViewContext();
|
|
|
|
} else {
|
|
|
|
bootbox.alert({
|
|
|
|
title: responseData.status,
|
2024-08-26 20:11:03 -05:00
|
|
|
message: responseData.error,
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2023-06-05 18:20:45 -04:00
|
|
|
async function deleteItem(path, el, callback) {
|
2023-09-04 19:22:11 -04:00
|
|
|
const token = getCookie("_xsrf");
|
2023-06-05 18:20:45 -04:00
|
|
|
let res = await fetch(`/api/v2/servers/${serverId}/files`, {
|
2024-08-26 20:11:03 -05:00
|
|
|
method: "DELETE",
|
2023-09-04 19:22:11 -04:00
|
|
|
headers: {
|
2024-08-26 20:11:03 -05:00
|
|
|
"X-XSRFToken": token,
|
2023-09-04 19:22:11 -04:00
|
|
|
},
|
2024-08-26 20:11:03 -05:00
|
|
|
body: JSON.stringify({ filename: path }),
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
let responseData = await res.json();
|
|
|
|
if (responseData.status === "ok") {
|
|
|
|
el = document.getElementById(path + "li");
|
|
|
|
$(el).remove();
|
2024-08-26 20:11:03 -05:00
|
|
|
document.getElementById("files-tree-nav").style.display = "none";
|
2023-09-04 19:22:11 -04:00
|
|
|
} else {
|
|
|
|
bootbox.alert({
|
|
|
|
title: responseData.status,
|
2024-08-26 20:11:03 -05:00
|
|
|
message: responseData.error,
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2023-09-03 16:15:38 -04:00
|
|
|
async function unZip(path, callback) {
|
2024-08-26 20:11:03 -05:00
|
|
|
const token = getCookie("_xsrf");
|
2023-09-03 16:15:38 -04:00
|
|
|
let res = await fetch(`/api/v2/servers/${serverId}/files/zip/`, {
|
2024-08-26 20:11:03 -05:00
|
|
|
method: "POST",
|
2023-09-04 19:22:11 -04:00
|
|
|
headers: {
|
2024-08-26 20:11:03 -05:00
|
|
|
"X-XSRFToken": token,
|
2023-09-04 19:22:11 -04:00
|
|
|
},
|
2024-08-26 20:11:03 -05:00
|
|
|
body: JSON.stringify({ folder: path }),
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
let responseData = await res.json();
|
|
|
|
if (responseData.status === "ok") {
|
2024-08-26 20:11:03 -05:00
|
|
|
getTreeView($("#root_dir").data("path"));
|
2023-09-04 19:22:11 -04:00
|
|
|
setTreeViewContext();
|
|
|
|
} else {
|
|
|
|
bootbox.alert({
|
|
|
|
title: responseData.status,
|
2024-08-26 20:11:03 -05:00
|
|
|
message: responseData.error,
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-08-22 16:31:49 -04:00
|
|
|
|
2022-04-02 13:06:20 -04:00
|
|
|
let uploadWaitDialog;
|
2021-08-22 16:31:49 -04:00
|
|
|
|
2023-01-28 19:10:27 -05:00
|
|
|
async function uploadFilesE(event) {
|
2024-08-26 20:11:03 -05:00
|
|
|
path = event.target.parentElement.getAttribute("data-path");
|
2021-08-22 16:31:49 -04:00
|
|
|
$(function () {
|
2024-08-26 20:11:03 -05:00
|
|
|
var uploadHtml =
|
|
|
|
"<div>" +
|
|
|
|
'<form id="upload_file" enctype="multipart/form-data">' +
|
|
|
|
"<label class='upload-area' style='width:100%;text-align:center;' for='files'>" +
|
2022-04-02 13:06:20 -04:00
|
|
|
"<i class='fa fa-cloud-upload fa-3x'></i>" +
|
|
|
|
"<br />" +
|
|
|
|
"{{translate('serverFiles', 'clickUpload', data['lang'])}}" +
|
2022-04-12 15:27:03 -04:00
|
|
|
"<input style='margin-left: 21%;' id='files' name='files' type='file' multiple='true'>" +
|
2021-08-22 16:31:49 -04:00
|
|
|
"</label></form>" +
|
|
|
|
"<br />" +
|
|
|
|
"<ul style='margin-left:5px !important;' id='fileList'></ul>" +
|
2022-04-02 13:06:20 -04:00
|
|
|
"</div><div class='clearfix'></div>";
|
2022-02-27 19:26:54 +02:00
|
|
|
bootbox.dialog({
|
2021-08-22 16:31:49 -04:00
|
|
|
message: uploadHtml,
|
2024-08-26 20:11:03 -05:00
|
|
|
title:
|
|
|
|
"{{ translate('serverFiles', 'uploadTitle', data['lang'])}}" + path,
|
2021-08-22 16:31:49 -04:00
|
|
|
buttons: {
|
2022-02-27 19:26:54 +02:00
|
|
|
success: {
|
|
|
|
label: "{{ translate('serverFiles', 'upload', data['lang']) }}",
|
|
|
|
className: "btn-default",
|
|
|
|
callback: async function () {
|
2024-06-17 13:31:34 -04:00
|
|
|
if ($("#files").get(0).files.length === 0) {
|
|
|
|
return hideUploadBox();
|
|
|
|
}
|
2022-04-02 13:06:20 -04:00
|
|
|
var height = files.files.length * 50;
|
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
var waitMessage =
|
|
|
|
'<p class="text-center mb-0">' +
|
2023-02-01 17:34:07 -05:00
|
|
|
'<i class="fa fa-spin fa-cog"></i> ' +
|
2024-08-26 20:11:03 -05:00
|
|
|
"{{ translate('serverFiles', 'waitUpload', data['lang']) }}" +
|
|
|
|
"<br>" +
|
|
|
|
"<strong>" +
|
|
|
|
"{{ translate('serverFiles', 'stayHere', data['lang']) }}" +
|
|
|
|
"</strong>" +
|
|
|
|
"</p>" +
|
|
|
|
'<div class="progress" id="upload-progress-bar-parent" style="height:' +
|
|
|
|
height +
|
|
|
|
'px; width:100%; display: block;">' +
|
|
|
|
"</div>";
|
2022-04-02 13:06:20 -04:00
|
|
|
files = document.getElementById("files");
|
|
|
|
uploadWaitDialog = bootbox.dialog({
|
|
|
|
message: waitMessage,
|
2024-08-26 20:11:03 -05:00
|
|
|
closeButton: false,
|
2022-02-27 19:26:54 +02:00
|
|
|
});
|
2022-06-03 19:49:51 +01:00
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
let nFiles = files.files.length;
|
2024-05-26 23:08:43 -04:00
|
|
|
const uploadPromises = [];
|
2022-06-03 19:49:51 +01:00
|
|
|
|
2024-05-26 23:08:43 -04:00
|
|
|
for (let i = 0; i < nFiles; i++) {
|
|
|
|
const file = files.files[i];
|
2022-02-27 19:26:54 +02:00
|
|
|
const progressHtml = `
|
2024-05-26 23:08:43 -04:00
|
|
|
<div style="width: 100%; min-width: 100%;">
|
|
|
|
${file.name}:
|
|
|
|
<br><div
|
|
|
|
id="upload-progress-bar-${i + 1}"
|
|
|
|
class="progress-bar progress-bar-striped progress-bar-animated"
|
|
|
|
role="progressbar"
|
|
|
|
style="width: 100%; height: 10px;"
|
|
|
|
aria-valuenow="0"
|
|
|
|
aria-valuemin="0"
|
|
|
|
aria-valuemax="100"
|
|
|
|
></div>
|
|
|
|
</div><br>
|
|
|
|
`;
|
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
$("#upload-progress-bar-parent").append(progressHtml);
|
|
|
|
|
|
|
|
const uploadPromise = uploadFile(
|
|
|
|
"server_upload",
|
|
|
|
file,
|
|
|
|
path,
|
|
|
|
i,
|
|
|
|
(progress) => {
|
|
|
|
$(`#upload-progress-bar-${i + 1}`).attr(
|
|
|
|
"aria-valuenow",
|
|
|
|
progress
|
|
|
|
);
|
|
|
|
$(`#upload-progress-bar-${i + 1}`).css(
|
|
|
|
"width",
|
|
|
|
progress + "%"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
2024-05-26 23:08:43 -04:00
|
|
|
uploadPromises.push(uploadPromise);
|
|
|
|
}
|
|
|
|
|
2024-05-27 19:12:31 -04:00
|
|
|
await Promise.all(uploadPromises);
|
2024-06-19 13:28:39 -04:00
|
|
|
setTimeout(() => {
|
|
|
|
hideUploadBox();
|
|
|
|
}, 2000);
|
2024-08-26 20:11:03 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2022-02-27 19:26:54 +02:00
|
|
|
});
|
|
|
|
});
|
2021-12-20 12:51:27 -05:00
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
|
2024-05-27 19:12:31 -04:00
|
|
|
async function calculateFileHash(file) {
|
|
|
|
const arrayBuffer = await file.arrayBuffer();
|
2024-08-26 20:11:03 -05:00
|
|
|
const hashBuffer = await crypto.subtle.digest("SHA-256", arrayBuffer);
|
2024-05-27 19:12:31 -04:00
|
|
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
2024-08-26 20:11:03 -05:00
|
|
|
const hashHex = hashArray
|
|
|
|
.map((b) => b.toString(16).padStart(2, "0"))
|
|
|
|
.join("");
|
2024-05-27 19:12:31 -04:00
|
|
|
|
|
|
|
return hashHex;
|
|
|
|
}
|
|
|
|
|
2023-09-04 19:22:11 -04:00
|
|
|
function getDirView(event) {
|
2023-06-04 23:08:27 -04:00
|
|
|
let path = event.target.parentElement.getAttribute("data-path");
|
2024-08-26 20:11:03 -05:00
|
|
|
if (document.getElementById(path).classList.contains("clicked")) {
|
2023-06-04 23:08:27 -04:00
|
|
|
return;
|
2023-09-04 19:22:11 -04:00
|
|
|
} else {
|
2023-06-04 23:08:27 -04:00
|
|
|
getTreeView(path);
|
|
|
|
}
|
2022-04-02 13:06:20 -04:00
|
|
|
}
|
2023-09-04 19:22:11 -04:00
|
|
|
async function getTreeView(path) {
|
|
|
|
const token = getCookie("_xsrf");
|
2023-06-04 23:08:27 -04:00
|
|
|
let res = await fetch(`/api/v2/servers/${serverId}/files`, {
|
2024-08-26 20:11:03 -05:00
|
|
|
method: "POST",
|
2023-09-04 19:22:11 -04:00
|
|
|
headers: {
|
2024-08-26 20:11:03 -05:00
|
|
|
"X-XSRFToken": token,
|
2023-09-04 19:22:11 -04:00
|
|
|
},
|
2024-08-26 20:11:03 -05:00
|
|
|
body: JSON.stringify({ page: "files", path: path }),
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
let responseData = await res.json();
|
|
|
|
if (responseData.status === "ok") {
|
|
|
|
console.log(responseData);
|
|
|
|
process_tree_response(responseData);
|
|
|
|
} else {
|
|
|
|
bootbox.alert({
|
|
|
|
title: responseData.status,
|
2024-08-26 20:11:03 -05:00
|
|
|
message: responseData.error,
|
2023-09-04 19:22:11 -04:00
|
|
|
});
|
|
|
|
}
|
2023-06-04 23:08:27 -04:00
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2023-06-04 23:08:27 -04:00
|
|
|
function process_tree_response(response) {
|
|
|
|
let path = response.data.root_path.path;
|
|
|
|
let text = ``;
|
2023-09-04 19:22:11 -04:00
|
|
|
if (!response.data.root_path.top) {
|
2023-06-04 23:08:27 -04:00
|
|
|
text = `<ul class="tree-nested d-block" id="${path}ul">`;
|
|
|
|
}
|
2023-09-04 19:22:11 -04:00
|
|
|
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;
|
|
|
|
}
|
2024-08-26 20:11:03 -05:00
|
|
|
let checked = "";
|
2023-06-04 23:08:27 -04:00
|
|
|
let dpath = value.path;
|
|
|
|
let filename = key;
|
2023-09-04 19:22:11 -04:00
|
|
|
if (value.dir) {
|
|
|
|
if (value.excluded) {
|
2024-08-26 20:11:03 -05:00
|
|
|
checked = "checked";
|
2023-06-04 23:08:27 -04:00
|
|
|
}
|
|
|
|
text += `<li class="tree-item" id="${dpath}li" 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 d-none file-check" name="root_path" value="${dpath}" ${checked}>
|
|
|
|
<span id="${dpath}span" class="files-tree-title" data-path="${dpath}" data-name="${filename}" onclick="getDirView(event)">
|
2024-10-06 20:54:50 +02:00
|
|
|
<i class="far fa-folder text-info"></i>
|
|
|
|
<i class="far fa-folder-open text-info"></i>
|
2023-06-04 23:08:27 -04:00
|
|
|
${filename}
|
|
|
|
</span>
|
2024-08-26 20:11:03 -05:00
|
|
|
</input></div></li>`;
|
2023-09-04 19:22:11 -04:00
|
|
|
} else {
|
2023-06-04 23:08:27 -04:00
|
|
|
text += `<li
|
|
|
|
class="d-block tree-ctx-item tree-file"
|
|
|
|
data-path="${dpath}"
|
|
|
|
data-name="${filename}"
|
|
|
|
onclick="clickOnFile(event)" id="${dpath}li"><input type='checkbox' class="checkBoxClass d-none file-check" name='root_path' value="${dpath}" ${checked}><span style="margin-right: 6px;">
|
2024-08-26 20:11:03 -05:00
|
|
|
<i class="far fa-file"></i></span></input>${filename}</li>`;
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2023-06-04 23:08:27 -04:00
|
|
|
});
|
2023-09-04 19:22:11 -04:00
|
|
|
if (!response.data.root_path.top) {
|
2023-06-04 23:08:27 -04:00
|
|
|
text += `</ul>`;
|
|
|
|
}
|
2023-09-04 19:22:11 -04:00
|
|
|
if (response.data.root_path.top) {
|
2023-06-04 23:08:27 -04:00
|
|
|
try {
|
2024-08-26 20:11:03 -05:00
|
|
|
document.getElementById("main-tree-div").innerHTML += text;
|
|
|
|
document
|
|
|
|
.getElementById("main-tree")
|
|
|
|
.parentElement.classList.add("clicked");
|
2023-09-04 19:22:11 -04:00
|
|
|
} catch {
|
2024-08-26 20:11:03 -05:00
|
|
|
document.getElementById("files-tree").innerHTML = text;
|
2023-09-04 19:22:11 -04:00
|
|
|
}
|
|
|
|
} else {
|
2023-06-04 23:08:27 -04:00
|
|
|
try {
|
2024-08-26 20:11:03 -05:00
|
|
|
document.getElementById(path + "span").classList.add("tree-caret-down");
|
2023-09-04 19:22:11 -04:00
|
|
|
document.getElementById(path).innerHTML += text;
|
|
|
|
document.getElementById(path).classList.add("clicked");
|
|
|
|
} catch {
|
2024-08-26 20:11:03 -05:00
|
|
|
console.log("Bad");
|
2023-09-04 19:22:11 -04:00
|
|
|
}
|
2022-01-08 23:03:45 +00:00
|
|
|
|
2023-09-04 19:22:11 -04:00
|
|
|
var toggler = document.getElementById(path + "span");
|
2022-01-21 23:50:04 +01:00
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
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");
|
|
|
|
});
|
2023-09-04 19:22:11 -04:00
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
}
|
2024-08-26 20:11:03 -05:00
|
|
|
setTimeout(function () {
|
|
|
|
setTreeViewContext();
|
|
|
|
}, 1000);
|
2023-06-04 23:08:27 -04:00
|
|
|
}
|
|
|
|
function getToggleMain(event) {
|
2024-08-26 20:11:03 -05:00
|
|
|
path = event.target.parentElement.getAttribute("data-path");
|
2023-06-04 23:08:27 -04:00
|
|
|
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");
|
2021-08-20 14:58:52 -04:00
|
|
|
}
|
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
function setTreeViewContext() {
|
2024-08-26 20:11:03 -05:00
|
|
|
var treeItems = Array.from(
|
|
|
|
document.getElementsByClassName("tree-ctx-item")
|
|
|
|
);
|
|
|
|
|
|
|
|
treeItems.forEach((item) => {
|
|
|
|
if (
|
|
|
|
[
|
|
|
|
"iPad Simulator",
|
|
|
|
"iPhone Simulator",
|
|
|
|
"iPod Simulator",
|
|
|
|
"iPad",
|
|
|
|
"iPhone",
|
|
|
|
"iPod",
|
|
|
|
].includes(navigator.platform) ||
|
2022-03-22 14:24:15 +00:00
|
|
|
// iPad on iOS 13 detection
|
2024-08-26 20:11:03 -05:00
|
|
|
(navigator.userAgent.includes("Mac") && "ontouchend" in document)
|
|
|
|
) {
|
2022-06-03 19:49:51 +01:00
|
|
|
item.addEventListener("touchstart", touchstart, false);
|
|
|
|
item.addEventListener("touchend", touchend, false);
|
2022-04-02 13:06:20 -04:00
|
|
|
}
|
2024-08-26 20:11:03 -05:00
|
|
|
item.addEventListener("contextmenu", function contextListener(event) {
|
2022-02-27 19:26:54 +02:00
|
|
|
event.preventDefault();
|
2024-08-26 20:11:03 -05:00
|
|
|
var ctxmenuPath = event.target.getAttribute("data-path");
|
|
|
|
var ctxmenuName = event.target.getAttribute("data-name");
|
2022-02-27 19:26:54 +02:00
|
|
|
if (!ctxmenuPath) {
|
2024-08-26 20:11:03 -05:00
|
|
|
console.log({ "event.target": event.target, ctxmenuPath });
|
2022-02-27 19:26:54 +02:00
|
|
|
return;
|
|
|
|
}
|
2024-08-26 20:11:03 -05:00
|
|
|
$("#renameItem").show();
|
|
|
|
|
|
|
|
var isDir = event.target.classList.contains("files-tree-title");
|
|
|
|
$("#createFile").toggle(isDir);
|
|
|
|
$("#createDir").toggle(isDir);
|
|
|
|
$("#deleteDir").toggle(isDir);
|
|
|
|
$("#upload").toggle(isDir);
|
|
|
|
|
|
|
|
document.getElementById("context-title").innerHTML = ctxmenuName;
|
|
|
|
|
|
|
|
var isFile = event.target.classList.contains("tree-file");
|
|
|
|
$("#deleteFile").toggle(isFile);
|
|
|
|
$("#downloadFile").toggle(isFile);
|
|
|
|
|
|
|
|
if (event.target.classList.contains("root-dir")) {
|
|
|
|
$("#createFile").show();
|
|
|
|
$("#createDir").show();
|
|
|
|
$("#renameItem").hide();
|
|
|
|
$("#deleteDir").hide();
|
|
|
|
$("#deleteFile").hide();
|
|
|
|
$("#downloadFile").hide();
|
|
|
|
$("#upload").show();
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2024-08-26 20:11:03 -05:00
|
|
|
if (event.target.textContent.endsWith(".zip")) {
|
|
|
|
$("#unzip").show();
|
2022-02-27 19:26:54 +02:00
|
|
|
} else {
|
2024-08-26 20:11:03 -05:00
|
|
|
$("#unzip").hide();
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2022-04-02 13:06:20 -04:00
|
|
|
var clientX = event.clientX;
|
|
|
|
var clientY = event.clientY;
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
document
|
|
|
|
.getElementById("files-tree-nav-content")
|
|
|
|
.setAttribute("data-path", ctxmenuPath);
|
|
|
|
document
|
|
|
|
.getElementById("files-tree-nav-content")
|
|
|
|
.setAttribute("data-name", ctxmenuName);
|
2022-02-27 19:26:54 +02:00
|
|
|
document.getElementById("files-tree-nav").style.display = "flex";
|
|
|
|
document.getElementById("files-tree-nav").style.position = "fixed";
|
2024-08-26 20:11:03 -05:00
|
|
|
domRect = document
|
|
|
|
.getElementById("files-tree-nav")
|
|
|
|
.getBoundingClientRect();
|
|
|
|
sum = clientY + domRect["height"] - window.innerHeight;
|
|
|
|
if (domRect["height"] + clientY > window.innerHeight) {
|
|
|
|
clientY = clientY - sum;
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2024-08-26 20:11:03 -05:00
|
|
|
document.getElementById("files-tree-nav").style.top = clientY + "px";
|
|
|
|
document.getElementById("files-tree-nav").style.left = clientX + "px";
|
|
|
|
});
|
|
|
|
});
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
document.addEventListener("click", function (e) {
|
|
|
|
let inside = e.target.closest("#files-tree-nav");
|
|
|
|
let contextMenu = document.getElementById("files-tree-nav");
|
2022-02-27 19:26:54 +02:00
|
|
|
if (!inside) {
|
2024-08-26 20:11:03 -05:00
|
|
|
contextMenu.setAttribute("style", "display:none");
|
2022-02-27 19:26:54 +02:00
|
|
|
} else {
|
2024-08-26 20:11:03 -05:00
|
|
|
contextMenu.setAttribute("style", "display:none");
|
2021-08-24 21:33:29 -04:00
|
|
|
}
|
2022-02-27 19:26:54 +02:00
|
|
|
});
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
if (webSocket) {
|
2024-08-26 20:11:03 -05:00
|
|
|
webSocket.on("close_upload_box", function (close_upload_box) {
|
2022-02-27 19:26:54 +02:00
|
|
|
hideUploadBox();
|
|
|
|
});
|
|
|
|
}
|
2022-04-02 13:06:20 -04:00
|
|
|
function hideUploadBox() {
|
2022-02-27 19:26:54 +02:00
|
|
|
if (!uploadWaitDialog) return;
|
2024-08-26 20:11:03 -05:00
|
|
|
uploadWaitDialog.modal("hide");
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function createFileE(event) {
|
2024-08-26 20:11:03 -05:00
|
|
|
bootbox.prompt(
|
|
|
|
"{% raw translate('serverFiles', 'createFileQuestion', data['lang']) %}",
|
|
|
|
function (result) {
|
|
|
|
path = event.target.parentElement.getAttribute("data-path");
|
|
|
|
name = event.target.parentElement.getAttribute("data-name");
|
|
|
|
if (!result) return;
|
|
|
|
|
|
|
|
createFile(path, result, function () {
|
|
|
|
getTreeView();
|
|
|
|
document.getElementById("files-tree-nav").style.display = "none";
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
function createDirE(event) {
|
2024-08-26 20:11:03 -05:00
|
|
|
bootbox.prompt(
|
|
|
|
"{% raw translate('serverFiles', 'createDirQuestion', data['lang']) %}",
|
|
|
|
function (result) {
|
|
|
|
path = event.target.parentElement.getAttribute("data-path");
|
|
|
|
name = event.target.parentElement.getAttribute("data-name");
|
|
|
|
if (!result) return;
|
|
|
|
|
|
|
|
createDir(path, result, function () {
|
|
|
|
getTreeView();
|
|
|
|
document.getElementById("files-tree-nav").style.display = "none";
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
|
|
|
function downloadFileE(event) {
|
2024-08-26 20:11:03 -05:00
|
|
|
path = event.target.parentElement.getAttribute("data-path");
|
|
|
|
name = event.target.parentElement.getAttribute("data-name");
|
|
|
|
encoded_path = encodeURIComponent(path);
|
|
|
|
encoded_name = encodeURIComponent(name);
|
2022-11-30 20:28:24 -05:00
|
|
|
window.location.href = `/panel/download_file?id=${serverId}&path=${encoded_path}&name=${encoded_name}`;
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
function renameItemE(event) {
|
2024-08-26 20:11:03 -05:00
|
|
|
path = event.target.parentElement.getAttribute("data-path");
|
|
|
|
name = event.target.parentElement.getAttribute("data-name");
|
2022-02-27 19:26:54 +02:00
|
|
|
bootbox.prompt({
|
2024-08-26 20:11:03 -05:00
|
|
|
title:
|
|
|
|
"{% raw translate('serverFiles', 'renameItemQuestion', data['lang']) %}",
|
2022-02-27 19:26:54 +02:00
|
|
|
value: name,
|
2022-04-02 13:06:20 -04:00
|
|
|
callback: function (result) {
|
2022-02-27 19:26:54 +02:00
|
|
|
if (!result) return;
|
|
|
|
renameItem(path, result, function () {
|
2024-08-26 20:11:03 -05:00
|
|
|
getTreeView();
|
|
|
|
document.getElementById("files-tree-nav").style.display = "none";
|
2022-02-27 19:26:54 +02:00
|
|
|
});
|
2024-08-26 20:11:03 -05:00
|
|
|
},
|
2022-02-27 19:26:54 +02:00
|
|
|
});
|
|
|
|
}
|
2022-04-02 13:06:20 -04:00
|
|
|
function unzipFilesE(event) {
|
2024-08-26 20:11:03 -05:00
|
|
|
path = event.target.parentElement.getAttribute("data-path");
|
|
|
|
console.log(path);
|
|
|
|
unZip(path);
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function deleteFileE(event) {
|
2024-08-26 20:11:03 -05:00
|
|
|
path = event.target.parentElement.getAttribute("data-path");
|
|
|
|
name = event.target.parentElement.getAttribute("data-name");
|
2022-02-27 19:26:54 +02:00
|
|
|
bootbox.confirm({
|
2022-04-02 13:06:20 -04:00
|
|
|
size: "",
|
2024-08-26 20:11:03 -05:00
|
|
|
title:
|
|
|
|
"{% raw translate('serverFiles', 'deleteItemQuestion', data['lang']) %}",
|
2022-04-02 13:06:20 -04:00
|
|
|
closeButton: false,
|
2024-08-26 20:11:03 -05:00
|
|
|
message:
|
|
|
|
"{% raw translate('serverFiles', 'deleteItemQuestionMessage', data['lang']) %}",
|
2022-04-02 13:06:20 -04:00
|
|
|
buttons: {
|
|
|
|
confirm: {
|
|
|
|
label: "{{ translate('serverFiles', 'yesDelete', data['lang']) }}",
|
2024-08-26 20:11:03 -05:00
|
|
|
className: "btn-danger",
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
|
|
|
cancel: {
|
|
|
|
label: "{{ translate('serverFiles', 'noDelete', data['lang']) }}",
|
2024-08-26 20:11:03 -05:00
|
|
|
className: "btn-link",
|
|
|
|
},
|
2022-02-27 19:26:54 +02:00
|
|
|
},
|
2022-04-02 13:06:20 -04:00
|
|
|
callback: function (result) {
|
2022-02-27 19:26:54 +02:00
|
|
|
if (!result) return;
|
2023-06-05 18:20:45 -04:00
|
|
|
deleteItem(path);
|
2024-08-26 20:11:03 -05:00
|
|
|
},
|
2022-02-27 19:26:54 +02:00
|
|
|
});
|
|
|
|
}
|
2021-01-17 19:20:28 +02:00
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
getTreeView($("#root_dir").data("path"));
|
2022-02-27 19:26:54 +02:00
|
|
|
setTreeViewContext();
|
2021-01-23 00:12:52 +02:00
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
function setKeyboard(target) {
|
2024-08-26 20:11:03 -05:00
|
|
|
var handlerName = target.getAttribute("data-handler-name");
|
|
|
|
if (handlerName == "null") handlerName = null;
|
2022-06-14 02:45:17 +03:00
|
|
|
editor.setKeyboardHandler(handlerName, () => {
|
2024-08-26 20:11:03 -05:00
|
|
|
if (handlerName == "ace/keyboard/vim") {
|
|
|
|
require("ace/keyboard/vim").Vim.defineEx("write", "w", function () {
|
2022-06-14 02:45:17 +03:00
|
|
|
save();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2021-01-23 00:12:52 +02:00
|
|
|
|
2022-02-27 19:26:54 +02:00
|
|
|
var nodes = target.parentNode.querySelectorAll("[data-handler-name]");
|
2024-08-26 20:11:03 -05:00
|
|
|
nodes.forEach((node) => {
|
|
|
|
node.classList.remove("btn-primary");
|
|
|
|
node.classList.add("btn-secondary");
|
|
|
|
});
|
2021-01-23 00:12:52 +02:00
|
|
|
|
2024-08-26 20:11:03 -05:00
|
|
|
target.classList.remove("btn-secondary");
|
|
|
|
target.classList.add("btn-primary");
|
2022-02-27 19:26:54 +02:00
|
|
|
}
|
2021-01-15 14:13:06 +02:00
|
|
|
</script>
|
2024-05-27 19:12:31 -04:00
|
|
|
<script src="../../static/assets/js/shared/upload.js"></script>
|
2024-10-04 23:33:54 +02:00
|
|
|
{% end %}
|