83 lines
2.3 KiB
TypeScript
83 lines
2.3 KiB
TypeScript
const editor = document.getElementById("editor") as HTMLTextAreaElement;
|
|
const backLink = document.getElementById("back-link") as HTMLAnchorElement;
|
|
const saveBtn = document.getElementById("save-btn") as HTMLButtonElement;
|
|
const status = document.getElementById("status")!;
|
|
|
|
const path = decodeURIComponent(window.location.pathname.replace(/^\/edit\//, "")) || null;
|
|
|
|
// Set back link to return to the file view
|
|
if (path) {
|
|
backLink.href = "/" + path.split("/").map(encodeURIComponent).join("/");
|
|
}
|
|
|
|
let savedContent = "";
|
|
|
|
if (!path) {
|
|
editor.value = "Error: no file path specified";
|
|
editor.disabled = true;
|
|
} else {
|
|
const res = await fetch("/api/read?path=" + encodeURIComponent(path));
|
|
const data = await res.json();
|
|
|
|
if (data.error) {
|
|
editor.value = "Error: " + data.error;
|
|
editor.disabled = true;
|
|
} else {
|
|
savedContent = data.content;
|
|
editor.value = data.content;
|
|
saveBtn.disabled = true;
|
|
}
|
|
}
|
|
|
|
const isDirty = () => editor.value !== savedContent;
|
|
|
|
editor.addEventListener("input", () => {
|
|
const dirty = isDirty();
|
|
saveBtn.disabled = !dirty;
|
|
status.textContent = dirty ? "Unsaved changes" : "";
|
|
});
|
|
|
|
window.addEventListener("beforeunload", (e) => {
|
|
if (isDirty()) e.preventDefault();
|
|
});
|
|
|
|
async function save() {
|
|
if (!path) return;
|
|
saveBtn.disabled = true;
|
|
status.textContent = "Saving...";
|
|
|
|
try {
|
|
const res = await fetch("/api/edit", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ path, content: editor.value }),
|
|
});
|
|
const data = await res.json();
|
|
|
|
if (data.error) {
|
|
status.textContent = "Error: " + data.error;
|
|
saveBtn.disabled = false;
|
|
} else {
|
|
savedContent = editor.value;
|
|
window.location.href = "/" + path.split("/").map(encodeURIComponent).join("/");
|
|
}
|
|
} catch (err: unknown) {
|
|
const message = err instanceof Error ? err.message : "Failed to save";
|
|
status.textContent = "Error: " + message;
|
|
saveBtn.disabled = false;
|
|
}
|
|
}
|
|
|
|
saveBtn.addEventListener("click", save);
|
|
|
|
document.addEventListener("keydown", (e) => {
|
|
if ((e.ctrlKey || e.metaKey) && e.key === "s") {
|
|
e.preventDefault();
|
|
if (!saveBtn.disabled) save();
|
|
}
|
|
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
|
e.preventDefault();
|
|
if (!saveBtn.disabled) save();
|
|
}
|
|
});
|