Browse Source

Tiny improvements for filebrowser

master
Torsten Stauder 5 years ago
parent
commit
ea6fdc1f9c
  1. 138
      html/management.html
  2. 410
      src/HTMLmanagement.h
  3. 8
      src/main.cpp

138
html/management.html

@ -131,14 +131,14 @@
<div class="container" id="fileExplorer">
<div class="ui-widget">
<div class="filetree demo" id="explorerTree"></div>
<form id="explorerUploadForm" method="POST" enctype="multipart/form-data" action="/explorer" accept-charset="iso-8859-1">
<input id="explorerUploadedFiles" type="file" class="form-control-file" name="explorerUploadFiles" multiple> <input type="submit" class="btn btn-primary" id="submit" value="Hochladen">
</form>
<div>
<progress id="explorerUploadProgress" style="margin-top:10px" value="0" max="100"></progress> <span id="explorerUploadPercent"></span>
</div>
</div>
</div>
</div>
@ -458,12 +458,12 @@
data.instance.rename_node(data.instance._model.data[key], lastFolder);
});
}
// File Explorer functions begin
/* File Explorer functions begin*/
var lastSelectedNodePath = "";
$('#explorerTree').on('select_node.jstree', function (e, data) {
$('input[name=fileOrUrl]').val(data.node.data.path);
if (data.node.type == "folder") {
@ -486,7 +486,7 @@
if(!sel.length) { return false; }
sel = sel[0];
var children = $("#explorerTree").jstree("get_children_dom",sel);
// refresh only, when there is no child -> possible not yet updated
/* refresh only, when there is no child -> possible not yet updated */
if(children.length < 1){
refreshNode(sel);
}
@ -497,7 +497,7 @@
});
function doRest(path, callback, obj) {
obj.url = path;
obj.dataType = "json";
@ -510,48 +510,48 @@
};
obj.error = function(jqXHR, textStatus, errorThrown) {
console.log("AJAX error");
//debugger;
/*debugger; */
};
jQuery.ajax(obj);
} // doRest
} /* doRest */
function getData(path, callback) {
doRest(path, callback, {
method : "GET"
});
} // getData
} /* getData */
function deleteData(path, callback, _data) {
doRest(path, callback, {
method : "DELETE",
data: _data
});
} // deleteData
} /* deleteData */
function patchData(path, callback, _data) {
doRest(path, callback, {
method : "PATCH",
data: _data
});
} // patchData
} /* patchData */
function postData(path, callback, _data) {
doRest(path, callback, {
method : "POST",
data: _data
});
} // postData
} /* postData */
function putData(path, callback, _data) {
doRest(path, callback, {
method : "PUT",
data: _data
});
} // putData
// File Upload
} /* putData */
/* File Upload */
$('#explorerUploadForm').submit(function(e){
e.preventDefault();
console.log("Upload!");
@ -566,12 +566,12 @@
if(selectedNode.data.directory){
path = selectedNode.data.path
} else {
// remap sel to parent folder
/* remap sel to parent folder */
sel = ref.get_node(ref.get_parent(sel));
path = parentNode.data.path;
console.log("Parent path: " + path);
}
$.ajax({
url: '/explorer?path=' + path,
type: 'POST',
@ -604,19 +604,19 @@
console.log("Upload success!");
getData("/explorer?path=" + path, function(data) {
// We now have data!
/* We now have data! */
deleteChildrenNodes(sel);
addFileDirectory(sel, data);
ref.open_node(sel);
});
}
});
});
// File Delete
/* File Delete */
function handleDeleteData(nodeId) {
var ref = $('#explorerTree').jstree(true);
var node = ref.get_node(nodeId);
@ -652,7 +652,7 @@
}
return 0;
}
function createChild(nodeId, data) {
var ref = $('#explorerTree').jstree(true);
var node = ref.get_node(nodeId);
@ -664,11 +664,11 @@
directory: data.dir
}
}
return child;
}
function deleteChildrenNodes(nodeId) {
var ref = $('#explorerTree').jstree(true);
var children = $("#explorerTree").jstree("get_children_dom",nodeId);
@ -676,30 +676,30 @@
{
ref.delete_node(children[i].id);
}
}
function refreshNode(nodeId) {
var ref = $('#explorerTree').jstree(true);
var node = ref.get_node(nodeId);
getData("/explorer?path=" + node.data.path, function(data) {
// We now have data!
/* We now have data! */
deleteChildrenNodes(nodeId);
addFileDirectory(nodeId, data);
ref.open_node(nodeId);
});
}
function getType(data) {
var type = "";
if(data.dir) {
type = "folder";
} else if ((/\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|flac|FLAC)$/i).test(data.name)) {
@ -707,24 +707,24 @@
} else {
type = "file";
}
return type;
}
function addFileDirectory(parent, data) {
data.sort( fileNameSort );
var ref = $('#explorerTree').jstree(true);
for (var i=0; i<data.length; i++) {
console.log("Create Node");
ref.create_node(parent, createChild(parent, data[i]));
}
} // addFileDirectory
} /* addFileDirectory */
function buildFileSystemTree(path) {
$('#explorerTree').jstree({
"core" : {
"check_callback" : true,
@ -777,8 +777,8 @@
}
}
}
// Play
/* Play */
items.play = {
label: "Abspielen",
action: function(x) {
@ -786,16 +786,16 @@
postData("/exploreraudio?path=" + node.data.path + "&playmode=" + playMode);
}
}
// Refresh
/* Refresh */
items.refresh = {
label: "Aktualisieren",
action: function(x) {
refreshNode(nodeId);
}
}
// Delete
/* Delete */
items.delete = {
label: "Loeschen",
action: function(x) {
@ -803,8 +803,8 @@
refreshNode(ref.get_parent(nodeId));
}
}
// Rename
/* Rename */
items.rename = {
label: "Umbenennen",
action: function(x) {
@ -816,22 +816,22 @@
});
}
}
return items;
}
}
});
if (path.length == 0) {
return;
}
getData("/explorer?path=/", function(data) {
// We now have data!
/* We now have data! */
$('#explorerTree').jstree(true).settings.core.data.children = [];
data.sort( fileNameSort );
for (var i=0; i<data.length; i++) {
var newChild = {
text: data[i].name,
@ -846,12 +846,12 @@
}
$("#explorerTree").jstree(true).refresh();
});
} // buildFileSystemTree
} /* buildFileSystemTree */
// File Explorer functions end
/* File Explorer functions end */
function renderFileTree() {
var filesURI = "/files";

410
src/HTMLmanagement.h

@ -117,6 +117,7 @@ static const char management_HTML[] PROGMEM = "<!DOCTYPE html>\
<nav>\
<div class=\"container nav nav-tabs\" id=\"nav-tab\" role=\"tablist\">\
<a class=\"nav-item nav-link active\" id=\"nav-rfid-tab\" data-toggle=\"tab\" href=\"#nav-rfid\" role=\"tab\" aria-controls=\"nav-rfid\" aria-selected=\"true\"><i class=\"fas fa-dot-circle\"></i> RFID</a>\
<a class=\"nav-item nav-link\" id=\"nav-files-tab\" data-toggle=\"tab\" href=\"#nav-files\" role=\"tab\" aria-controls=\"nav-files\" aria-selected=\"false\"><i class=\"fas fa-folder\"></i> Dateien</a>\
<a class=\"nav-item nav-link\" id=\"nav-wifi-tab\" data-toggle=\"tab\" href=\"#nav-wifi\" role=\"tab\" aria-controls=\"nav-wifi\" aria-selected=\"false\"><i class=\"fas fa-wifi\"></i><span class=\".d-sm-none .d-md-block\"> WLAN</span></a>\
%SHOW_MQTT_TAB%\
%SHOW_FTP_TAB%\
@ -126,6 +127,21 @@ static const char management_HTML[] PROGMEM = "<!DOCTYPE html>\
</nav>\
<br>\
<div class=\"tab-content\" id=\"nav-tabContent\">\
<div class=\"tab-pane fade\" id=\"nav-files\" role=\"tabpanel\" aria-labelledby=\"nav-files-tab\">\
<div class=\"container\" id=\"fileExplorer\">\
<div class=\"ui-widget\">\
<div class=\"filetree demo\" id=\"explorerTree\"></div>\
\
<form id=\"explorerUploadForm\" method=\"POST\" enctype=\"multipart/form-data\" action=\"/explorer\" accept-charset=\"iso-8859-1\">\
<input id=\"explorerUploadedFiles\" type=\"file\" class=\"form-control-file\" name=\"explorerUploadFiles\" multiple> <input type=\"submit\" class=\"btn btn-primary\" id=\"submit\" value=\"Hochladen\">\
</form>\
<div>\
<progress id=\"explorerUploadProgress\" style=\"margin-top:10px\" value=\"0\" max=\"100\"></progress> <span id=\"explorerUploadPercent\"></span>\
</div>\
\
</div>\
</div>\
</div>\
<div class=\"tab-pane fade\" id=\"nav-wifi\" role=\"tabpanel\" aria-labelledby=\"nav-wifi-tab\">\
<div class=\"container\" id=\"wifiConfig\">\
<form action=\"#wifiConfig\" method=\"POST\" onsubmit=\"wifiConfig('wifiConfig'); return false\">\
@ -443,6 +459,399 @@ static const char management_HTML[] PROGMEM = "<!DOCTYPE html>\
});\
}\
\
/* File Explorer functions begin*/\
var lastSelectedNodePath = \"\";\
\
$('#explorerTree').on('select_node.jstree', function (e, data) {\
\
$('input[name=fileOrUrl]').val(data.node.data.path);\
\
if (data.node.type == \"folder\") {\
$('.option-folder').show();\
$('.option-file').hide();\
$('#playMode option').removeAttr('selected').filter('[value=3]').attr('selected', true);\
}\
\
if (data.node.type == \"audio\") {\
$('.option-file').show();\
$('.option-folder').hide();\
$('#playMode option').removeAttr('selected').filter('[value=1]').attr('selected', true);\
}\
\
if(lastSelectedNodePath != data.node.data.path) {\
if (data.node.data.directory) {\
\
var ref = $('#explorerTree').jstree(true),\
sel = ref.get_selected();\
if(!sel.length) { return false; }\
sel = sel[0];\
var children = $(\"#explorerTree\").jstree(\"get_children_dom\",sel);\
/* refresh only, when there is no child -> possible not yet updated */\
if(children.length < 1){\
refreshNode(sel);\
}\
\
}\
lastSelectedNodePath = data.node.data.path;\
}\
\
\
});\
\
function doRest(path, callback, obj) {\
obj.url = path;\
obj.dataType = \"json\";\
obj.contentType= \"application/json;charset=iso-8859-1\",\
obj.scriptCharset= \"iso-8859-1\",\
obj.success = function(data, textStatus, jqXHR) {\
if (callback) {\
callback(data);\
}\
};\
obj.error = function(jqXHR, textStatus, errorThrown) {\
console.log(\"AJAX error\");\
/*debugger; */\
};\
jQuery.ajax(obj);\
} /* doRest */\
\
function getData(path, callback) {\
doRest(path, callback, {\
method : \"GET\"\
});\
} /* getData */\
\
function deleteData(path, callback, _data) {\
doRest(path, callback, {\
method : \"DELETE\",\
data: _data\
});\
} /* deleteData */\
\
function patchData(path, callback, _data) {\
doRest(path, callback, {\
method : \"PATCH\",\
data: _data\
});\
} /* patchData */\
\
function postData(path, callback, _data) {\
doRest(path, callback, {\
method : \"POST\",\
data: _data\
});\
} /* postData */\
\
\
function putData(path, callback, _data) {\
doRest(path, callback, {\
method : \"PUT\",\
data: _data\
});\
} /* putData */\
\
\
/* File Upload */\
$('#explorerUploadForm').submit(function(e){\
e.preventDefault();\
console.log(\"Upload!\");\
var data = new FormData(this);\
\
var ref = $('#explorerTree').jstree(true),\
sel = ref.get_selected(),\
path = \"/\";\
if(!sel.length) { alert(\"Please select the upload location!\");return false; }\
sel = sel[0];\
selectedNode = ref.get_node(sel);\
if(selectedNode.data.directory){\
path = selectedNode.data.path\
} else {\
/* remap sel to parent folder */\
sel = ref.get_node(ref.get_parent(sel));\
path = parentNode.data.path;\
console.log(\"Parent path: \" + path);\
}\
\
$.ajax({\
url: '/explorer?path=' + path,\
type: 'POST',\
data: data,\
contentType: false,\
processData:false,\
xhr: function() {\
var xhr = new window.XMLHttpRequest();\
\
xhr.upload.addEventListener(\"progress\", function(evt) {\
if (evt.lengthComputable) {\
var percentComplete = evt.loaded / evt.total;\
percentComplete = parseInt(percentComplete * 100);\
console.log(percentComplete);\
document.getElementById(\"explorerUploadProgress\").value = percentComplete;\
document.getElementById(\"explorerUploadPercent\").innerHTML = percentComplete + \"%\";\
\
if (percentComplete === 100) {\
\
}\
\
Sleep(1000);\
\
}\
}, false);\
\
return xhr;\
},\
success: function(data, textStatus, jqXHR) {\
console.log(\"Upload success!\");\
\
getData(\"/explorer?path=\" + path, function(data) {\
/* We now have data! */\
deleteChildrenNodes(sel);\
addFileDirectory(sel, data);\
ref.open_node(sel);\
\
\
});\
\
}\
});\
});\
\
/* File Delete */\
function handleDeleteData(nodeId) {\
var ref = $('#explorerTree').jstree(true);\
var node = ref.get_node(nodeId);\
var children = $(\"#explorerTree\").jstree(\"get_children_dom\",nodeId);\
console.log(children.length);\
if(node.data.directory) {\
if(children.length > 0) {\
for(var i=0;i<children.length;i++)\
{\
console.log(\"call delete function for: \" + children[i].text);\
handleDeleteData(children[i].id);\
}\
}\
}\
console.log(\"call delete request: \" + node.data.path);\
deleteData(\"/explorer?path=\" + node.data.path);\
}\
function Sleep(milliseconds) {\
return new Promise(resolve => setTimeout(resolve, milliseconds));\
}\
function fileNameSort( a, b ) {\
if ( a.dir && !b.dir ) {\
return -1\
}\
if ( !a.dir && b.dir ) {\
return 1\
}\
if ( a.name < b.name ){\
return -1;\
}\
if ( a.name > b.name ){\
return 1;\
}\
return 0;\
}\
\
function createChild(nodeId, data) {\
var ref = $('#explorerTree').jstree(true);\
var node = ref.get_node(nodeId);\
var child = {\
text: data.name,\
type: getType(data),\
data: {\
path: node.data.path + \"/\" + data.name,\
directory: data.dir\
}\
}\
\
return child;\
\
}\
\
function deleteChildrenNodes(nodeId) {\
var ref = $('#explorerTree').jstree(true);\
var children = $(\"#explorerTree\").jstree(\"get_children_dom\",nodeId);\
for(var i=0;i<children.length;i++)\
{\
ref.delete_node(children[i].id);\
}\
\
}\
\
function refreshNode(nodeId) {\
\
var ref = $('#explorerTree').jstree(true);\
\
var node = ref.get_node(nodeId);\
\
getData(\"/explorer?path=\" + node.data.path, function(data) {\
/* We now have data! */\
\
deleteChildrenNodes(nodeId);\
addFileDirectory(nodeId, data);\
ref.open_node(nodeId);\
\
});\
\
\
}\
\
function getType(data) {\
var type = \"\";\
\
if(data.dir) {\
type = \"folder\";\
} else if ((/\\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|flac|FLAC)$/i).test(data.name)) {\
type = \"audio\";\
} else {\
type = \"file\";\
}\
\
return type;\
}\
\
\
function addFileDirectory(parent, data) {\
\
data.sort( fileNameSort );\
var ref = $('#explorerTree').jstree(true);\
\
for (var i=0; i<data.length; i++) {\
console.log(\"Create Node\");\
ref.create_node(parent, createChild(parent, data[i]));\
}\
} /* addFileDirectory */\
\
function buildFileSystemTree(path) {\
\
$('#explorerTree').jstree({\
\"core\" : {\
\"check_callback\" : true,\
'force_text' : true,\
\"themes\" : { \"stripes\" : true },\
'data' : { text: '/',\
state: {\
opened: true\
},\
type: 'folder',\
children: [],\
data: {\
path: '/',\
directory: true\
}}\
},\
'types': {\
'folder': {\
'icon': \"fa fa-folder\"\
},\
'file': {\
'icon': \"fa fa-file\"\
},\
'audio': {\
'icon': \"fa fa-file-audio\"\
},\
'default': {\
'icon': \"fa fa-folder\"\
}\
},\
plugins: [\"contextmenu\", \"themes\", \"types\"],\
contextmenu: {\
items: function(nodeId) {\
var ref = $('#explorerTree').jstree(true);\
var node = ref.get_node(nodeId);\
var items = {};\
\
\
if (node.data.directory) {\
items.createDir = {\
label: \"Neuer Ordner\",\
action: function(x) {\
var childNode = ref.create_node(nodeId, {text: \"Neuer Ordner\", type: \"folder\"});\
if(childNode) {\
ref.edit(childNode, null, function(childNode, status){\
putData(\"/explorer?path=\" + node.data.path + \"/\" + childNode.text);\
refreshNode(nodeId);\
});\
}\
}\
}\
}\
\
/* Play */\
items.play = {\
label: \"Abspielen\",\
action: function(x) {\
var playMode = node.data.directory?\"5\":\"1\";\
postData(\"/exploreraudio?path=\" + node.data.path + \"&playmode=\" + playMode);\
}\
}\
\
/* Refresh */\
items.refresh = {\
label: \"Aktualisieren\",\
action: function(x) {\
refreshNode(nodeId);\
}\
}\
\
/* Delete */\
items.delete = {\
label: \"Loeschen\",\
action: function(x) {\
handleDeleteData(nodeId);\
refreshNode(ref.get_parent(nodeId));\
}\
}\
\
/* Rename */\
items.rename = {\
label: \"Umbenennen\",\
action: function(x) {\
var srcPath = node.data.path;\
ref.edit(nodeId, null, function(node, status){\
node.data.path = node.data.path.substring(0,node.data.path.lastIndexOf(\"/\")+1) + node.text;\
patchData(\"/explorer?srcpath=\" + srcPath + \"&dstpath=\" + node.data.path);\
refreshNode(ref.get_parent(nodeId));\
});\
}\
}\
\
return items;\
}\
}\
});\
\
if (path.length == 0) {\
return;\
}\
getData(\"/explorer?path=/\", function(data) {\
/* We now have data! */\
$('#explorerTree').jstree(true).settings.core.data.children = [];\
\
data.sort( fileNameSort );\
\
\
for (var i=0; i<data.length; i++) {\
var newChild = {\
text: data[i].name,\
type: getType(data[i]),\
data: {\
path: \"/\" + data[i].name,\
directory: data[i].dir\
},\
children: []\
}\
$('#explorerTree').jstree(true).settings.core.data.children.push(newChild);\
}\
\
$(\"#explorerTree\").jstree(true).refresh();\
\
\
});\
} /* buildFileSystemTree */\
\
/* File Explorer functions end */\
function renderFileTree() {\
\
var filesURI = \"/files\";\
@ -715,6 +1124,7 @@ static const char management_HTML[] PROGMEM = "<!DOCTYPE html>\
$(document).ready(function () {\
connect();\
renderFileTree();\
buildFileSystemTree(\"/\");\
\
console.log(parseInt(document.getElementById('warningLowVoltage').value));\
$(function () {\

8
src/main.cpp

@ -1456,7 +1456,7 @@ void playAudio(void *parameter) {
if(currentRfidTagId != NULL){
strncpy(playProperties.playRfidTag, currentRfidTagId, sizeof(playProperties.playRfidTag) / sizeof(playProperties.playRfidTag[0]));
}
}
if (playProperties.trackFinished) {
playProperties.trackFinished = false;
@ -3596,13 +3596,13 @@ void webserverStart(void) {
wServer.addHandler(&events);
wServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(FSystem, "/index.html");
request->send(FSystem, "/management.html", String(), false, templateProcessor);
});
wServer.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", backupRecoveryWebsite);
}, handleUpload);
wServer.on("/restart", HTTP_GET, [] (AsyncWebServerRequest *request) {
request->send_P(200, "text/html", restartWebsite);
Serial.flush();
@ -3837,7 +3837,7 @@ void explorerHandleDeleteRequest(AsyncWebServerRequest *request) {
}
}
} else {
snprintf(logBuf, serialLoglength, "DELETE: Path %s does not exitst", asciiFilePath);
snprintf(logBuf, serialLoglength, "DELETE: Path %s does not exist", asciiFilePath);
loggerNl(logBuf, LOGLEVEL_ERROR);
}
} else {

Loading…
Cancel
Save