more file manager progress
This commit is contained in:
@@ -9,9 +9,32 @@ function FileManager(windowElement) {
|
||||
this.breadcrumbs = this.navBar.querySelector("#breadcrumbs");
|
||||
this.btnReload = this.navBar.querySelector("#btn_reload");
|
||||
this.inputSearch = this.navBar.querySelector("#input_search");
|
||||
this.directorySorters = this.window.querySelector("#directory_sorters");
|
||||
this.directoryArea = this.window.querySelector("#directory_area");
|
||||
this.directoryFooter = this.window.querySelector("#directory_footer");
|
||||
|
||||
// Sorters
|
||||
this.currentSortField = "";
|
||||
this.currentSortAscending = true;
|
||||
|
||||
this.btnSortName = document.createElement("div");
|
||||
this.btnSortName.innerText = "Name";
|
||||
this.btnSortName.addEventListener("click", () => { this.sortBy("name"); });
|
||||
this.directorySorters.appendChild(this.btnSortName);
|
||||
|
||||
this.btnSortType = document.createElement("div");
|
||||
this.btnSortType.innerText = "Type";
|
||||
this.btnSortType.addEventListener("click", () => { this.sortBy("type"); });
|
||||
this.directorySorters.appendChild(this.btnSortType);
|
||||
|
||||
this.btnSortSize = document.createElement("div");
|
||||
this.btnSortSize.innerText = "Size";
|
||||
this.btnSortSize.addEventListener("click", () => { this.sortBy("size"); });
|
||||
this.directorySorters.appendChild(this.btnSortSize);
|
||||
|
||||
// Buttons
|
||||
this.btnReload.addEventListener("click", () => { this.getUserFiles(); })
|
||||
|
||||
this.dirContainer = document.createElement("div");
|
||||
this.directoryArea.appendChild(this.dirContainer);
|
||||
|
||||
@@ -22,12 +45,27 @@ function FileManager(windowElement) {
|
||||
this.renderVisibleFiles(this.visibleFiles, false);
|
||||
})
|
||||
|
||||
// type: {icon, name, href, type, size}
|
||||
this.allFiles = [];
|
||||
this.visibleFiles = [];
|
||||
|
||||
this.lastScrollTop = 0;
|
||||
}
|
||||
|
||||
FileManager.prototype.setSpinner = function() {
|
||||
this.window.appendChild(document.getElementById("tpl_spinner").content.cloneNode(true));
|
||||
}
|
||||
FileManager.prototype.delSpinner = function() {
|
||||
for (let i in this.window.children) {
|
||||
if (
|
||||
typeof(this.window.children[i].classList) === "object" &&
|
||||
this.window.children[i].classList.contains("spinner")
|
||||
) {
|
||||
this.window.children[i].remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileManager.prototype.search = function(term) {
|
||||
if (term === "") {
|
||||
this.visibleFiles = this.allFiles;
|
||||
@@ -51,28 +89,36 @@ FileManager.prototype.getDirectory = function(path) {
|
||||
}
|
||||
|
||||
FileManager.prototype.getUserFiles = function() {
|
||||
this.setSpinner();
|
||||
|
||||
let getAll = (page) => {
|
||||
fetch(apiEndpoint+"/user/files?page="+page+"&limit=10000").then(resp => {
|
||||
if (!resp.ok) {Promise.reject("yo");}
|
||||
return resp.json();
|
||||
}).then(resp => {
|
||||
if (page === 0) {
|
||||
this.allFiles = resp.files;
|
||||
} else {
|
||||
this.allFiles = this.allFiles.concat(resp.files);
|
||||
for (let i in resp.files) {
|
||||
this.allFiles.push({
|
||||
icon: apiEndpoint+"/file/"+resp.files[i].id+"/thumbnail?width=32&height=32",
|
||||
name: resp.files[i].name,
|
||||
href: "/u/"+resp.files[i].id,
|
||||
type: resp.files[i].mime_type,
|
||||
size: resp.files[i].size
|
||||
})
|
||||
}
|
||||
|
||||
this.allFiles.sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
this.visibleFiles = this.allFiles;
|
||||
|
||||
this.renderVisibleFiles(this.visibleFiles, true);
|
||||
this.currentSortField = "";
|
||||
this.sortBy("name");
|
||||
|
||||
if (resp.files.length === 10000) {
|
||||
getAll(page+1);
|
||||
} else {
|
||||
// Less than 10000 results means we're done loading, we can
|
||||
// remove the loading spinner
|
||||
this.delSpinner();
|
||||
}
|
||||
}).catch((err) => {
|
||||
this.delSpinner();
|
||||
console.log("Req failed:" + err);
|
||||
})
|
||||
}
|
||||
@@ -80,9 +126,77 @@ FileManager.prototype.getUserFiles = function() {
|
||||
getAll(0);
|
||||
}
|
||||
|
||||
FileManager.prototype.getUserLists = function() {
|
||||
this.setSpinner();
|
||||
|
||||
let getAll = (page) => {
|
||||
fetch(apiEndpoint+"/user/lists?page="+page+"&limit=10000").then(resp => {
|
||||
if (!resp.ok) {Promise.reject("yo");}
|
||||
return resp.json();
|
||||
}).then(resp => {
|
||||
for (let i in resp.lists) {
|
||||
this.allFiles.push({
|
||||
icon: apiEndpoint+"/list/"+resp.lists[i].id+"/thumbnail?width=32&height=32",
|
||||
name: resp.lists[i].title,
|
||||
href: "/l/"+resp.lists[i].id,
|
||||
type: "list",
|
||||
size: 0
|
||||
})
|
||||
}
|
||||
|
||||
this.visibleFiles = this.allFiles;
|
||||
this.currentSortField = "";
|
||||
this.sortBy("name");
|
||||
|
||||
if (resp.lists.length === 10000) {
|
||||
getAll(page+1);
|
||||
} else {
|
||||
// Less than 10000 results means we're done loading, we can
|
||||
// remove the loading spinner
|
||||
this.delSpinner();
|
||||
}
|
||||
}).catch((err) => {
|
||||
this.delSpinner();
|
||||
console.log("Req failed:" + err);
|
||||
})
|
||||
}
|
||||
|
||||
getAll(0);
|
||||
}
|
||||
|
||||
FileManager.prototype.sortBy = function(field) {
|
||||
if (this.currentSortField !== field) {
|
||||
this.currentSortAscending = true;
|
||||
this.currentSortField = field;
|
||||
} else if (this.currentSortField === field) {
|
||||
this.currentSortAscending = !this.currentSortAscending;
|
||||
}
|
||||
|
||||
this.visibleFiles.sort((a, b) => {
|
||||
if (this.currentSortAscending) {
|
||||
return a[field].localeCompare(b[field]);
|
||||
} else {
|
||||
return b[field].localeCompare(a[field]);
|
||||
}
|
||||
});
|
||||
this.renderVisibleFiles(this.visibleFiles, true);
|
||||
}
|
||||
|
||||
FileManager.prototype.renderVisibleFiles = function(files, freshStart) {
|
||||
let scrollDown = this.lastScrollTop <= this.directoryArea.scrollTop;
|
||||
this.lastScrollTop = this.directoryArea.scrollTop;
|
||||
|
||||
let fileMargin = 4;
|
||||
let fileHeight = 32 + fileMargin;
|
||||
let totalHeight = (files.length * fileHeight);
|
||||
let viewportHeight = this.directoryArea.clientHeight;
|
||||
|
||||
if (freshStart) {
|
||||
this.dirContainer.innerHTML = "";
|
||||
this.dirContainer.style.height = totalHeight+"px";
|
||||
this.dirContainer.scrollTop = 0;
|
||||
this.lastScrollTop = 0;
|
||||
scrollDown = true;
|
||||
|
||||
let totalSize = 0;
|
||||
for (let i in files) {
|
||||
@@ -95,25 +209,15 @@ FileManager.prototype.renderVisibleFiles = function(files, freshStart) {
|
||||
+formatDataVolume(totalSize, 4);
|
||||
}
|
||||
|
||||
let scrollDown = this.lastScrollTop <= this.directoryArea.scrollTop;
|
||||
this.lastScrollTop = this.directoryArea.scrollTop;
|
||||
|
||||
let fileHeight = 32;
|
||||
let totalHeight = (files.length * fileHeight)+38;
|
||||
let viewportHeight = this.directoryArea.clientHeight;
|
||||
let paddingTop = this.lastScrollTop - this.lastScrollTop%fileHeight;
|
||||
if (paddingTop < 0) { paddingTop = 0;}
|
||||
let paddingBottom = totalHeight - paddingTop - viewportHeight - this.lastScrollTop%fileHeight;
|
||||
if (paddingBottom < 0) {paddingBottom = 0;}
|
||||
let start = Math.floor(paddingTop/fileHeight) - 5;
|
||||
if (start < 0) { start = 0; }
|
||||
|
||||
// Pad the items out which we're not going to show
|
||||
this.dirContainer.style.marginTop = paddingTop+"px";
|
||||
this.dirContainer.style.marginBottom = paddingBottom+"px";
|
||||
|
||||
let start = Math.floor(paddingTop/fileHeight);
|
||||
let end = Math.ceil((paddingTop+viewportHeight)/fileHeight);
|
||||
let end = Math.ceil((paddingTop+viewportHeight)/fileHeight) + 5;
|
||||
if (end > files.length) { end = files.length-1; }
|
||||
|
||||
this.dirContainer.style.paddingTop = (start*fileHeight)+"px";
|
||||
|
||||
// First remove the elements which are out of bounds
|
||||
let firstEl;
|
||||
let firstIdx = -1;
|
||||
@@ -142,13 +246,13 @@ FileManager.prototype.renderVisibleFiles = function(files, freshStart) {
|
||||
let makeButton = (i, file) => {
|
||||
let el = document.createElement("a");
|
||||
el.classList = "node";
|
||||
el.href = "/u/"+file.id;
|
||||
el.href = file.href;
|
||||
el.target = "_blank";
|
||||
el.title = file.name;
|
||||
el.setAttribute("fileindex", i);
|
||||
|
||||
let thumb = document.createElement("img");
|
||||
thumb.src = apiEndpoint+"/file/"+file.id+"/thumbnail?width=32&height=32";
|
||||
thumb.src = file.icon;
|
||||
|
||||
let label = document.createElement("span");
|
||||
label.innerText = file.name;
|
||||
|
@@ -9,18 +9,31 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#button_toggle_navigation {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.file_manager {
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
background-color: var(--layer_1_color);
|
||||
box-shadow: #000000 8px 8px 50px 5px;
|
||||
left:2%;
|
||||
top:2%;
|
||||
right:2%;
|
||||
bottom:2%;
|
||||
left:3%;
|
||||
top:3%;
|
||||
right:3%;
|
||||
bottom:3%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@media (max-width: 800px) {
|
||||
.file_manager {
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.file_manager > .nav_bar {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
@@ -30,11 +43,28 @@
|
||||
.file_manager > .nav_bar > .breadcrumbs {
|
||||
flex-grow: .8;
|
||||
flex-shrink: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.file_manager > .nav_bar > .input_search {
|
||||
flex-grow: .2;
|
||||
flex-shrink: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.file_manager > .directory_sorters {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
}
|
||||
.file_manager > .directory_sorters > div {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 1;
|
||||
display: inline-block;
|
||||
margin: 4px 12px;
|
||||
border-bottom: 1px solid var(--input_color);
|
||||
}
|
||||
|
||||
.file_manager > .directory_area {
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
@@ -45,6 +75,9 @@
|
||||
text-align: left;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.file_manager > .directory_area > div {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.file_manager > .status_bar {
|
||||
flex-shrink: 0;
|
||||
text-align: left;
|
||||
@@ -52,9 +85,10 @@
|
||||
|
||||
.node {
|
||||
position: relative;
|
||||
height: 24px;
|
||||
height: 32px;
|
||||
overflow: hidden;
|
||||
margin: 8px;
|
||||
border-radius: 4px;
|
||||
margin: 6px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
color: var(--text_color);
|
||||
@@ -69,13 +103,14 @@
|
||||
}
|
||||
|
||||
.spinner {
|
||||
position: relative;
|
||||
position: absolute;
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
@@ -90,7 +125,7 @@
|
||||
<div id="page_body" class="page_body">
|
||||
<div id="file_manager" class="file_manager">
|
||||
<div id="nav_bar" class="nav_bar highlight_light">
|
||||
<button id="btn_menu">☰</button>
|
||||
<button id="btn_menu" onclick="toggleMenu();">☰</button>
|
||||
<div class="spacer"></div>
|
||||
<button id="btn_back" >⇐</button id="btn_forward">
|
||||
<button id="btn_up" >⇑</button id="btn_forward">
|
||||
@@ -104,6 +139,7 @@
|
||||
<div class="spacer"></div>
|
||||
<button id="btn_reload">↻</button>
|
||||
</div>
|
||||
<div id="directory_sorters" class="directory_sorters"></div>
|
||||
<div id="directory_area" class="directory_area"></div>
|
||||
<div id="directory_footer" class="status_bar highlight_light"></div>
|
||||
</div>
|
||||
@@ -115,8 +151,9 @@
|
||||
{{template `util.js`}}
|
||||
{{template `FileManager.js`}}
|
||||
|
||||
let fm = null;
|
||||
window.addEventListener("load", () => {
|
||||
let fm = new FileManager(document.getElementById("file_manager"));
|
||||
fm = new FileManager(document.getElementById("file_manager"));
|
||||
fm.getUserFiles();
|
||||
});
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user