1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-22 11:15:41 +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:
TheGeneralist 2026-06-24 12:24:34 +02:00
parent b895d6331c
commit 4458f17b13
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4
22 changed files with 1035 additions and 591 deletions

View file

@ -0,0 +1,27 @@
import EntryRow from './EntryRow';
export default function EntriesView({ entries, selectedEntryUid, onSelectEntry }) {
return (
<section id="archive-view" className="view is-active">
<div className="entry-table">
<div className="entry-header-row">
<div className="col-added">Added</div>
<div className="col-title">Title</div>
<div className="col-type">Type</div>
<div className="col-size">Size</div>
<div className="col-url">Original URL</div>
</div>
<div id="entries-body">
{entries.map(entry => (
<EntryRow
key={entry.entry_uid}
entry={entry}
isSelected={entry.entry_uid === selectedEntryUid}
onSelect={() => onSelectEntry(entry)}
/>
))}
</div>
</div>
</section>
);
}