import "@logseq/libs"; import { BlockEntity } from "@logseq/libs/dist/LSPlugin.user"; const endpoint = 'http://localhost:3000/quizzes'; const uniqueIdentifier = () => Math.random() .toString(36) .replace(/[^a-z]+/g, ""); const sanitizeBlockContent = (text: string) => text.replace(/((?<=::).*|.*::)/g, "").replace(/{.*}/, "").trim() async function fetchQuizzes() { const { status: status, content: quizzes } = await fetch(endpoint).then(res => res.json()) const ret = quizzes || [] return ret.map((quiz, i) => { return `${i + 1}. ${quiz.Question.Text}` }) } const render = (id, slot, status: ("modified" | "saved" | "error")) => { logseq.provideUI({ key: `${id}`, slot, reset: true, template: ` ${status === 'saved' ? 'saved' : ''} `, }); } const main = () => { console.log("logseq-probo-plugin LOADED!"); logseq.Editor.registerSlashCommand("Get All Quizzes", async () => { const currBlock = await logseq.Editor.getCurrentBlock(); let blocks = await fetchQuizzes() blocks = blocks.map((it: BlockEntity) => ({ content: it })) await logseq.Editor.insertBatchBlock(currBlock.uuid, blocks, { sibling: false }) }); logseq.Editor.registerSlashCommand("Create a new Probo quiz", async () => { await logseq.Editor.insertAtEditingCursor( `{{renderer :probo_${uniqueIdentifier()}}}` ); }); logseq.App.onMacroRendererSlotted(async ({ slot, payload }) => { const [type] = payload.arguments; if (!type.startsWith(":probo")) return const id = type.split("_")[1]?.trim(); const proboId = `probo_${id}`; let status: ("modified" | "saved" | "error") logseq.provideModel({ async createOrUpdateQuiz() { const parentBlock = await logseq.Editor.getBlock(payload.uuid, { includeChildren: true }); const answers = parentBlock.children.map((answer: BlockEntity, i: number) => { return { text: answer.content, correct: (i == 0) ? true : false } }) const quiz = { question: { text: sanitizeBlockContent(parentBlock.content) }, answers: answers } if (parentBlock.properties.proboQuizUuid) { const res = await fetch(endpoint + `/update/${parentBlock.properties.proboQuizUuid}`, { method: 'PUT', body: JSON.stringify(quiz) }) const data = await res.json(); await logseq.Editor.upsertBlockProperty(parentBlock.uuid, `probo-quiz-uuid`, data.content.ID) render(proboId, slot, "saved") } else { const res = await fetch(endpoint + '/create', { method: 'POST', body: JSON.stringify(quiz) }) const data = await res.json(); await logseq.Editor.upsertBlockProperty(parentBlock.uuid, `probo-quiz-uuid`, data.content.ID) render(proboId, slot, "saved") } } }); logseq.provideStyle(` .renderBtn { border: 1px solid white; border-radius: 8px; padding: 5px; margin-right: 5px; font-size: 80%; background-color: black; color: white; } .renderBtn:hover { background-color: white; color: black; } `); logseq.provideUI({ key: `${proboId}`, slot, reset: true, template: ``, }); }); }; logseq.ready(main).catch(console.error);