feat(files): file-row click opens editor via URL-addressable modal
files-overlay.js no longer fetches /files/content JSON and populates the inline <dialog>; it calls window.openModal(<edit-url>) which the modal-router handles end-to-end. Binary files retain the old inline dialog path (binary replace deferred from pilot scope). Added document-level event delegation for .files-editor-save and .files-editor-delete inside #modal-content so save/delete work on the server-rendered editor DOM (reads data-rel-path from the textarea; calls window.__filesEditor.getValue() for content; calls closeModal() on success). The inline dialog's own save/delete handlers are untouched and continue to serve the create-new-file and binary-replace flows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7829d1ca95
commit
64cf203890
1 changed files with 65 additions and 1 deletions
|
|
@ -589,6 +589,57 @@
|
|||
}
|
||||
});
|
||||
|
||||
// ---------- modal-content save / delete (URL-addressable modal) ----------
|
||||
// The new server-rendered editor (loaded into #modal-content) has its own
|
||||
// .files-editor-save and .files-editor-delete buttons. Those are not the
|
||||
// same elements as editorEls.saveBtn / editorEls.deleteBtn (which live in
|
||||
// the old inline dialog still present for create-new-file / binary flows).
|
||||
// Use event delegation so the handlers fire on dynamically swapped content.
|
||||
|
||||
document.addEventListener("click", async (event) => {
|
||||
const modalContent = document.getElementById("modal-content");
|
||||
if (!modalContent) return;
|
||||
|
||||
const saveBtn = event.target.closest(".files-editor-save");
|
||||
if (saveBtn && modalContent.contains(saveBtn)) {
|
||||
const ta = modalContent.querySelector("textarea[data-rel-path]");
|
||||
if (!ta) return;
|
||||
const relPath = ta.dataset.relPath;
|
||||
if (!relPath) return;
|
||||
const content = (window.__filesEditor && window.__filesEditor.getValue)
|
||||
? window.__filesEditor.getValue()
|
||||
: ta.value;
|
||||
const r = await postJson(`${baseUrl}/files/save`, { path: relPath, content });
|
||||
if (r.ok) {
|
||||
if (typeof window.closeModal === "function") window.closeModal();
|
||||
scheduleRefresh(parentOf(relPath));
|
||||
} else {
|
||||
alert((r.body && r.body.error) || `Save failed (HTTP ${r.status}).`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const deleteBtn = event.target.closest(".files-editor-delete");
|
||||
if (deleteBtn && modalContent.contains(deleteBtn)) {
|
||||
const ta = modalContent.querySelector("textarea[data-rel-path]");
|
||||
if (!ta) return;
|
||||
const relPath = ta.dataset.relPath;
|
||||
if (!relPath) return;
|
||||
if (!confirm(`Delete ${relPath}?`)) return;
|
||||
const fd = new FormData();
|
||||
fd.append("path", relPath);
|
||||
fd.append("csrf_token", csrfToken);
|
||||
const r = await postForm(`${baseUrl}/files/delete`, fd);
|
||||
if (r.ok) {
|
||||
if (typeof window.closeModal === "function") window.closeModal();
|
||||
scheduleRefresh(parentOf(relPath));
|
||||
} else {
|
||||
alert((r.body && r.body.error) || `Delete failed (HTTP ${r.status}).`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// ---------- new-folder modal --------------------------------------------
|
||||
|
||||
function openNewFolder(targetFolder) {
|
||||
|
|
@ -994,7 +1045,20 @@
|
|||
window.location.href = url;
|
||||
} else if (op === "edit") {
|
||||
const editable = action.dataset.editable === "1";
|
||||
openEditorForFile(path, editable);
|
||||
if (editable) {
|
||||
// Editable text files: open via URL-addressable modal.
|
||||
const editUrl = `/overlays/${overlayId}/files/edit?path=${encodeURIComponent(path)}`;
|
||||
if (typeof window.openModal === "function") {
|
||||
window.openModal(editUrl);
|
||||
} else {
|
||||
// Graceful fallback if modal-router didn't load — full-page navigation
|
||||
// still hits the same route and renders the standalone editor page.
|
||||
window.location.href = editUrl;
|
||||
}
|
||||
} else {
|
||||
// Binary files: keep old inline dialog (binary replace deferred from pilot).
|
||||
openEditorForFile(path, false);
|
||||
}
|
||||
} else if (op === "delete") {
|
||||
const kind = action.dataset.rowKind;
|
||||
const name = action.dataset.rowName || basename(path);
|
||||
|
|
|
|||
Loading…
Reference in a new issue