Move file linking to component detail view, consistent with images

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-22 00:24:35 +00:00
parent f0bedc80a7
commit 61d52d8076
3 changed files with 58 additions and 54 deletions

View File

@@ -336,23 +336,59 @@ function render_detail_panel() {
// Linked files
const files_list = qs(content, '.detail-files-list');
async function save_file_ids(new_ids) {
const result = await api.update_component(comp.id, { file_ids: new_ids });
const idx = all_components.findIndex(c => c.id === comp.id);
if (idx !== -1) all_components[idx] = result.component;
render_detail_panel();
}
function rebuild_detail_files() {
const linked_files = all_pdfs.filter(p => (comp.file_ids ?? []).includes(p.id));
if (linked_files.length === 0) {
const note = document.createElement('p');
note.className = 'detail-empty-note';
note.textContent = 'No files linked.';
files_list.replaceChildren(note);
} else {
files_list.replaceChildren(...linked_files.map(pdf => {
const rows = linked_files.map(pdf => {
const row = document.createElement('div');
row.className = 'detail-file-row';
const a = document.createElement('a');
a.className = 'detail-file-link';
a.href = `/pdf/${pdf.filename}`;
a.target = '_blank';
a.rel = 'noopener';
a.textContent = pdf.display_name;
return a;
}));
const unlink_btn = document.createElement('button');
unlink_btn.type = 'button';
unlink_btn.className = 'btn-icon btn-danger';
unlink_btn.textContent = '✕';
unlink_btn.title = 'Unlink file';
unlink_btn.addEventListener('click', () => {
const new_ids = (comp.file_ids ?? []).filter(id => id !== pdf.id);
save_file_ids(new_ids);
});
row.append(a, unlink_btn);
return row;
});
if (rows.length === 0) {
const note = document.createElement('p');
note.className = 'detail-empty-note';
note.textContent = 'No files linked.';
files_list.replaceChildren(note);
} else {
files_list.replaceChildren(...rows);
}
}
rebuild_detail_files();
qs(content, '.detail-link-file-btn').addEventListener('click', () => {
open_file_picker((pdf) => {
const new_ids = [...new Set([...(comp.file_ids ?? []), pdf.id])];
save_file_ids(new_ids);
});
});
// Inventory entries
const inv_list = qs(content, '.detail-inventory-list');
@@ -1421,42 +1457,6 @@ function open_component_dialog(comp = null) {
desc_input.value = comp?.description ?? '';
const active_fields = new Map(Object.entries(comp?.fields ?? {}));
const active_file_ids = new Set(comp?.file_ids ?? []);
const file_rows_el = qs(dlg, '#c-file-rows');
function rebuild_file_rows() {
const linked = all_pdfs.filter(p => active_file_ids.has(p.id));
file_rows_el.replaceChildren(...linked.map(pdf => {
const row = document.createElement('div');
row.className = 'c-field-input-row';
const name_el = document.createElement('span');
name_el.className = 'c-field-input-label';
name_el.textContent = pdf.display_name;
const remove_btn = document.createElement('button');
remove_btn.type = 'button';
remove_btn.className = 'btn-icon btn-danger';
remove_btn.textContent = '✕';
remove_btn.title = 'Unlink file';
remove_btn.addEventListener('click', () => {
active_file_ids.delete(pdf.id);
rebuild_file_rows();
});
row.append(name_el, remove_btn);
return row;
}));
}
rebuild_file_rows();
qs(dlg, '#c-link-file').addEventListener('click', () => {
open_file_picker((pdf) => {
active_file_ids.add(pdf.id);
rebuild_file_rows();
});
});
function rebuild_field_rows() {
field_rows_el.replaceChildren(...[...active_fields.entries()].map(([fid, val]) => {
@@ -1552,7 +1552,7 @@ function open_component_dialog(comp = null) {
for (const [fid, val] of active_fields.entries()) {
if (val.trim()) fields[fid] = val.trim();
}
const body = { name, description: desc_input.value.trim(), fields, file_ids: [...active_file_ids] };
const body = { name, description: desc_input.value.trim(), fields };
if (comp) {
const result = await api.update_component(comp.id, body);
const idx = all_components.findIndex(c => c.id === comp.id);

View File

@@ -1571,6 +1571,12 @@ nav {
gap: 0.3rem;
}
.detail-file-row {
display: flex;
align-items: center;
gap: 0.5rem;
}
.detail-file-link {
color: var(--accent);
text-decoration: none;

View File

@@ -58,7 +58,10 @@
</div>
<div class="detail-block">
<div class="detail-block-label">Files</div>
<div class="detail-block-label">
Files
<button class="btn btn-secondary detail-link-file-btn">+ Link file</button>
</div>
<div class="detail-files-list"></div>
</div>
@@ -401,12 +404,7 @@
<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">
<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>
</div>