- log_thread.py: thread-safe ContextVar bridge so executor threads can log
individual LLM calls and archive searches back to the event loop
- ai_log.py: init_thread_logging(), notify_entity_update(); WS now pushes
entity_update messages when book data changes after any plugin or batch run
- batch.py: replace batch_pending.json with batch_queue SQLite table;
run_batch_consumer() reads queue dynamically so new books can be added
while batch is running; add_to_queue() deduplicates
- migrate.py: fix _migrate_v1 (clear-on-startup bug); add _migrate_v2 for
batch_queue table
- _client.py / archive.py / identification.py: wrap each LLM API call and
archive search with log_thread start/finish entries
- api.py: POST /api/batch returns {already_running, added}; notify_entity_update
after identify pipeline
- models.default.yaml: strengthen ai_identify confidence-scoring instructions;
warn against placeholder data
- detail-render.js: book log entries show clickable ID + spine thumbnail;
book spine/title images open full-screen popup
- events.js: batch-start handles already_running+added; open-img-popup action
- init.js: entity_update WS handler; image popup close listeners
- overlays.css / index.html: full-screen image popup overlay
- eslint.config.js: add new globals; fix no-redeclare/no-unused-vars for
multi-file global architecture; all lint errors resolved
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
91 lines
3.9 KiB
HTML
91 lines
3.9 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
|
||
<meta name="theme-color" content="#1e3a5f">
|
||
<title>Bookshelf</title>
|
||
|
||
<!-- Global reset, body font/background, and .hidden utility -->
|
||
<link rel="stylesheet" href="css/base.css">
|
||
<!-- Sticky header, two-column desktop layout, mobile single-column default -->
|
||
<link rel="stylesheet" href="css/layout.css">
|
||
<!-- Sidebar tree: node rows, drag handle, toggle, name, action buttons, book thumbnails, status/source badges -->
|
||
<link rel="stylesheet" href="css/tree.css">
|
||
<!-- Generic button variants, book detail panel, image/canvas wrapper, identification form -->
|
||
<link rel="stylesheet" href="css/forms.css">
|
||
<!-- Fixed-position overlays: toast notification, loading spinner, photo queue -->
|
||
<link rel="stylesheet" href="css/overlays.css">
|
||
</head>
|
||
<body>
|
||
|
||
<!-- Main app mount point — entire UI is rendered here by render() in js/init.js -->
|
||
<div id="app"></div>
|
||
|
||
<!-- Photo queue overlay: full-screen mobile UI for sequential book photography.
|
||
Lives outside #app so its event listener does not conflict with the tree. -->
|
||
<div id="photo-queue-overlay" style="display:none"></div>
|
||
|
||
<!-- Shared file input for all photo uploads (cabinet, shelf, book, room).
|
||
Triggered programmatically by triggerPhoto() in js/photo.js. -->
|
||
<input type="file" id="gphoto" accept="image/*" class="hidden">
|
||
|
||
<!-- Slide-in toast notification; text set by toast() in js/helpers.js -->
|
||
<div class="toast" id="toast"></div>
|
||
|
||
<!-- Full-screen image popup: shown when user clicks a book spine or title-page image.
|
||
Closed by clicking outside or the × button. -->
|
||
<div id="img-popup" class="img-popup">
|
||
<div class="img-popup-inner">
|
||
<button class="img-popup-close" id="img-popup-close">×</button>
|
||
<img id="img-popup-img" src="" alt="">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- SortableJS: drag-and-drop reordering for rooms, cabinets, shelves, and books -->
|
||
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.2/Sortable.min.js"></script>
|
||
|
||
<!-- All mutable application state (S, _plugins, _batchState, _bnd, _photoQueue).
|
||
Must load first — every subsequent module reads these globals. -->
|
||
<script src="js/state.js"></script>
|
||
|
||
<!-- Pure utilities: esc(), toast(), isDesktop(). No dependencies. -->
|
||
<script src="js/helpers.js"></script>
|
||
|
||
<!-- Fetch wrapper req(). Throws on non-2xx with server detail message. -->
|
||
<script src="js/api.js"></script>
|
||
|
||
<!-- Boundary-line canvas editor: draw, drag, snap-to-AI, Ctrl+Alt+Click to add.
|
||
Defines _bnd structure — loaded before detail-render.js which reads it. -->
|
||
<script src="js/canvas-boundary.js"></script>
|
||
|
||
<!-- Tree HTML generators: vApp(), vRoom/Cabinet/Shelf/Book(), vBatchBtn(),
|
||
plugin helpers, candidate suggestion rows, walkTree/findNode/removeNode. -->
|
||
<script src="js/tree-render.js"></script>
|
||
|
||
<!-- Detail panel HTML generators: vDetailBody(), vCabinetDetail(),
|
||
vShelfDetail(), vBookDetail(). Reads _bnd for boundary plugin selection. -->
|
||
<script src="js/detail-render.js"></script>
|
||
|
||
<!-- In-place crop tool: draggable rectangle on canvas, POSTs pixel coords.
|
||
Calls drawBnd() on cancel to restore the boundary overlay. -->
|
||
<script src="js/canvas-crop.js"></script>
|
||
|
||
<!-- Inline contenteditable name editing (blur-to-save) and SortableJS wiring. -->
|
||
<script src="js/editing.js"></script>
|
||
|
||
<!-- Photo upload for all entity types and mobile Photo Queue feature.
|
||
Registers the gphoto 'change' handler at parse time. -->
|
||
<script src="js/photo.js"></script>
|
||
|
||
<!-- Event delegation on #app and #photo-queue-overlay; central handle() dispatcher
|
||
with all action cases; accordion expand helpers. -->
|
||
<script src="js/events.js"></script>
|
||
|
||
<!-- render(), renderDetail(), loadConfig(), connectBatchWs(), loadTree(),
|
||
and the bootstrap Promise.all([loadConfig(), loadTree()]) call. -->
|
||
<script src="js/init.js"></script>
|
||
|
||
</body>
|
||
</html>
|