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 --------------------------------------------
|
// ---------- new-folder modal --------------------------------------------
|
||||||
|
|
||||||
function openNewFolder(targetFolder) {
|
function openNewFolder(targetFolder) {
|
||||||
|
|
@ -994,7 +1045,20 @@
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
} else if (op === "edit") {
|
} else if (op === "edit") {
|
||||||
const editable = action.dataset.editable === "1";
|
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") {
|
} else if (op === "delete") {
|
||||||
const kind = action.dataset.rowKind;
|
const kind = action.dataset.rowKind;
|
||||||
const name = action.dataset.rowName || basename(path);
|
const name = action.dataset.rowName || basename(path);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue