105 lines
2.9 KiB
JavaScript
105 lines
2.9 KiB
JavaScript
const fileList = document.getElementById('file-list');
|
|
const searchBox = document.getElementById('search');
|
|
const breadcrumb = document.getElementById('breadcrumb');
|
|
let currentPath = '';
|
|
|
|
function pathJoin(...parts) {
|
|
return parts.filter(Boolean).join('/');
|
|
}
|
|
|
|
function fetchDirectory(path = '') {
|
|
fetch(`/api/list?path=${encodeURIComponent(path)}`)
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
currentPath = path;
|
|
renderBreadcrumb(path);
|
|
renderList(data);
|
|
});
|
|
}
|
|
|
|
function renderBreadcrumb(path) {
|
|
breadcrumb.innerHTML = '';
|
|
const parts = path.split('/').filter(Boolean);
|
|
let accum = '';
|
|
|
|
const root = document.createElement('span');
|
|
root.textContent = 'Home';
|
|
root.onclick = () => fetchDirectory('');
|
|
breadcrumb.appendChild(root);
|
|
|
|
parts.forEach((part, index) => {
|
|
accum = pathJoin(accum, part);
|
|
const sep = document.createElement('span');
|
|
sep.className = 'separator';
|
|
sep.textContent = ' / ';
|
|
breadcrumb.appendChild(sep);
|
|
|
|
const crumb = document.createElement('span');
|
|
crumb.textContent = part;
|
|
crumb.onclick = () => fetchDirectory(parts.slice(0, index + 1).join('/'));
|
|
breadcrumb.appendChild(crumb);
|
|
});
|
|
}
|
|
|
|
function renderList(items) {
|
|
fileList.innerHTML = '';
|
|
|
|
const folders = items.filter(i => i.isDirectory);
|
|
const files = items.filter(i => !i.isDirectory);
|
|
|
|
folders.forEach(item => {
|
|
const li = document.createElement('li');
|
|
li.className = 'folder';
|
|
li.textContent = `📁 ${item.name}`;
|
|
li.onclick = () => fetchDirectory(pathJoin(currentPath, item.name));
|
|
fileList.appendChild(li);
|
|
});
|
|
|
|
files.forEach(item => {
|
|
const li = document.createElement('li');
|
|
li.textContent = item.name;
|
|
|
|
const link = document.createElement('a');
|
|
link.href = `/api/download?path=${encodeURIComponent(pathJoin(currentPath, item.name))}`;
|
|
link.textContent = 'Download';
|
|
link.className = 'download-link';
|
|
link.onclick = e => e.stopPropagation();
|
|
|
|
li.appendChild(link);
|
|
fileList.appendChild(li);
|
|
});
|
|
}
|
|
|
|
function searchFiles(term) {
|
|
fetch(`/api/search?q=${encodeURIComponent(term)}`)
|
|
.then(res => res.json())
|
|
.then(results => {
|
|
breadcrumb.innerHTML = '';
|
|
fileList.innerHTML = '';
|
|
|
|
results.forEach(relPath => {
|
|
const li = document.createElement('li');
|
|
li.textContent = relPath;
|
|
|
|
const link = document.createElement('a');
|
|
link.href = `/api/download?path=${encodeURIComponent(relPath)}`;
|
|
link.textContent = 'Download';
|
|
link.className = 'download-link';
|
|
link.onclick = e => e.stopPropagation();
|
|
|
|
li.appendChild(link);
|
|
fileList.appendChild(li);
|
|
});
|
|
});
|
|
}
|
|
|
|
searchBox.addEventListener('input', e => {
|
|
const term = e.target.value.trim();
|
|
if (term.length === 0) {
|
|
fetchDirectory();
|
|
} else {
|
|
searchFiles(term);
|
|
}
|
|
});
|
|
|
|
fetchDirectory(); |