add: drawings in questions

This commit is contained in:
trisua 2025-06-20 17:40:55 -04:00
parent 6be729de50
commit 16843a6ab8
28 changed files with 1181 additions and 32 deletions

View file

@ -18,6 +18,42 @@
(div ("class" "skel") ("style" "width: 25%; height: 25px;"))
(div ("class" "skel") ("style" "width: 100%; height: 150px"))))))
(template
("id" "carp_canvas")
(div
("class" "flex flex-col gap-2")
(div ("ui_ident" "canvas_loc"))
(div
("class" "flex justify-between gap-2")
(div
("class" "flex gap-2")
(input
("type" "color")
("style" "width: 5rem")
("ui_ident" "color_picker"))
(input
("type" "range")
("min" "1")
("max" "25")
("step" "1")
("value" "2")
("ui_ident" "stroke_range")))
(div
("class" "flex gap-2")
(button
("title" "Undo")
("ui_ident" "undo")
("type" "button")
(icon (text "undo")))
(button
("title" "Redo")
("ui_ident" "redo")
("type" "button")
(icon (text "redo")))))))
; random js
(text "<script data-turbo-permanent=\"true\" id=\"init-script\">
document.documentElement.addEventListener(\"turbo:load\", () => {

View file

@ -405,7 +405,7 @@
(text "{%- endif %}"))))
(text "{% if community and show_community and community.id != config.town_square or question %}"))
(text "{%- endif %} {%- endmacro %} {% macro post_media(upload_ids) -%} {% if upload_ids|length > 0%}")
(text "{%- endif %} {%- endmacro %} {% macro post_media(upload_ids) -%} {% if upload_ids|length > 0 -%}")
(div
("class" "media_gallery gap-2")
(text "{% for upload in upload_ids %}")
@ -677,6 +677,8 @@
("class" "no_p_margin")
("style" "font-weight: 500")
(text "{{ question.content|markdown|safe }}"))
; question drawings
(text "{{ self::post_media(upload_ids=question.drawings) }}")
; anonymous user ip thing
; this is only shown if the post author is anonymous AND we are a helper
(text "{% if is_helper and owner.id == 0 %}")
@ -693,7 +695,7 @@
(div
("class" "flex gap-2 items-center justify-between"))))
(text "{%- endmacro %} {% macro create_question_form(receiver=\"0\", community=\"\", header=\"\", is_global=false) -%}")
(text "{%- endmacro %} {% macro create_question_form(receiver=\"0\", community=\"\", header=\"\", is_global=false, drawing_enabled=false) -%}")
(div
("class" "card-nest")
(div
@ -707,6 +709,12 @@
("onsubmit" "create_question_from_form(event)")
(div
("class" "flex flex-col gap-1")
; carp canvas
(text "{% if drawing_enabled -%}")
(div ("ui_ident" "carp_canvas_field"))
(text "{%- endif %}")
; form
(label
("for" "content")
(text "{{ text \"communities:label.content\" }}"))
@ -718,25 +726,83 @@
("required" "")
("minlength" "2")
("maxlength" "4096")))
(button
("class" "primary")
(text "{{ text \"communities:action.create\" }}"))))
(div
("class" "flex gap-2")
(button
("class" "primary")
(text "{{ text \"communities:action.create\" }}"))
(text "{% if drawing_enabled -%}")
(button
("class" "lowered")
("ui_ident" "add_drawing")
("onclick" "attach_drawing()")
("type" "button")
(text "{{ text \"communities:action.draw\" }}"))
(button
("class" "lowered red hidden")
("ui_ident" "remove_drawing")
("onclick" "remove_drawing()")
("type" "button")
(text "{{ text \"communities:action.remove_drawing\" }}"))
(script
(text "globalThis.attach_drawing = () => {
globalThis.gerald = trigger(\"carp::new\", [document.querySelector(\"[ui_ident=carp_canvas_field]\")]);
globalThis.gerald.create_canvas();
document.querySelector(\"[ui_ident=add_drawing]\").classList.add(\"hidden\");
document.querySelector(\"[ui_ident=remove_drawing]\").classList.remove(\"hidden\");
}
globalThis.remove_drawing = async () => {
if (
!(await trigger(\"atto::confirm\", [
\"Are you sure you would like to do this?\",
]))
) {
return;
}
document.querySelector(\"[ui_ident=carp_canvas_field]\").innerHTML = \"\";
globalThis.gerald = null;
document.querySelector(\"[ui_ident=add_drawing]\").classList.remove(\"hidden\");
document.querySelector(\"[ui_ident=remove_drawing]\").classList.add(\"hidden\");
}"))
(text "{%- endif %}"))))
(script
(text "async function create_question_from_form(e) {
(text "globalThis.gerald = null;
async function create_question_from_form(e) {
e.preventDefault();
await trigger(\"atto::debounce\", [\"questions::create\"]);
fetch(\"/api/v1/questions\", {
method: \"POST\",
headers: {
\"Content-Type\": \"application/json\",
},
body: JSON.stringify({
// create body
const body = new FormData();
if (globalThis.gerald) {
body.append(\"drawing.carpgraph\", new Blob([new Uint8Array(globalThis.gerald.as_carp2())], {
type: \"application/octet-stream\"
}));
}
body.append(
\"body\",
JSON.stringify({
content: e.target.content.value,
receiver: \"{{ receiver }}\",
community: \"{{ community }}\",
is_global: \"{{ is_global }}\" == \"true\",
}),
);
// ...
fetch(\"/api/v1/questions\", {
method: \"POST\",
body,
})
.then((res) => res.json())
.then((res) => {
@ -747,6 +813,10 @@
if (res.ok) {
e.target.reset();
if (globalThis.gerald) {
globalThis.gerald.clear();
}
}
});
}"))

View file

@ -276,7 +276,7 @@
; init codemirror
(script ("id" "editor_content") ("type" "text/markdown") (text "{{ note.content|remove_script_tags|safe }}"))
(script
(text "setTimeout(() => {
(text "setTimeout(async () => {
if (!document.getElementById(\"preview_tab\").shadowRoot) {
document.getElementById(\"preview_tab\").attachShadow({ mode: \"open\" });
}
@ -335,6 +335,7 @@
const preview_token = window.crypto.randomUUID();
document.getElementById(\"preview_tab\").shadowRoot.innerHTML = `${res}<style>
@import url(\"/css/style.css\");
@import url(\"/api/v1/journals/{{ journal.id }}/journal.css?v=preview-${preview_token}\");
</style>`;
trigger(\"atto::hooks::tabs:switch\", [\"preview\"]);

View file

@ -1,7 +1,7 @@
(text "{% extends \"profile/base.html\" %} {% block content %} {% if profile.settings.enable_questions and (user or profile.settings.allow_anonymous_questions) %}")
(div
("style" "display: contents")
(text "{{ components::create_question_form(receiver=profile.id, header=profile.settings.motivational_header) }}"))
(text "{{ components::create_question_form(receiver=profile.id, header=profile.settings.motivational_header, drawing_enabled=profile.settings.enable_drawings) }}"))
(text "{%- endif %} {{ macros::profile_nav(selected=\"media\") }}")
(div

View file

@ -1,7 +1,7 @@
(text "{% extends \"profile/base.html\" %} {% block content %} {% if profile.settings.enable_questions and (user or profile.settings.allow_anonymous_questions) %}")
(div
("style" "display: contents")
(text "{{ components::create_question_form(receiver=profile.id, header=profile.settings.motivational_header) }}"))
(text "{{ components::create_question_form(receiver=profile.id, header=profile.settings.motivational_header, drawing_enabled=profile.settings.enable_drawings) }}"))
(text "{%- endif %} {{ macros::profile_nav(selected=\"outbox\") }}")
(div

View file

@ -1,7 +1,7 @@
(text "{% extends \"profile/base.html\" %} {% block content %} {% if profile.settings.enable_questions and (user or profile.settings.allow_anonymous_questions) %}")
(div
("style" "display: contents")
(text "{{ components::create_question_form(receiver=profile.id, header=profile.settings.motivational_header) }}"))
(text "{{ components::create_question_form(receiver=profile.id, header=profile.settings.motivational_header, drawing_enabled=profile.settings.enable_drawings) }}"))
(text "{%- endif %} {% if not tag and pinned|length != 0 -%}")
(div

View file

@ -1,7 +1,7 @@
(text "{% extends \"profile/base.html\" %} {% block content %} {% if profile.settings.enable_questions and (user or profile.settings.allow_anonymous_questions) %}")
(div
("style" "display: contents")
(text "{{ components::create_question_form(receiver=profile.id, header=profile.settings.motivational_header) }}"))
(text "{{ components::create_question_form(receiver=profile.id, header=profile.settings.motivational_header, drawing_enabled=profile.settings.enable_drawings) }}"))
(text "{%- endif %} {{ macros::profile_nav(selected=\"replies\") }}")
(div

View file

@ -1376,6 +1376,14 @@
\"{{ profile.settings.allow_anonymous_questions }}\",
\"checkbox\",
],
[
[
\"enable_drawings\",
\"Allow users to create drawings and submit them with questions\",
],
\"{{ profile.settings.enable_drawings }}\",
\"checkbox\",
],
[
[\"motivational_header\", \"Motivational header\"],
settings.motivational_header,