mirror of
https://github.com/thegeneralist01/archivr
synced 2026-07-22 03:05:32 +02:00
feat(ui): rewrite frontend in React with Vite
- Scaffold Vite+React project in frontend/ (bun, react 18, @vitejs/plugin-react) - vite.config.js outputs to crates/archivr-server/static/ directly - src/utils.js: formatBytes, valueText, formatTimestamp, SOURCE_ICONS, sourceIconSvg - src/api.js: typed fetch wrappers for all API endpoints - App.jsx: full state management, archive switching, debounced search, tag filter, view routing, capture dialog orchestration - components/Topbar.jsx: archive switcher, nav, capture button - components/CaptureDialog.jsx: native <dialog> ref with showModal/close, Escape key support, locator validation - components/EntriesView.jsx + EntryRow.jsx: flex table with source icons, type pills, keyboard selection - components/ContextRail.jsx: parallel detail+tags fetch, stale-race guard via selectSeqRef, inline tag assign/remove - components/RunsView.jsx: runs kept as <table> (matches original) - components/AdminView.jsx: mounted archives list - components/TagsView.jsx: recursive tag tree with active state - Remove old app.js; styles.css moved to frontend/src/ (Vite bundles it)
This commit is contained in:
parent
b895d6331c
commit
4458f17b13
22 changed files with 1035 additions and 591 deletions
|
|
@ -1,94 +1,13 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Archivr</title>
|
||||
<link rel="stylesheet" href="/assets/styles.css">
|
||||
<script type="module" crossorigin src="/assets/index-XKDv7X2o.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DJpQthbx.css">
|
||||
</head>
|
||||
<body>
|
||||
<header class="topbar">
|
||||
<div class="brand">Archivr</div>
|
||||
<select id="archive-switcher" class="archive-switcher" aria-label="Select archive"></select>
|
||||
<nav class="nav" aria-label="Primary">
|
||||
<button class="nav-link is-active" data-view="archive">Archive</button>
|
||||
<button class="nav-link" data-view="runs">Runs</button>
|
||||
<button class="nav-link" data-view="admin">Admin</button>
|
||||
<button class="nav-link" data-view="tags">Tags</button>
|
||||
</nav>
|
||||
<button class="capture-button">+ Capture</button>
|
||||
</header>
|
||||
|
||||
<main class="app-shell">
|
||||
<section class="workspace">
|
||||
<div class="search-row">
|
||||
<input id="search" class="search-input" type="search" aria-label="Search archive" autocomplete="off">
|
||||
<div id="result-count" class="result-count"></div>
|
||||
</div>
|
||||
|
||||
<section id="archive-view" class="view is-active">
|
||||
<div class="entry-table">
|
||||
<div class="entry-header-row">
|
||||
<div class="col-added">Added</div>
|
||||
<div class="col-title">Title</div>
|
||||
<div class="col-type">Type</div>
|
||||
<div class="col-size">Size</div>
|
||||
<div class="col-url">Original URL</div>
|
||||
</div>
|
||||
<div id="entries-body"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="runs-view" class="view">
|
||||
<table class="entry-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Started</th>
|
||||
<th>Status</th>
|
||||
<th>Requested</th>
|
||||
<th>Completed</th>
|
||||
<th>Failed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="runs-body"></tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section id="admin-view" class="view admin-view">
|
||||
<h1>Mounted Archives</h1>
|
||||
<div id="admin-archives" class="admin-list"></div>
|
||||
</section>
|
||||
|
||||
<section id="tags-view" class="view">
|
||||
<div id="tag-tree" class="tag-tree"></div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<aside class="context-rail">
|
||||
<div class="rail-title">Context</div>
|
||||
<div id="context-body" class="rail-body">Select an entry.</div>
|
||||
<div id="entry-tags" class="entry-tags" hidden></div>
|
||||
<div id="assign-tag-form" class="assign-tag-form" hidden>
|
||||
<input id="assign-tag-input" class="assign-tag-input" type="text" placeholder="/science/cs" autocomplete="off">
|
||||
<button id="assign-tag-btn" class="assign-tag-btn">Add tag</button>
|
||||
</div>
|
||||
</aside>
|
||||
</main>
|
||||
|
||||
<dialog id="capture-dialog" class="capture-dialog">
|
||||
<div class="capture-dialog-inner">
|
||||
<h2 class="capture-dialog-title">Capture</h2>
|
||||
<label for="capture-locator" class="capture-label">Locator</label>
|
||||
<input id="capture-locator" class="capture-input" type="text"
|
||||
placeholder="tweet:1234567890 or https://..." autocomplete="off">
|
||||
<div id="capture-error" class="capture-error" hidden></div>
|
||||
<div class="capture-actions">
|
||||
<button type="button" id="capture-cancel-btn" class="capture-cancel">Cancel</button>
|
||||
<button type="button" id="capture-submit-btn" class="capture-submit">Capture</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<script type="module" src="/assets/app.js"></script>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue