fluffle/app/templates_src/edit.lisp

210 lines
8 KiB
Common Lisp
Raw Normal View History

2025-07-20 02:49:01 -04:00
(text "{% extends \"root.lisp\" %} {% block head %}")
(title
(text "{{ entry.slug }}"))
2025-07-21 02:11:23 -04:00
(link ("rel" "icon") ("href" "/public/favicon.svg"))
2025-07-20 02:49:01 -04:00
(text "{% endblock %} {% block body %}")
(div
2025-08-03 23:25:39 -04:00
("class" "flex items_center bar")
2025-07-20 02:49:01 -04:00
(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()")
2025-07-21 02:11:23 -04:00
(text "Preview"))
(button
("class" "button camo tab_button")
("id" "metadata_tab_button")
("onclick" "tab_metadata()")
2025-07-25 15:12:15 -04:00
(text "Metadata")
(a
("class" "button simple surface")
("href" "/docs/metadata")
("target" "_blank")
("title" "Info")
(text "i"))))
2025-07-20 02:49:01 -04:00
(div
("class" "flex justify_center tab")
2025-07-20 02:49:01 -04:00
(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"))))
2025-07-20 02:49:01 -04:00
(form
2025-08-04 12:25:54 -04:00
("class" "w_full flex flex_col gap_2")
2025-07-20 02:49:01 -04:00
("style" "margin-top: var(--pad-2)")
("onsubmit" "edit_entry(event)")
(div
2025-08-04 12:25:54 -04:00
("class" "w_full flex gap_2")
2025-07-20 02:49:01 -04:00
(input
2025-08-04 12:25:54 -04:00
("class" "w_full")
2025-07-20 02:49:01 -04:00
("type" "text")
("minlength" "2")
("name" "edit_code")
("required" "")
("placeholder" "Enter edit code"))
2025-08-04 12:25:54 -04:00
(input ("class" "w_full") ("style" "visibility: hidden") ("aria-hidden" "true") ("disabled" "true"))
(input ("class" "w_full") ("style" "visibility: hidden") ("aria-hidden" "true") ("disabled" "true")))
2025-07-26 01:01:45 -04:00
(div
2025-08-03 23:25:39 -04:00
("class" "flex gap_2")
2025-07-20 02:49:01 -04:00
(input
2025-08-04 12:25:54 -04:00
("class" "w_full")
2025-07-20 02:49:01 -04:00
("type" "text")
("minlength" "2")
("name" "new_edit_code")
("placeholder" "New edit code"))
2025-07-26 01:01:45 -04:00
(input
2025-08-04 12:25:54 -04:00
("class" "w_full")
2025-07-26 01:01:45 -04:00
("type" "text")
("minlength" "2")
("name" "new_modify_code")
("placeholder" "New modify code"))
2025-07-20 02:49:01 -04:00
(input
2025-08-04 12:25:54 -04:00
("class" "w_full")
2025-07-20 02:49:01 -04:00
("type" "text")
("minlength" "2")
("name" "new_slug")
2025-07-20 20:43:01 -04:00
("oninput" "check_exists_input(event)")
2025-07-20 02:49:01 -04:00
("placeholder" "New url")))
(div
2025-08-04 12:25:54 -04:00
("class" "w_full flex justify_between gap_2")
2025-07-20 02:49:01 -04:00
(div
2025-08-03 23:25:39 -04:00
("class" "flex gap_2")
2025-07-20 02:49:01 -04:00
(button
("class" "button green")
(span ("ui_ident" "text") (text "Save"))
(span ("class" "hidden loader no_fill") ("ui_ident" "loader") (text "{{ icon \"loader-circle\" }}")))
2025-07-20 02:49:01 -04:00
(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")))))))
2025-07-20 02:49:01 -04:00
; 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"))
2025-07-20 02:49:01 -04:00
(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 }}"))
2025-07-21 02:11:23 -04:00
(script ("id" "editor_metadata_content") ("type" "text/markdown") (text "{{ entry.metadata|remove_script_tags|safe }}"))
2025-07-20 02:49:01 -04:00
(script
(text "setTimeout(() => {
globalThis.init_editor();
globalThis.init_editor(\"metadata_editor\", \"toml\", \"metadata_tab\", \"editor_metadata_content\");
2025-07-20 02:49:01 -04:00
}, 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();
2025-07-20 02:49:01 -04:00
fetch(\"/api/v1/entries/{{ entry.slug }}\", {
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,
2025-07-26 01:01:45 -04:00
new_modify_code: e.target.new_modify_code.value || undefined,
2025-07-21 02:11:23 -04:00
metadata: globalThis.metadata_editor.getValue(),
2025-07-20 02:49:01 -04:00
\"delete\": rm,
}),
})
.then(res => res.json())
.then((res) => {
if (res.ok) {
2025-07-20 03:24:55 -04:00
globalThis.ALLOW_LEAVE = true;
2025-07-20 02:49:01 -04:00
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 {
2025-07-21 02:11:23 -04:00
show_message(res.message, false);
failed();
2025-07-20 02:49:01 -04:00
}
})
}
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();
2025-07-20 02:49:01 -04:00
}"))
(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 %}")