All checks were successful
Notify chart dev on beta cut / notify-chart-dev (push) Successful in 5s
A new HTML tool — browse — that lists the contents of any directory.
Designed for ZDDC archives but no ZDDC-specific filtering; just a
straight folder browser with expand/collapse, sort, and name filter.
Modes (auto-detected at page load):
- Online: when served by zddc-server at a folder URL, queries
the same URL with Accept: application/json to load the listing
and renders it. Auto-served as the default at any directory
under ZDDC_ROOT without an index.html (replacing the previous
minimal-HTML stub from directory.go).
- Local: 'Select Directory' button uses FileSystemAccessAPI to
pick any folder on disk; works in Chromium-based browsers.
Features (Phase 1 — what's in this commit):
- Tree view with lazy-loaded folders (children fetched on first
expand).
- Sort by name / size / extension / date (column header click).
- Filter by name substring (toolbar input).
- File click opens in a new tab — for server-backed pages,
routes through zddc-server's normal handler so .archive
redirects + apps cascade overrides + ACL all apply.
Phase 2 deferred:
- ZIP files inline expansion (treat archive entries as virtual
children).
- File preview popup (reuse shared/preview-lib.js).
- Extension multi-select filter.
Wiring:
- browse/ added to top-level ./build's per-tool list, embed
block, versions.txt, and the lockstep release commit + tag set.
All seven tools (archive, transmittal, classifier, mdedit,
landing, form, browse) advance together on stable cuts.
- shared/build-lib.sh: browse added to ZDDC_RELEASE_TOOLS and
verify_channel_links's per-tool loop.
- zddc/internal/apps/embed.go: //go:embed browse.html +
EmbeddedBytes("browse") case.
- zddc/internal/apps/availability.go: browse available at every
directory (same as archive).
- zddc/internal/apps/handler.go: MatchAppHTML routes
/<dir>/browse.html → 'browse'.
- zddc/internal/handler/directory.go: when a directory request
arrives with Accept: text/html and no index.html exists,
serve the embedded browse.html bytes (with a JSON-fallback
if the embedded slot is empty during bootstrap).
70 lines
1.2 KiB
CSS
70 lines
1.2 KiB
CSS
/* browse-specific layout on top of shared/base.css */
|
|
|
|
html, body {
|
|
height: 100%;
|
|
margin: 0;
|
|
padding: 0;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font-family: var(--font);
|
|
}
|
|
|
|
body {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
#appMain {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
}
|
|
|
|
/* Empty / first-paint state */
|
|
.empty-state {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 2rem;
|
|
}
|
|
|
|
.empty-state__inner {
|
|
max-width: 640px;
|
|
color: var(--text-muted);
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.empty-state__inner h2 {
|
|
color: var(--text);
|
|
margin: 0 0 1rem 0;
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
.empty-state__inner ul {
|
|
margin: 1rem 0;
|
|
padding-left: 1.5rem;
|
|
}
|
|
|
|
.empty-state__inner li {
|
|
margin: 0.4rem 0;
|
|
}
|
|
|
|
.hidden { display: none !important; }
|
|
|
|
/* Status bar — shows transient errors/info */
|
|
.status-bar {
|
|
padding: 0.4rem 1rem;
|
|
background: var(--bg-secondary);
|
|
border-top: 1px solid var(--border);
|
|
font-size: 0.85rem;
|
|
color: var(--text-muted);
|
|
min-height: 1.6rem;
|
|
line-height: 1.6rem;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.status-bar--error { color: #b00020; }
|
|
.status-bar--info { color: var(--primary); }
|