diff --git a/package.json b/package.json
index 80e064db..8f1c3f44 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "meshcentral",
- "version": "0.1.8-d",
+ "version": "0.1.8-e",
"keywords": [
"Remote Management",
"Intel AMT",
diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars
index 25991091..4bb08011 100644
--- a/views/default-mobile.handlebars
+++ b/views/default-mobile.handlebars
@@ -29,9 +29,9 @@
.i4 {background:url(../images/icons50.png) -150px 0px;height:50px;width:50px;border:none;}
.i5 {background:url(../images/icons50.png) -200px 0px;height:50px;width:50px;border:none;}
.i6 {background:url(../images/icons50.png) -250px 0px; height:50px;width:50px; border:none; }
- .m0 {background:url(../images/images16.png) -32px 0px; height:16px;width:16px; border:none;float:left }
- .m1 {background:url(../images/images16.png) -16px 0px; height:16px;width:16px; border:none;float:left }
- .m2 {background:url(../images/images16.png) -96px 0px; height:16px;width:16px; border:none;float:left }
+ .m0 {background:url(../images/images16.png) -32px 0px; height:16px;width:16px; border:none;float:left }
+ .m1 {background:url(../images/images16.png) -16px 0px; height:16px;width:16px; border:none;float:left }
+ .m2 {background:url(../images/images16.png) -96px 0px; height:16px;width:16px; border:none;float:left }
.m3 {background:url(../images/images16.png) -112px 0px; height:16px;width:16px; border:none;float:left }
.gray {
@@ -167,6 +167,77 @@
+
+
+
+
+
+ ◀
+ |
+
+
+ |
+
+
+ My Files
+
+ |
+
+
+
+
@@ -409,7 +480,7 @@
// Fetch list of meshes, nodes, files
meshserver.send({ action: 'meshes' });
meshserver.send({ action: 'nodes' });
- //meshserver.send({ action: 'files' });
+ meshserver.send({ action: 'files' });
if (xxcurrentView < 2) { go(2); }
}
}
@@ -459,8 +530,8 @@
break;
}
case 'files': {
- //filetree = setupBackPointers(message.filetree);
- //updateFiles();
+ filetree = setupBackPointers(message.filetree);
+ updateFiles();
//d3updatefiles();
break;
}
@@ -700,6 +771,7 @@
QV('topMenu', false);
xxdialogMode = 0;
if ((select == 1) && (xxcurrentView != 3)) { goForward('account'); } // My Account
+ if ((select == 2) && (xxcurrentView != 5)) { goForward('files'); } // My Files
}
}
@@ -713,6 +785,7 @@
if (idtype == 'mesh') { gotoMesh(id); }
if (idtype == 'account') { go(3); }
if (idtype == 'devices') { go(2); }
+ if (idtype == 'files') { go(5); }
}
function updateFooterMenu(options) {
@@ -879,6 +952,213 @@
function server_showVersionDlgUpdate() { QE('idx_dlgOkButton', Q('d2updateCheck').checked); }
function server_showVersionDlgEx() { meshserver.send({ action: 'serverupdate' }); }
+ //
+ // MY FILES
+ //
+
+ var filetreelinkpath;
+ var filetreelocation = [];
+
+ function p5refreshFiles() { meshserver.send({ action: 'files' }); }
+
+ function updateFiles() {
+ QV('MainMenuMyFiles', ((features & 8) == 0));
+ if ((features & 8) != 0) return; // If running on a server without files, exit now.
+ var html1 = '', html2 = '', displayPath = 'Root', fullPath = 'Root', publicPath, filetreex = filetree, folderdepth = 1;
+
+ // Navigate to path location, build the paths at the same time
+ var filetreelocation2 = [], oldlinkpath = filetreelinkpath, checkedBoxes = [], checkboxes = document.getElementsByName('fc');
+ for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkedBoxes.push(checkboxes[i].value) }; } // Save all existing checked boxes
+
+ filetreelinkpath = '';
+ for (var i in filetreelocation) {
+ if ((filetreex.f != null) && (filetreex.f[filetreelocation[i]] != null)) {
+ filetreelocation2.push(filetreelocation[i]);
+ fullPath += ' / ' + filetreelocation[i];
+ if ((folderdepth == 1)) {
+ var sp = filetreelocation[i].split('/');
+ publicPath = window.location + sp[0] + 'files/' + sp[2];
+ //if (filetreelocation[i] === userinfo._id) { filetreelinkpath += 'self'; } else { filetreelinkpath += (sp[0] + '/' + sp[2]); }
+ filetreelinkpath += filetreelocation[i];
+ } else {
+ if (filetreelinkpath != '') { filetreelinkpath += '/' + filetreelocation[i]; if (folderdepth > 2) { publicPath += '/' + filetreelocation[i]; } }
+ }
+ filetreex = filetreex.f[filetreelocation[i]];
+ displayPath += ' / ' + (filetreex.n != null?filetreex.n:filetreelocation[i]) + '';
+ folderdepth++;
+ } else {
+ break;
+ }
+ }
+ filetreelocation = filetreelocation2; // In case we could not go down the full path, we set the new path location here.
+ var publicfolder = fullPath.toLowerCase().startsWith("root / " + userinfo._id + " / public");
+
+ // Sort the files
+ var filetreexx = p5sort_files(filetreex.f);
+
+ // Display all files and folders at this location
+ for (var i in filetreexx) {
+ // Figure out the name and shortname
+ var f = filetreexx[i], name = f.n, shortname;
+ shortname = name;
+ if (name.length > 40) { shortname = '' + EscapeHtml(name.substring(0, 40)) + "..."; } else { shortname = EscapeHtml(name); }
+ name = EscapeHtml(name);
+
+ // Figure out the date
+ //var fdatestr = '';
+ //if (f.d != null) { var fdate = new Date(f.d), fdatestr = (fdate.getMonth() + 1) + "/" + (fdate.getDate()) + "/" + fdate.getFullYear() + " " + fdate.toLocaleTimeString() + " "; }
+
+ // Figure out the size
+ var fsize = '';
+ if (f.s != null) { fsize = getFileSizeStr(f.s); }
+
+ var h = '';
+ if (f.t < 3) {
+ var right = (f.t == 1)?p5getQuotabar(f):'', title = '';
+ h = "";
+ } else {
+ var link = shortname;
+ var publiclink = '';
+ if (publicfolder) { publiclink = ' (Link)'; }
+ if (f.s > 0) { link = "" + shortname + "" + publiclink; }
+ h = "";
+ }
+
+ if (f.t < 3) { html1 += h; } else { html2 += h; }
+ }
+
+ //if (f.parent == null) { }
+ //QH('p5rightOfButtons', p5getQuotabar(filetreex));
+
+ QH('p5files', html1 + html2);
+ QH('p5currentpath', displayPath);
+ QE('p5FolderUp', filetreelocation.length != 0);
+ QV('p5PublicShare', publicfolder);
+
+ // Re-check all boxes if needed
+ if (oldlinkpath == filetreelinkpath) {
+ checkboxes = document.getElementsByName('fc');
+ for (var i = 0; i < checkboxes.length; i++) {
+ checkboxes[i].checked = (checkedBoxes.indexOf(checkboxes[i].value) >= 0);
+ }
+ }
+
+ p5setActions();
+ }
+
+ function p5getQuotabar(f) {
+ while (f.t > 1) { f = f.parent; }
+ if ((f.t != 1) || (f.maxbytes == null)) return '';
+ var tf = Math.floor(f.s / 1024), tq = Math.floor((f.maxbytes - f.s) / 1024);
+ return ' 1?'s':'') + ". " + (Math.floor(f.maxbytes / 1024)) + 'k maxinum">' + ((tq < 0)?('Storage limit exceed'):(tq + 'k remaining')) + ' ';
+ }
+
+ function p5showPublicLink(u) { setDialogMode(2, "Public Link", 1, null, ''); }
+
+ var sortorder;
+ function p5sort_filename(a, b) { if (a.ln > b.ln) return (1 * sortorder); if (a.ln < b.ln) return (-1 * sortorder); return 0; }
+ function p5sort_timestamp(a, b) { if (a.d > b.d) return (1 * sortorder); if (a.d < b.d) return (-1 * sortorder); return 0; }
+ function p5sort_bysize(a, b) { if (a.s == b.s) return p5sort_filename(a, b); return (((a.s - b.s)) * sortorder); }
+
+ function p5sort_files(files) {
+ var r = [], sortselection = Q('p5sortdropdown').value;
+ for (var i in files) { files[i].nx = i; if (files[i].n == null) { files[i].n = i; } files[i].ln = files[i].n.toLowerCase(); r.push(files[i]); }
+ sortorder = 1;
+ if (sortselection > 3) { sortorder = -1; sortselection -= 3; }
+ if (sortselection == 1) { r.sort(p5sort_filename); }
+ else if (sortselection == 2) { r.sort(p5sort_bysize); }
+ else if (sortselection == 3) { r.sort(p5sort_timestamp); }
+ return r;
+ }
+
+ function p5setActions() {
+ var cc = getFileSelCount(), tc = getFileCount(), sfc = getFileSelCount(false); // In order: number of entires selected, number of total entries, number of selected entires that are files (not folders)
+ QE('p5DeleteFileButton', (cc > 0) && (filetreelocation.length > 0));
+ QE('p5NewFolderButton', filetreelocation.length > 0);
+ QE('p5UploadButton', filetreelocation.length > 0);
+ QE('p5RenameFileButton', (cc == 1) && (filetreelocation.length > 0));
+ QE('p5SelectAllButton', tc > 0);
+ Q('p5SelectAllButton').value = (cc > 0 ? 'Select None' : 'Select All');
+ QE('p5CutButton', (sfc > 0) && (cc == sfc));
+ QE('p5CopyButton', (sfc > 0) && (cc == sfc));
+ QE('p5PasteButton', (p5clipboard != null) && (p5clipboard.length > 0));
+ }
+
+ function getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == "3"))) cc++; } return cc; }
+ function getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fc'); return checkboxes.length; }
+ function p5selectallfile() { var nv = (getFileSelCount() == 0), checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p5setActions(); }
+ function setupBackPointers(x) { if (x.f != null) { var fs = 0, fc = 0; for (var i in x.f) { setupBackPointers(x.f[i]); x.f[i].parent = x; if (x.f[i].s) { fs += x.f[i].s; } if (x.f[i].c) { fc += x.f[i].c; } if (x.f[i].t == 3) { fc++; } } x.s = fs; x.c = fc; } return x; }
+ function getFileSizeStr(size) { if (size == 1) return "1 byte"; return "" + size + " bytes"; }
+ function p5folderup(x) { if (x == null) { filetreelocation.pop(); } else { while (filetreelocation.length > x) { filetreelocation.pop(); } } updateFiles(); }
+ function p5folderset(x) { filetreelocation.push(decodeURIComponent(x)); updateFiles(); }
+ function p5createfolder() { setDialogMode(2, "New Folder", 3, p5createfolderEx, ''); focusTextBox('p5renameinput'); p5fileNameCheck(); }
+ function p5createfolderEx() { meshserver.send({ action: 'fileoperation', fileop: 'createfolder', path: filetreelocation, newfolder: Q('p5renameinput').value}); }
+ function p5deletefile() { var cc = getFileSelCount(); setDialogMode(2, "Delete", 3, p5deletefileEx, (cc > 1)?('Delete ' + cc + ' selected items?'):('Delete selected item?')); }
+ function p5deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(checkboxes[i].value); } } meshserver.send({ action: 'fileoperation', fileop: 'delete', path: filetreelocation, delfiles: delfiles}); }
+ function p5renamefile() { var renamefile, checkboxes = document.getElementsByName('fc'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = checkboxes[i].value; } } setDialogMode(2, "Rename", 3, p5renamefileEx, '', { action: 'fileoperation', fileop: 'rename', path: filetreelocation, oldname: renamefile}); focusTextBox('p5renameinput'); p5fileNameCheck(); }
+ function p5renamefileEx(b, t) { t.newname = Q('p5renameinput').value; meshserver.send(t); }
+ function p5fileNameCheck(e) { var x = isFilenameValid(Q('p5renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e.keyCode == 13)) { dialogclose(1); } }
+ var isFilenameValid = (function(){ var x1=/^[^\\/:\*\?"<>\|]+$/, x2=/^\./, x3=/^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname){ return x1.test(fname)&&!x2.test(fname)&&!x3.test(fname)&&(fname[0] != '.'); } })();
+ function p5uploadFile() { setDialogMode(2, "Upload File", 3, p5uploadFileEx, ''); updateUploadDialogOk('p5uploadinput'); }
+ function p5uploadFileEx() { Q('p5loginSubmit').click(); }
+ function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q(x).value != ''); }
+
+ var p5clipboard = null, p5clipboardFolder = null, p5clipboardCut = 0;
+ function p5copyFile(cut) { var checkboxes = document.getElementsByName('fc'); p5clipboard = []; p5clipboardCut = cut, p5clipboardFolder = Clone(filetreelocation); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == "3")) { p5clipboard.push(checkboxes[i].value); } } p5updateClipview(); }
+ function p5pasteFile() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = 'Confim ' + (p5clipboardCut == 0?'copy':'move') + ' of ' + p5clipboard.length + ' entrie' + ((p5clipboard.length > 1)?'s':'') + ' to this location?' } setDialogMode(2, "Paste", 3, p5pasteFileEx, x); }
+ function p5pasteFileEx() { meshserver.send({ action: 'fileoperation', fileop: (p5clipboardCut == 0?'copy':'move'), scpath: p5clipboardFolder, path: filetreelocation, names: p5clipboard }); p5folderup(999); if (p5clipboardCut == 1) { p5clipboard = null, p5clipboardFolder = null, p5clipboardCut = 0; p5updateClipview(); } }
+ function p5updateClipview() { var x = ''; if ((p5clipboard != null) && (p5clipboard.length > 0)) { x = 'Holding ' + p5clipboard.length + ' entrie' + ((p5clipboard.length > 1)?'s':'') + ' for ' + (p5clipboardCut == 0?'copy':'move') + ', Clear.' } QH('p5bottomstatus', x); p5setActions(); }
+ function p5clearClip() { p5clipboard = null; p5clipboardFolder = null; p5clipboardCut = 0; p5updateClipview(); }
+
+ function p5fileDragDrop(e) {
+ haltEvent(e);
+ QV('bigfail', false);
+ QV('bigok', false);
+ //QV('p5fileCatchAllInput', false);
+ if (e.dataTransfer == null || e.dataTransfer.files.length == 0 || filetreelocation.length == 0) return;
+ var names = [], sizes = [], types = [], datas = [], readercount = e.dataTransfer.files.length;
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
+ var reader = new FileReader(), file = e.dataTransfer.files[i];
+ names.push(file.name);
+ sizes.push(file.size);
+ types.push(file.type);
+ reader.onload = function(event) {
+ datas.push(event.target.result);
+ if (--readercount == 0) {
+ Q('p5fileDragName').value = names.join('*');
+ Q('p5fileDragSize').value = sizes.join('*');
+ Q('p5fileDragType').value = types.join('*');
+ Q('p5fileDragData').value = datas.join('*');
+ Q('p5fileDragLink').value = encodeURIComponent(filetreelinkpath);
+ Q('p5loginSubmit2').click();
+ }
+ }
+ reader.readAsDataURL(file);
+ }
+ }
+
+ var p5dragtimer = null;
+ function p5fileDragOver(e) {
+ haltEvent(e);
+ if (p5dragtimer != null) { clearTimeout(p5dragtimer); p5dragtimer = null; }
+ var ac = true; // TODO: Set to true if we can accept the file
+ if (filetreelocation.length == 0) { ac = false; }
+ QV('bigok', ac);
+ QV('bigfail', !ac);
+ //QV('p5fileCatchAllInput', ac);
+ }
+
+ function p5fileDragLeave(e) {
+ haltEvent(e);
+ if (e.target.id != "p5filetable") {
+ QV('bigfail', false);
+ QV('bigok', false);
+ //QV('p5fileCatchAllInput', false);
+ } else {
+ p5dragtimer = setTimeout("QV('bigfail',false);QV('bigok',false);p5dragtimer=null;", 200);
+ }
+ }
+
//
// MY DEVICES
//