malachite/app/templates_src/edit.lisp
2025-08-20 00:26:44 -04:00

209 lines
8 KiB
Common Lisp

(text "{% extends \"root.lisp\" %} {% block head %}")
(title
(text "{{ entry.slug }}"))
(link ("rel" "icon") ("href" "/public/favicon.svg"))
(text "{% endblock %} {% block body %}")
(div
("class" "flex items_center bar")
(button
("class" "button tab_button")
("id" "editor_tab_button")
("onclick" "tab_editor()")
(text "Edit"))
(button
("class" "button camo tab_button")
("id" "preview_tab_button")
("onclick" "tab_preview()")
(text "Preview"))
(button
("class" "button camo tab_button")
("id" "metadata_tab_button")
("onclick" "tab_metadata()")
(text "Metadata")
(a
("class" "button simple surface")
("href" "/docs/metadata")
("target" "_blank")
("title" "Info")
(text "i"))))
(div
("class" "flex justify_center tab")
(div
("class" "card tab tabs container w_full")
("id" "tabs_group")
(div
("id" "editor_tab")
("class" "tab fadein w_full"))
(div
("id" "preview_tab")
("class" "tab fadein hidden w_full"))
(div
("id" "metadata_tab")
("class" "tab fadein hidden w_full"))))
(form
("class" "w_full flex flex_col gap_2")
("style" "margin-top: var(--pad-2)")
("onsubmit" "edit_entry(event)")
(div
("class" "w_full flex gap_2")
(input
("class" "w_full")
("type" "text")
("minlength" "2")
("name" "edit_code")
("required" "")
("placeholder" "Enter edit code"))
(input ("class" "w_full") ("style" "visibility: hidden") ("aria-hidden" "true") ("disabled" "true"))
(input ("class" "w_full") ("style" "visibility: hidden") ("aria-hidden" "true") ("disabled" "true")))
(div
("class" "flex gap_2")
(input
("class" "w_full")
("type" "text")
("minlength" "2")
("name" "new_edit_code")
("placeholder" "New edit code"))
(input
("class" "w_full")
("type" "text")
("minlength" "2")
("name" "new_modify_code")
("placeholder" "New modify code"))
(input
("class" "w_full")
("type" "text")
("minlength" "2")
("name" "new_slug")
("oninput" "check_exists_input(event)")
("placeholder" "New url")))
(div
("class" "w_full flex justify_between gap_2")
(div
("class" "flex gap_2")
(button
("class" "button green")
(span ("ui_ident" "text") (text "Save"))
(span ("class" "hidden loader no_fill") ("ui_ident" "loader") (text "{{ icon \"loader-circle\" }}")))
(a
("href" "/{{ entry.slug }}")
("class" "button")
(text "Back")))
(button
("class" "button red")
("type" "button")
("onclick" "document.getElementById('delete_modal').showModal()")
("id" "fake_delete_button")
(span ("ui_ident" "text") (text "Delete"))
(span ("class" "hidden loader no_fill") ("ui_ident" "loader") (text "{{ icon \"loader-circle\" }}")))
(dialog
("id" "delete_modal")
(div
("class" "inner")
(h2 ("class" "text_center w_full") (text "Delete {{ entry.slug }}?"))
(p (text "Deleting this entry will make its custom slug claimable by anyone."))
(p (text "Please ensure that you understand the consequences of deleting this entry before continuing."))
(hr ("class" "margin"))
(div
("class" "w_full flex gap_2 justify_between")
(button
("class" "button")
("type" "button")
("onclick" "document.getElementById('delete_modal').close()")
(text "Cancel"))
(button
("class" "button red")
("ui_ident" "delete")
("onclick" "document.getElementById('delete_modal').close()")
(text "Delete")))))))
; editor
(script ("src" "https://unpkg.com/codemirror@5.39.2/lib/codemirror.js"))
(script ("src" "https://unpkg.com/codemirror@5.39.2/mode/markdown/markdown.js"))
(script ("src" "https://unpkg.com/codemirror@5.39.2/mode/toml/toml.js"))
(script ("src" "https://unpkg.com/codemirror@5.39.2/addon/display/placeholder.js"))
(link ("rel" "stylesheet") ("href" "https://unpkg.com/codemirror@5.39.2/lib/codemirror.css"))
(script ("src" "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"))
(link ("rel" "stylesheet") ("href" "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/default.min.css"))
(script ("id" "editor_content") ("type" "text/markdown") (text "{{ entry.content|remove_script_tags|safe }}"))
(script ("id" "editor_metadata_content") ("type" "text/markdown") (text "{{ entry.metadata|remove_script_tags|safe }}"))
(script
(text "setTimeout(() => {
globalThis.init_editor();
globalThis.init_editor(\"metadata_editor\", \"toml\", \"metadata_tab\", \"editor_metadata_content\");
}, 150);
globalThis.edit_entry = (e) => {
e.preventDefault();
const rm = e.submitter.getAttribute(\"ui_ident\") === \"delete\";
const { load, failed } = submitter_load(rm ? document.getElementById(\"fake_delete_button\") : e.submitter);
load();
fetch(\"/api/v1/entries/{{ entry.id }}\", {
method: \"POST\",
headers: {
\"Content-Type\": \"application/json\",
},
body: JSON.stringify({
content: globalThis.editor.getValue(),
edit_code: e.target.edit_code.value,
new_slug: e.target.new_slug.value || undefined,
new_edit_code: e.target.new_edit_code.value || undefined,
new_modify_code: e.target.new_modify_code.value || undefined,
metadata: globalThis.metadata_editor.getValue(),
\"delete\": rm,
}),
})
.then(res => res.json())
.then((res) => {
if (res.ok) {
globalThis.ALLOW_LEAVE = true;
if (!rm) {
document.cookie = `Atto-Message=\"Entry updated\"; path=/`;
document.cookie = \"Atto-Message-Good=true; path=/\";
window.location.href = `/${res.payload}`;
} else {
document.cookie = `Atto-Message=\"Entry deleted\"; path=/`;
document.cookie = \"Atto-Message-Good=true; path=/\";
window.location.href = \"/\";
}
} else {
show_message(res.message, false);
failed();
}
})
}
globalThis.download = (content, type, name) => {
const blob = new Blob([content], { type });
const url = URL.createObjectURL(blob);
const anchor = document.createElement(\"a\");
anchor.setAttribute(\"download\", name);
anchor.href = url;
anchor.click();
anchor.remove();
}"))
(text "{% endblock %}")
(text "{% block dropdown %}")
(hr)
(span ("class" "title") (text "export"))
(button
("class" "button")
("onclick" "download(globalThis.editor.getValue(), 'text/markdown', '{{ entry.slug }}.md')")
(text "markdown"))
(button
("class" "button")
("onclick" "download(globalThis.metadata_editor.getValue(), 'application/toml', '{{ entry.slug }}.toml')")
(text "metadata"))
(button
("class" "button")
("onclick" "(async () => { download(await get_preview(), 'text/html', '{{ entry.slug }}.html') })();")
(text "html"))
(text "{%- endblock %}")