Add PDF file attachments to components

- Upload PDFs, rename them (conflict-checked), delete them
- Link/unlink files per component (many components can share a file)
- File picker dialog: browse existing files, rename inline, upload new
- Component detail shows linked files as clickable links
- Files stored in data/pdfs/, served at /pdf/:filename
- KV prefix: pdf:

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-22 00:19:30 +00:00
parent e91a656dc8
commit f0bedc80a7
6 changed files with 393 additions and 4 deletions

View File

@@ -57,6 +57,11 @@
</div>
</div>
<div class="detail-block">
<div class="detail-block-label">Files</div>
<div class="detail-files-list"></div>
</div>
<div class="detail-block">
<div class="detail-block-label">
Inventory
@@ -396,6 +401,11 @@
<button type="button" class="btn btn-secondary btn-sm" id="c-new-field">New…</button>
</div>
</div>
<div class="form-section-label">Files</div>
<div id="c-file-rows"></div>
<div class="form-row">
<button type="button" class="btn btn-secondary btn-sm" id="c-link-file">Link file…</button>
</div>
<div class="dialog-actions">
<button type="button" class="btn btn-secondary" id="c-cancel">Cancel</button>
<button type="submit" class="btn btn-primary" id="c-save">Save</button>
@@ -553,6 +563,25 @@
</dialog>
</template>
<!-- ===== DIALOG: FILE PICKER ===== -->
<template id="t-dialog-file-picker">
<dialog id="dialog-file-picker" class="app-dialog app-dialog-wide">
<h2 class="dialog-title">Files</h2>
<div id="fp-list" class="fp-list"></div>
<div class="fp-upload-section">
<div class="form-section-label">Upload new PDF</div>
<div class="fp-upload-row">
<input type="file" id="fp-file-input" accept=".pdf,application/pdf">
<input type="text" id="fp-upload-name" placeholder="Display name (optional)" autocomplete="off">
<button type="button" class="btn btn-primary btn-sm" id="fp-upload-btn">Upload</button>
</div>
</div>
<div class="dialog-actions">
<button type="button" class="btn btn-secondary" id="fp-cancel">Close</button>
</div>
</dialog>
</template>
<!-- ===== CELL INVENTORY OVERLAY ===== -->
<template id="t-cell-inventory">
<div class="cell-inventory-overlay" id="cell-inventory-overlay">