Files
devplacepy/devplacepy/static/js/NoteManager.js
T
retoor cae139ead9
DevPlace CI / test (push) Failing after 28m20s
Add personal notes, DeepSearch history, backup offload, and gateway auth throttling
Also streamline the top navigation: drop the Tools dropdown, make Quizzes
and Battles icon-only entries, and remove the Workspace, Containers and
Editor entry points from the project detail page.
2026-09-12 20:32:31 +02:00

136 lines
4.1 KiB
JavaScript

// retoor <retoor@molodetz.nl>
import { OptimisticAction } from "./OptimisticAction.js";
export class NoteManager extends OptimisticAction {
constructor() {
super();
document.addEventListener("click", (event) => this.onClick(event));
}
onClick(event) {
const toggle = event.target.closest("[data-note-toggle]");
if (toggle) {
event.preventDefault();
this.toggle(toggle);
return;
}
const cancel = event.target.closest(".note-editor-cancel");
if (cancel) {
event.preventDefault();
this.cancel(cancel);
return;
}
const save = event.target.closest(".note-editor-save");
if (save) {
event.preventDefault();
this.save(save);
return;
}
const remove = event.target.closest(".note-editor-delete");
if (remove) {
event.preventDefault();
this.remove(remove);
}
}
toggle(button) {
const widget = button.closest(".note-widget");
const editor = widget ? widget.querySelector(".note-editor") : null;
if (!editor) {
return;
}
const opening = editor.hidden;
editor.hidden = !opening;
button.setAttribute("aria-expanded", opening ? "true" : "false");
if (opening) {
const textarea = editor.querySelector(".note-editor-textarea");
if (textarea) {
textarea.focus();
}
}
}
cancel(button) {
const widget = button.closest(".note-widget");
const editor = widget ? widget.querySelector(".note-editor") : null;
const toggle = widget ? widget.querySelector("[data-note-toggle]") : null;
if (!editor) {
return;
}
const textarea = editor.querySelector(".note-editor-textarea");
if (textarea) {
textarea.value = textarea.dataset.saved || "";
}
editor.hidden = true;
if (toggle) {
toggle.setAttribute("aria-expanded", "false");
}
}
async save(button) {
const widget = button.closest(".note-widget");
const editor = widget ? widget.querySelector(".note-editor") : null;
const textarea = editor ? editor.querySelector(".note-editor-textarea") : null;
if (!widget || !textarea) {
return;
}
const content = textarea.value.trim();
if (!content) {
return;
}
const type = widget.dataset.noteType;
const uid = widget.dataset.noteUid;
await this.submit(
`/notes/${type}/${uid}`,
{ content },
widget,
(result) => this.applySaved(widget, result.content),
button
);
}
async remove(button) {
const widget = button.closest(".note-widget");
if (!widget) {
return;
}
const type = widget.dataset.noteType;
const uid = widget.dataset.noteUid;
await this.submit(
`/notes/${type}/${uid}/delete`,
{},
widget,
() => this.applySaved(widget, ""),
button
);
}
applySaved(widget, content) {
const toggle = widget.querySelector("[data-note-toggle]");
const editor = widget.querySelector(".note-editor");
const textarea = editor ? editor.querySelector(".note-editor-textarea") : null;
const label = toggle ? toggle.querySelector(".note-label") : null;
const deleteBtn = editor ? editor.querySelector(".note-editor-delete") : null;
if (textarea) {
textarea.value = content;
textarea.dataset.saved = content;
}
if (toggle) {
toggle.classList.toggle("has-note", Boolean(content));
}
if (label) {
label.textContent = content ? "Edit note" : "Add note";
}
if (deleteBtn) {
deleteBtn.hidden = !content;
}
if (editor) {
editor.hidden = true;
}
if (toggle) {
toggle.setAttribute("aria-expanded", "false");
}
}
}