Updates galore. Improved folder structure, componentized, and notifications upon completion.
This commit is contained in:
parent
b48784e2ad
commit
7e0502ca40
33 changed files with 3565 additions and 728 deletions
111
static/js/modules/browser.js
Normal file
111
static/js/modules/browser.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* browser.js
|
||||
* ----------
|
||||
* Server-side directory browser modal.
|
||||
*
|
||||
* Fetches directory listings from /api/browse and renders them inside the
|
||||
* modal panel. The user navigates the server filesystem and selects a
|
||||
* directory to populate the scan path input.
|
||||
*
|
||||
* Exports
|
||||
* -------
|
||||
* initBrowser() — attach all event listeners; call once at startup
|
||||
*/
|
||||
|
||||
import { state, els, announce } from './state.js';
|
||||
import { esc } from './utils.js';
|
||||
|
||||
// ─── Internal helpers ─────────────────────────────────────────────────────────
|
||||
|
||||
async function loadBrowserPath(path) {
|
||||
els.browserList.innerHTML =
|
||||
'<p class="browser-loading" aria-live="polite">Loading…</p>';
|
||||
els.browserPath.textContent = path;
|
||||
|
||||
try {
|
||||
const resp = await fetch(`/api/browse?path=${encodeURIComponent(path)}`);
|
||||
if (!resp.ok) throw new Error((await resp.json()).error || 'Error loading directory');
|
||||
const data = await resp.json();
|
||||
|
||||
state.browserPath = data.current;
|
||||
els.browserPath.textContent = data.current;
|
||||
|
||||
let html = '';
|
||||
|
||||
if (data.parent !== null) {
|
||||
html += `
|
||||
<button class="browser-item parent-dir" data-path="${esc(data.parent)}">
|
||||
<span class="item-icon" aria-hidden="true">↑</span>
|
||||
<span>.. (parent directory)</span>
|
||||
</button>`;
|
||||
}
|
||||
|
||||
for (const entry of data.entries) {
|
||||
if (!entry.is_dir) continue;
|
||||
html += `
|
||||
<button class="browser-item" data-path="${esc(entry.path)}"
|
||||
role="option" aria-label="Directory: ${esc(entry.name)}">
|
||||
<span class="item-icon" aria-hidden="true">📁</span>
|
||||
<span>${esc(entry.name)}</span>
|
||||
</button>`;
|
||||
}
|
||||
|
||||
if (!html) html = '<p class="browser-loading">No subdirectories found.</p>';
|
||||
els.browserList.innerHTML = html;
|
||||
|
||||
els.browserList.querySelectorAll('.browser-item').forEach(btn => {
|
||||
btn.addEventListener('click', () => loadBrowserPath(btn.dataset.path));
|
||||
btn.addEventListener('keydown', e => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
loadBrowserPath(btn.dataset.path);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
els.browserList.innerHTML =
|
||||
`<p class="browser-error" role="alert">Error: ${esc(err.message)}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
function openBrowser() {
|
||||
els.browserModal.hidden = false;
|
||||
document.body.style.overflow = 'hidden';
|
||||
loadBrowserPath(els.dirInput.value || '/');
|
||||
els.closeBrowser.focus();
|
||||
announce('Directory browser opened');
|
||||
}
|
||||
|
||||
function closeBrowser() {
|
||||
els.browserModal.hidden = true;
|
||||
document.body.style.overflow = '';
|
||||
els.browseBtn.focus();
|
||||
announce('Directory browser closed');
|
||||
}
|
||||
|
||||
// ─── Public init ─────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Attach all event listeners for the directory browser modal.
|
||||
* Call once during app initialisation.
|
||||
*/
|
||||
export function initBrowser() {
|
||||
els.browseBtn.addEventListener('click', openBrowser);
|
||||
els.closeBrowser.addEventListener('click', closeBrowser);
|
||||
els.browserCancel.addEventListener('click', closeBrowser);
|
||||
|
||||
els.browserModal.addEventListener('click', e => {
|
||||
if (e.target === els.browserModal) closeBrowser();
|
||||
});
|
||||
|
||||
els.browserSelect.addEventListener('click', () => {
|
||||
els.dirInput.value = state.browserPath;
|
||||
closeBrowser();
|
||||
announce(`Directory selected: ${state.browserPath}`);
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.key === 'Escape' && !els.browserModal.hidden) closeBrowser();
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue