Add Resource Loader SPA and JS test harness
All checks were successful
Build Org Website / build (push) Successful in 38s
All checks were successful
Build Org Website / build (push) Successful in 38s
This commit is contained in:
175
rl/index.org
Normal file
175
rl/index.org
Normal file
@@ -0,0 +1,175 @@
|
||||
#+TITLE: Resource Loader
|
||||
#+OPTIONS: num:nil title:nil toc:nil
|
||||
#+NO_SIDENOTES: t
|
||||
#+DATE: <2026-08-19 Wed>
|
||||
|
||||
#+BEGIN_EXPORT html
|
||||
<main class="rl-app" id="resource-loader" aria-labelledby="rl-title">
|
||||
<header class="rl-hero">
|
||||
<div class="rl-hero__copy">
|
||||
<p class="rl-eyebrow">Private browser library</p>
|
||||
<h1 id="rl-title">Resource Loader</h1>
|
||||
<p>Keep books, papers, articles, and videos together. Your vaults stay in this browser.</p>
|
||||
</div>
|
||||
<div class="rl-hero__actions">
|
||||
<label class="rl-vault-picker" for="rl-vault-select">
|
||||
<span>Current vault</span>
|
||||
<select id="rl-vault-select" aria-label="Current vault"></select>
|
||||
</label>
|
||||
<button type="button" class="rl-icon-button" id="rl-manage-vaults">Manage vaults</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="rl-summary" aria-label="Vault summary">
|
||||
<div><span id="rl-stat-total">0</span><small>resources</small></div>
|
||||
<div><span id="rl-stat-active">0</span><small>active</small></div>
|
||||
<div><span id="rl-stat-backlog">0</span><small>backlog</small></div>
|
||||
<div><span id="rl-stat-completed">0</span><small>completed</small></div>
|
||||
<div class="rl-summary__privacy"><span aria-hidden="true">●</span><small>stored locally</small></div>
|
||||
</section>
|
||||
|
||||
<section class="rl-command-bar" aria-label="Resource actions">
|
||||
<button type="button" class="rl-primary" id="rl-add-resource">Add resource</button>
|
||||
<button type="button" id="rl-import-pdf">Import PDF</button>
|
||||
<button type="button" id="rl-import-json">Import JSON</button>
|
||||
<button type="button" id="rl-export-json">Export JSON</button>
|
||||
<button type="button" id="rl-storage-button">Storage</button>
|
||||
<input class="visually-hidden" id="rl-pdf-input" type="file" accept="application/pdf,.pdf" />
|
||||
<input class="visually-hidden" id="rl-json-input" type="file" accept="application/json,.json" />
|
||||
</section>
|
||||
|
||||
<div class="rl-workspace">
|
||||
<aside class="rl-sidebar" aria-label="Library folders">
|
||||
<div class="rl-sidebar__head">
|
||||
<div>
|
||||
<p class="rl-eyebrow">Browse</p>
|
||||
<h2>Folders</h2>
|
||||
</div>
|
||||
<button type="button" class="rl-icon-button" id="rl-add-folder" aria-label="Add folder">+ Add</button>
|
||||
</div>
|
||||
<nav class="rl-folder-list" id="rl-folder-list"></nav>
|
||||
</aside>
|
||||
|
||||
<section class="rl-library" aria-labelledby="rl-library-title">
|
||||
<header class="rl-library__toolbar">
|
||||
<div>
|
||||
<p class="rl-eyebrow" id="rl-context-label">All resources</p>
|
||||
<h2 id="rl-library-title">Library</h2>
|
||||
</div>
|
||||
<div class="rl-view-toggle" aria-label="Display mode">
|
||||
<button type="button" id="rl-view-list" class="is-active" aria-pressed="true">List</button>
|
||||
<button type="button" id="rl-view-grid" aria-pressed="false">Grid</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="rl-filters">
|
||||
<label class="rl-search">
|
||||
<span class="visually-hidden">Search resources</span>
|
||||
<input id="rl-search" type="search" placeholder="Search title, creator, tag…" autocomplete="off" />
|
||||
</label>
|
||||
<label><span class="visually-hidden">Resource type</span><select id="rl-filter-type">
|
||||
<option value="">All types</option><option value="book">Books</option><option value="article">Articles</option><option value="video">Videos</option>
|
||||
</select></label>
|
||||
<label><span class="visually-hidden">Resource status</span><select id="rl-filter-status">
|
||||
<option value="">All statuses</option><option value="backlog">Backlog</option><option value="shelf">Shelf</option><option value="active">Active</option><option value="completed">Completed</option><option value="archived">Archived</option>
|
||||
</select></label>
|
||||
<label><span class="visually-hidden">Resource tag</span><select id="rl-filter-tag"><option value="">All tags</option></select></label>
|
||||
<label><span class="visually-hidden">Sort resources</span><select id="rl-sort">
|
||||
<option value="updated">Recently updated</option><option value="title">Title</option><option value="progress">Progress</option>
|
||||
</select></label>
|
||||
</div>
|
||||
|
||||
<div class="rl-resource-list" id="rl-resource-list" aria-live="polite"></div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<dialog class="rl-dialog rl-resource-dialog" id="rl-resource-dialog">
|
||||
<form method="dialog" class="rl-dialog__shell" id="rl-resource-form">
|
||||
<header class="rl-dialog__head">
|
||||
<div><p class="rl-eyebrow">Library record</p><h2 id="rl-resource-dialog-title">Add resource</h2></div>
|
||||
<button type="button" class="rl-close" data-close-dialog aria-label="Close">×</button>
|
||||
</header>
|
||||
<div class="rl-dialog__body">
|
||||
<input type="hidden" id="rl-resource-id" />
|
||||
<input type="hidden" id="rl-attachment-id" />
|
||||
<input type="hidden" id="rl-thumbnail-id" />
|
||||
<div class="rl-cover-preview" id="rl-cover-preview" aria-label="Cover preview"><span>Cover</span></div>
|
||||
<div class="rl-form-grid">
|
||||
<label class="rl-field rl-field--wide">Title <input id="rl-field-title" required maxlength="300" /></label>
|
||||
<label class="rl-field rl-field--wide">Creators <input id="rl-field-creators" placeholder="Separate names with commas" /></label>
|
||||
<label class="rl-field">Type <select id="rl-field-type"><option value="book">Book</option><option value="article">Article</option><option value="video">Video</option></select></label>
|
||||
<label class="rl-field">Format <select id="rl-field-format"><option value="physical">Physical</option><option value="pdf">PDF</option><option value="web">Web</option></select></label>
|
||||
<label class="rl-field">Status <select id="rl-field-status"><option value="backlog">Backlog</option><option value="shelf">Shelf</option><option value="active">Active</option><option value="completed">Completed</option><option value="archived">Archived</option></select></label>
|
||||
<label class="rl-field">Folder <select id="rl-field-folder"><option value="">Unfiled</option></select></label>
|
||||
<label class="rl-field">Pages <input id="rl-field-pages" type="number" min="0" inputmode="numeric" /></label>
|
||||
<label class="rl-field">Duration (minutes) <input id="rl-field-duration" type="number" min="0" inputmode="numeric" /></label>
|
||||
<label class="rl-field rl-field--wide">URL <input id="rl-field-url" type="url" placeholder="https://…" /></label>
|
||||
<label class="rl-field">Publisher / channel <input id="rl-field-publisher" /></label>
|
||||
<label class="rl-field">Published <input id="rl-field-published" placeholder="Year or date" /></label>
|
||||
<label class="rl-field rl-field--wide">Tags <input id="rl-field-tags" placeholder="Separate tags with commas" /></label>
|
||||
<label class="rl-field rl-field--wide">Description <textarea id="rl-field-description" rows="3"></textarea></label>
|
||||
<label class="rl-field rl-field--wide">Notes <textarea id="rl-field-notes" rows="4"></textarea></label>
|
||||
</div>
|
||||
<section class="rl-sessions" id="rl-session-section" hidden>
|
||||
<div class="rl-sessions__head"><h3>Progress sessions</h3><button type="button" id="rl-add-session">Log session</button></div>
|
||||
<div id="rl-session-list"></div>
|
||||
</section>
|
||||
</div>
|
||||
<footer class="rl-dialog__foot">
|
||||
<button type="button" class="rl-danger" id="rl-delete-resource" hidden>Delete</button>
|
||||
<span class="rl-dialog__spacer"></span>
|
||||
<button type="button" id="rl-open-resource" hidden>Open</button>
|
||||
<button type="button" data-close-dialog>Cancel</button>
|
||||
<button type="submit" class="rl-primary">Save resource</button>
|
||||
</footer>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<dialog class="rl-dialog" id="rl-session-dialog">
|
||||
<form method="dialog" class="rl-dialog__shell rl-dialog__shell--small" id="rl-session-form">
|
||||
<header class="rl-dialog__head"><div><p class="rl-eyebrow">Reading activity</p><h2>Log a session</h2></div><button type="button" class="rl-close" data-close-dialog aria-label="Close">×</button></header>
|
||||
<div class="rl-dialog__body rl-form-grid">
|
||||
<label class="rl-field">Date <input id="rl-session-date" type="date" required /></label>
|
||||
<label class="rl-field"><span id="rl-session-start-label">Start page</span><input id="rl-session-start" type="number" min="0" required /></label>
|
||||
<label class="rl-field"><span id="rl-session-end-label">End page</span><input id="rl-session-end" type="number" min="0" required /></label>
|
||||
<label class="rl-field rl-field--wide">Note <textarea id="rl-session-note" rows="3"></textarea></label>
|
||||
</div>
|
||||
<footer class="rl-dialog__foot"><button type="button" data-close-dialog>Cancel</button><button type="submit" class="rl-primary">Save session</button></footer>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<dialog class="rl-dialog" id="rl-name-dialog">
|
||||
<form method="dialog" class="rl-dialog__shell rl-dialog__shell--small" id="rl-name-form">
|
||||
<header class="rl-dialog__head"><div><p class="rl-eyebrow" id="rl-name-kicker">Organise</p><h2 id="rl-name-title">Add folder</h2></div><button type="button" class="rl-close" data-close-dialog aria-label="Close">×</button></header>
|
||||
<div class="rl-dialog__body"><label class="rl-field">Name <input id="rl-name-input" required maxlength="80" /></label><label class="rl-field" id="rl-colour-field" hidden>Colour <input id="rl-name-colour" type="color" value="#9b6b43" /></label></div>
|
||||
<footer class="rl-dialog__foot"><button type="button" class="rl-danger" id="rl-name-delete" hidden>Delete</button><span class="rl-dialog__spacer"></span><button type="button" data-close-dialog>Cancel</button><button type="submit" class="rl-primary">Save</button></footer>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
<dialog class="rl-dialog" id="rl-vault-dialog">
|
||||
<div class="rl-dialog__shell rl-dialog__shell--small">
|
||||
<header class="rl-dialog__head"><div><p class="rl-eyebrow">Separate collections</p><h2>Manage vaults</h2></div><button type="button" class="rl-close" data-close-dialog aria-label="Close">×</button></header>
|
||||
<div class="rl-dialog__body"><div id="rl-vault-list"></div><button type="button" class="rl-primary" id="rl-add-vault">Add vault</button></div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<dialog class="rl-dialog" id="rl-import-dialog">
|
||||
<div class="rl-dialog__shell rl-dialog__shell--small">
|
||||
<header class="rl-dialog__head"><div><p class="rl-eyebrow">JSON preview</p><h2>Import library</h2></div><button type="button" class="rl-close" data-close-dialog aria-label="Close">×</button></header>
|
||||
<div class="rl-dialog__body"><div class="rl-import-summary" id="rl-import-summary"></div><p class="rl-help">PDF files are not contained in JSON backups and must be reattached in this browser.</p></div>
|
||||
<footer class="rl-dialog__foot"><button type="button" data-close-dialog>Cancel</button><button type="button" id="rl-import-replace">Replace all</button><button type="button" class="rl-primary" id="rl-import-merge">Merge</button></footer>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<dialog class="rl-dialog" id="rl-storage-dialog">
|
||||
<div class="rl-dialog__shell rl-dialog__shell--small">
|
||||
<header class="rl-dialog__head"><div><p class="rl-eyebrow">This browser</p><h2>Local storage</h2></div><button type="button" class="rl-close" data-close-dialog aria-label="Close">×</button></header>
|
||||
<div class="rl-dialog__body"><p id="rl-storage-summary">Calculating storage use…</p><p class="rl-help">Export JSON regularly. Clearing browser data removes vault metadata and retained PDFs.</p><button type="button" id="rl-request-persistence">Request persistent storage</button></div>
|
||||
<footer class="rl-dialog__foot"><button type="button" class="rl-danger" id="rl-clear-data">Clear Resource Loader data</button><button type="button" data-close-dialog>Close</button></footer>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<div class="rl-loading" id="rl-loading" role="status"><span></span><p>Opening your library…</p></div>
|
||||
<div class="rl-toast" id="rl-toast" role="status" aria-live="polite"></div>
|
||||
#+END_EXPORT
|
||||
Reference in New Issue
Block a user