mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Now can see a tree view of the directory the server is in. Will do file editing now.
This commit is contained in:
parent
c08751c7f8
commit
eba7bff050
@ -462,7 +462,7 @@ class Helpers:
|
||||
if os.path.isdir(rel):
|
||||
html += '<li>\n<span class="tree-caret">{}</span>\n<ul class="tree-nested">'.format(filename)
|
||||
html += helper.generate_tree(rel)
|
||||
html += '</ul>'
|
||||
html += '</ul>\n</li>'
|
||||
else:
|
||||
html += '<li>{}</li>'.format(filename)
|
||||
return html
|
||||
|
@ -62,24 +62,6 @@ class PanelHandler(BaseHandler):
|
||||
elif page == 'file_edit':
|
||||
template = "panel/file_edit.html"
|
||||
|
||||
elif page == 'files':
|
||||
server_id = self.get_argument('id', None)
|
||||
|
||||
if server_id is None:
|
||||
self.redirect("/panel/error?error=Invalid Server ID")
|
||||
return False
|
||||
else:
|
||||
server_id = bleach.clean(server_id)
|
||||
|
||||
# does this server id exist?
|
||||
if not db_helper.server_id_exists(server_id):
|
||||
self.redirect("/panel/error?error=Invalid Server ID")
|
||||
return False
|
||||
|
||||
page_data['tree_html'] = helper.generate_tree(db_helper.get_server_data_by_id(server_id)['path'])
|
||||
|
||||
template = "panel/files.html"
|
||||
|
||||
elif page == "remove_server":
|
||||
server_id = self.get_argument('id', None)
|
||||
server_data = controller.get_server_data(server_id)
|
||||
@ -121,10 +103,15 @@ class PanelHandler(BaseHandler):
|
||||
self.redirect("/panel/error?error=Invalid Server ID")
|
||||
return False
|
||||
|
||||
valid_subpages = ['term', 'logs', 'config']
|
||||
valid_subpages = ['term', 'logs', 'config', 'files']
|
||||
|
||||
if subpage not in valid_subpages:
|
||||
console.debug('not a valid subpage')
|
||||
subpage = 'term'
|
||||
console.debug('Subpage: "{}"'.format(subpage))
|
||||
if subpage == 'files':
|
||||
console.debug('Subpage is "files"')
|
||||
page_data['tree_html'] = helper.generate_tree(db_helper.get_server_data_by_id(server_id)['path'])
|
||||
|
||||
# server_data isn't needed since the server_stats also pulls server data
|
||||
# page_data['server_data'] = db_helper.get_server_data_by_id(server_id)
|
||||
|
@ -1,173 +0,0 @@
|
||||
{% extends ../base.html %}
|
||||
|
||||
{% block meta %}
|
||||
<!-- <meta http-equiv="refresh" content="60">-->
|
||||
{% end %}
|
||||
|
||||
{% block title %}Crafty Controller - Looking at files in server -< server name >- (-< server path id >-){% 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">
|
||||
Looking at files in server -< server name >- (-< server path id >-)
|
||||
<br />
|
||||
<small>Path: -< location relative to server directory >-</small>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- Page Title Header Ends-->
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-6">
|
||||
<noscript>
|
||||
Some functionality does not work without JavaScript.
|
||||
</noscript>
|
||||
<ul class="tree-view">
|
||||
<li>
|
||||
<span class="tree-caret">Files</span>
|
||||
<ul class="tree-nested">
|
||||
{{ data['tree_html'] }}
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<style>
|
||||
/* Remove default bullets */
|
||||
.tree-view {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Style the caret/arrow */
|
||||
.tree-caret {
|
||||
cursor: pointer;
|
||||
user-select: none; /* Prevent text selection */
|
||||
}
|
||||
|
||||
/* Create the caret/arrow with a unicode, and style it */
|
||||
.tree-caret::before {
|
||||
content: "\25B6";
|
||||
color: white;
|
||||
display: inline-block;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
|
||||
.tree-caret-down::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
/* Hide the nested list */
|
||||
.tree-nested {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<div class="col-6">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var toggler = document.getElementsByClassName("tree-caret");
|
||||
var i;
|
||||
|
||||
for (i = 0; i < toggler.length; i++) {
|
||||
toggler[i].addEventListener("click", function() {
|
||||
this.parentElement.querySelector(".tree-nested").classList.toggle("d-block");
|
||||
this.classList.toggle("tree-caret-down");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- <div class="col-sm-12 grid-margin">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
|
||||
<ul class="files-list list-group">
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center"
|
||||
style="background-color: var(--dark) !important;">
|
||||
<a href="/panel/file_edit?path=-< file location relative to server directory >-" class="text-white">-< name >-</a>
|
||||
<span>
|
||||
<a href="/panel/file_edit?path=-< file location relative to server directory >-" class="mx-1 btn btn-dark">Edit</a>
|
||||
<button onclick="alert('will make a modal')" class="mx-1 btn btn-dark">Rename</button>
|
||||
<button onclick="alert('will make a confirmation modal')" class="mx-1 btn btn-danger">Delete</button>
|
||||
<span style="margin-left: 0.3rem;width: 5rem;display: inline-block;">
|
||||
<span class="badge badge-primary badge-pill">File</span>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center"
|
||||
style="background-color: var(--dark) !important;">
|
||||
<a href="/panel/files_menu?path=-< location relative to server directory >-" class="text-white">-< name >-</a>
|
||||
<span>
|
||||
<a href="/panel/files_menu?path=-< location relative to server directory >-" class="mx-1 btn btn-dark">Open</a>
|
||||
<button onclick="alert('will make a modal')" class="mx-1 btn btn-dark">Rename</button>
|
||||
<button onclick="alert('will make a confirmation modal')" class="mx-1 btn btn-danger">Delete</button>
|
||||
<span style="margin-left: 0.3rem;width: 5rem;display: inline-block;">
|
||||
<span class="badge badge-primary badge-pill">Folder</span>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
<a!--
|
||||
|
||||
File:
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center"
|
||||
style="background-color: var(--dark) !important;">
|
||||
<a href="/panel/file_edit?path=-< file location relative to server directory >-" class="text-white">-< name >-</a>
|
||||
<span>
|
||||
<a href="/panel/file_edit?path=-< file location relative to server directory >-" class="mx-1 btn btn-dark">Edit</a>
|
||||
<button onclick="alert('will make a modal')" class="mx-1 btn btn-dark">Rename</button>
|
||||
<button onclick="alert('will make a confirmation modal')" class="mx-1 btn btn-danger">Delete</button>
|
||||
<span style="margin-left: 0.3rem;width: 5rem;display: inline-block;">
|
||||
<span class="badge badge-primary badge-pill">File</span>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
Folder:
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center"
|
||||
style="background-color: var(--dark) !important;">
|
||||
<a href="/panel/files_menu?path=-< location relative to server directory >-" class="text-white">-< name >-</a>
|
||||
<span>
|
||||
<a href="/panel/files_menu?path=-< location relative to server directory >-" class="mx-1 btn btn-dark">Open</a>
|
||||
<button onclick="alert('will make a modal')" class="mx-1 btn btn-dark">Rename</button>
|
||||
<button onclick="alert('will make a confirmation modal')" class="mx-1 btn btn-danger">Delete</button>
|
||||
<span style="margin-left: 0.3rem;width: 5rem;display: inline-block;">
|
||||
<span class="badge badge-primary badge-pill">Folder</span>
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
--a>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- content-wrapper ends -->
|
||||
|
||||
{% end %}
|
||||
|
||||
{% block js %}
|
||||
|
||||
<script>
|
||||
|
||||
// empty for now
|
||||
|
||||
</script>
|
||||
|
||||
{% end %}
|
296
app/frontend/templates/panel/server_files.html
Normal file
296
app/frontend/templates/panel/server_files.html
Normal file
@ -0,0 +1,296 @@
|
||||
{% extends ../base.html %}
|
||||
|
||||
{% block meta %}
|
||||
<!-- <meta http-equiv="refresh" content="60">-->
|
||||
{% end %}
|
||||
|
||||
{% block title %}Crafty Controller - Server Details{% 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">
|
||||
Server Details - {{ data['server_stats'][0]['server_id']['server_name'] }}
|
||||
<br />
|
||||
<small>UUID: {{ data['server_stats'][0]['server_id']['server_uuid'] }}</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">
|
||||
<ul class="nav nav-tabs col-md-12 tab-simple-styled " role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/panel/server_detail?id={{ data['server_stats'][0]['server_id']['server_id'] }}&subpage=term" role="tab" aria-selected="false">
|
||||
<i class="fas fa-file-signature"></i>Terminal</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/panel/server_detail?id={{ data['server_stats'][0]['server_id']['server_id'] }}&subpage=logs" role="tab" aria-selected="false">
|
||||
<i class="fas fa-file-signature"></i>Logs</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/panel/server_detail?id={{ data['server_stats'][0]['server_id']['server_id'] }}&subpage=tasks" role="tab" aria-selected="false">
|
||||
<i class="fas fa-clock"></i>Schedule</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/panel/server_detail?id={{ data['server_stats'][0]['server_id']['server_id'] }}&subpage=backup" role="tab" aria-selected="false">
|
||||
<i class="fas fa-save"></i>Backup</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/panel/server_detail?id={{ data['server_stats'][0]['server_id']['server_id'] }}&subpage=files" role="tab" aria-selected="false">
|
||||
<i class="fas fa-folder-tree"></i>Files</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/panel/server_detail?id={{ data['server_stats'][0]['server_id']['server_id'] }}&subpage=config" role="tab" aria-selected="true">
|
||||
<i class="fas fa-cogs"></i>Config</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-sm-12">
|
||||
<noscript>
|
||||
The file manager does not work without JavaScript
|
||||
</noscript>
|
||||
<ul class="tree-view">
|
||||
<li>
|
||||
<span class="tree-caret">Files</span>
|
||||
<ul class="tree-nested" id="files-tree">
|
||||
<li>Error while getting files</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<style>
|
||||
/* Remove default bullets */
|
||||
.tree-view {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Style the caret/arrow */
|
||||
.tree-caret {
|
||||
cursor: pointer;
|
||||
user-select: none; /* Prevent text selection */
|
||||
}
|
||||
|
||||
/* Create the caret/arrow with a unicode, and style it */
|
||||
.tree-caret::before {
|
||||
content: "\25B6";
|
||||
color: white;
|
||||
display: inline-block;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
|
||||
.tree-caret-down::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
/* Hide the nested list */
|
||||
.tree-nested {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<div class="col-md-6 col-sm-12">
|
||||
TODO: edit files<br/><br/>
|
||||
Editing file <span id="editingFile"></span>
|
||||
<div id="editor">file_contents</div>
|
||||
<h3 id="file_warn"></h3>
|
||||
<button class="btn btn-success" onclick="save()">Save</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
var encoded = `{{ data['tree_html'] }}`;
|
||||
var elem = document.createElement('textarea');
|
||||
elem.innerHTML = encoded;
|
||||
var decoded = elem.value;
|
||||
|
||||
document.getElementById('files-tree').innerHTML = decoded;
|
||||
|
||||
|
||||
var toggler = document.getElementsByClassName("tree-caret");
|
||||
var i;
|
||||
|
||||
for (i = 0; i < toggler.length; i++) {
|
||||
toggler[i].addEventListener("click", function() {
|
||||
this.parentElement.querySelector(".tree-nested").classList.toggle("d-block");
|
||||
this.classList.toggle("tree-caret-down");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<!-- content-wrapper ends -->
|
||||
|
||||
{% end %}
|
||||
|
||||
{% block js %}
|
||||
<script src="/static/assets/vendors/ace-builds/src-min/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
|
||||
<script>
|
||||
|
||||
let editor = ace.edit('editor');
|
||||
editor.setTheme('ace/theme/dracula');
|
||||
|
||||
let extensionChanges = [
|
||||
{
|
||||
regex: /^js$/,
|
||||
replaceWith: 'ace/mode/javascript'
|
||||
},
|
||||
{
|
||||
regex: /^py$/,
|
||||
replaceWith: 'ace/mode/python'
|
||||
},
|
||||
{
|
||||
regex: /^html$/,
|
||||
replaceWith: 'ace/mode/html'
|
||||
},
|
||||
{
|
||||
regex: /^yml$/,
|
||||
replaceWith: 'ace/mode/yaml'
|
||||
},
|
||||
{
|
||||
regex: /^yaml$/,
|
||||
replaceWith: 'ace/mode/yaml'
|
||||
},
|
||||
{
|
||||
regex: /^txt$/,
|
||||
replaceWith: 'ace/mode/text'
|
||||
},
|
||||
{
|
||||
regex: /^json$/,
|
||||
replaceWith: 'ace/mode/json'
|
||||
},
|
||||
{
|
||||
regex: /^java$/,
|
||||
replaceWith: 'ace/mode/java'
|
||||
},
|
||||
{
|
||||
regex: /^cpp$/,
|
||||
replaceWith: 'ace/mode/c_cpp'
|
||||
},
|
||||
{
|
||||
regex: /^css$/,
|
||||
replaceWith: 'ace/mode/css'
|
||||
},
|
||||
{
|
||||
regex: /^scss$/,
|
||||
replaceWith: 'ace/mode/scss'
|
||||
},
|
||||
{
|
||||
regex: /^sass$/,
|
||||
replaceWith: 'ace/mode/sass'
|
||||
},
|
||||
{
|
||||
regex: /^lua$/,
|
||||
replaceWith: 'ace/mode/lua'
|
||||
},
|
||||
{
|
||||
regex: /^php$/,
|
||||
replaceWith: 'ace/mode/php'
|
||||
},
|
||||
{
|
||||
regex: /^ps1$/,
|
||||
replaceWith: 'ace/mode/powershell'
|
||||
},
|
||||
{
|
||||
regex: /^svg$/,
|
||||
replaceWith: 'ace/mode/svg'
|
||||
},
|
||||
{
|
||||
regex: /^sh$/,
|
||||
replaceWith: 'ace/mode/sh'
|
||||
},
|
||||
{
|
||||
regex: /^xml$/,
|
||||
replaceWith: 'ace/mode/xml'
|
||||
},
|
||||
{
|
||||
regex: /^ts$/,
|
||||
replaceWith: 'ace/mode/typescript'
|
||||
}
|
||||
];
|
||||
|
||||
function setFileName(name) {
|
||||
let fileName = name || 'default.txt';
|
||||
document.getElementById('editingFile').innerText = fileName;
|
||||
|
||||
if (fileName.match('.')) {
|
||||
|
||||
// The pop method removes and returns the last element.
|
||||
setMode(fileName
|
||||
.split('.')
|
||||
.pop()
|
||||
.replace('ace/mode/', ''));
|
||||
|
||||
} else {
|
||||
setMode('txt');
|
||||
document
|
||||
.querySelector('#file_warn')
|
||||
.innerText = 'Warning: This is not a supported language';
|
||||
}
|
||||
}
|
||||
|
||||
setFileName();
|
||||
|
||||
function setMode (extension) {
|
||||
// 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) => {
|
||||
return extension.match(element.regex)
|
||||
? element.replaceWith
|
||||
: output;
|
||||
}, extension);
|
||||
|
||||
if (!aceMode.startsWith('ace/mode/')) {
|
||||
document
|
||||
.querySelector('#file_warn')
|
||||
.innerText = 'Warning: This is not a supported language';
|
||||
} else {
|
||||
document
|
||||
.querySelector('#file_warn')
|
||||
.innerText = '';
|
||||
|
||||
console.log(aceMode || 'ace/mode/text');
|
||||
editor.session.setMode(aceMode || 'ace/mode/text');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function save() {
|
||||
let text = editor.session.getValue();
|
||||
// Use AJAX or something
|
||||
alert(text);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
{% end %}
|
Loading…
Reference in New Issue
Block a user