1import QuestionRender from "#src/q+a/tags/question.marko";
2import type { ScriptPayload } from "#src/q+a/views/editor.marko";
3
4declare const payload: ScriptPayload;
5const date = new Date(payload.date);
6
7const main = document.getElementById("edit-grid")! as HTMLDivElement;
8const preview = document.getElementById("preview")! as HTMLDivElement;
9const editor = document.getElementById("editor") as HTMLTextAreaElement;
10
11async function updatePreview(text: string) {
12 preview.innerHTML = await QuestionRender.render({
13 question: {
14 id: payload.id,
15 qmid: payload.qmid,
16 text: text,
17 type: payload.type,
18 date,
19 },
20 editor: true,
21 });
22}
23updatePreview(payload.text);
24
25editor.value = payload.text;
26editor.addEventListener("input", () => {
27 updatePreview(editor.value);
28});
29editor.focus();
30
31(globalThis as any).onCommitQuestion = wrapAction(async () => {
32 const text = editor.value;
33 const res = await fetch(`/admin/q+a/${payload.id}`, {
34 method: "PATCH",
35 headers: {
36 Accept: "application/json",
37 "Content-Type": "application/json",
38 },
39 body: JSON.stringify({
40 text,
41 type: payload.type,
42 }),
43 });
44 if (!res.ok) {
45 throw new Error("Failed to update question, status: " + res.status);
46 }
47 if (location.search.includes("return=inbox")) {
48 location.href = "/admin/q+a/inbox";
49 } else {
50 location.href = "/q+a#q" + payload.id;
51 }
52});
53(globalThis as any).onDelete = wrapAction(async () => {
54 if (confirm("Are you sure you want to delete this question?")) {
55 const res = await fetch(`/admin/q+a/${payload.id}`, {
56 method: "DELETE",
57 headers: {
58 Accept: "application/json",
59 },
60 });
61 if (!res.ok) {
62 throw new Error("Failed to delete question, status: " + res.status);
63 }
64 location.href = document.referrer || "/admin/q+a";
65 }
66});
67(globalThis as any).onTypeChange = () => {
68 payload.type = (document.getElementById("type") as HTMLSelectElement).value as ScriptPayload["type"];
69 updatePreview(view.state.doc.toString());
70};
71
72function wrapAction(cb: () => Promise<void>) {
73 return async () => {
74 main.style.opacity = "0.5";
75 main.style.pointerEvents = "none";
76 const inputs = main.querySelectorAll(
77 "button,select,input",
78 ) as NodeListOf<HTMLButtonElement>;
79 inputs.forEach((b) => {
80 b.disabled = true;
81 });
82 try {
83 await cb();
84 } catch (e: any) {
85 main.style.opacity = "1";
86 main.style.pointerEvents = "auto";
87 inputs.forEach((b) => {
88 b.disabled = false;
89 });
90 alert(e.message);
91 }
92 };
93}