A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 215 lines 10 kB view raw
1import {fetchPost} from "../util/fetch"; 2import {Dialog} from "../dialog"; 3import {isMobile} from "../util/functions"; 4import {hideMessage, showMessage} from "../dialog/message"; 5import {confirmDialog} from "../dialog/confirmDialog"; 6import {hideElements} from "../protyle/ui/hideElements"; 7import {viewCards} from "./viewCards"; 8import {Constants} from "../constants"; 9import {escapeAttr, escapeHtml} from "../util/escape"; 10import {transaction} from "../protyle/wysiwyg/transaction"; 11import {App} from "../index"; 12 13export const genCardItem = (item: ICardPackage) => { 14 return `<li data-id="${item.id}" data-name="${escapeAttr(item.name)}" class="b3-list-item b3-list-item--narrow${isMobile() ? "" : " b3-list-item--hide-action"}"> 15<span class="b3-list-item__text"> 16 <span>${escapeHtml(item.name)}</span> 17 <span class="b3-list-item__meta">${item.size}</span> 18</span> 19<span data-type="rename" class="b3-list-item__action b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.rename}"> 20 <svg><use xlink:href="#iconEdit"></use></svg> 21</span> 22<span data-type="delete" class="b3-list-item__action b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.delete}"> 23 <svg><use xlink:href="#iconTrashcan"></use></svg> 24</span> 25<span data-type="view" class="b3-list-item__action b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.cardPreview}"> 26 <svg><use xlink:href="#iconEye"></use></svg> 27</span> 28<span data-type="remove" class="b3-list-item__action b3-list-item__action--warning b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.removeDeck}"> 29 <svg><use xlink:href="#iconMin"></use></svg> 30</span> 31<span data-type="add" style="display: flex" class="b3-list-item__action b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.addDeck}"> 32 <svg><use xlink:href="#iconAdd"></use></svg> 33</span> 34<span class="b3-list-item__meta${isMobile() ? " fn__none" : ""}">${item.updated}</span> 35</li>`; 36}; 37 38export const makeCard = (app: App, ids: string[]) => { 39 window.siyuan.dialogs.find(item => { 40 if (item.element.getAttribute("data-key") === Constants.DIALOG_MAKECARD) { 41 hideElements(["dialog"]); 42 return true; 43 } 44 }); 45 fetchPost("/api/riff/getRiffDecks", {}, (response) => { 46 let html = ""; 47 response.data.forEach((item: ICardPackage) => { 48 html += genCardItem(item); 49 }); 50 const dialog = new Dialog({ 51 positionId: Constants.DIALOG_MAKECARD, 52 width: isMobile() ? "92vw" : "50vw", 53 height: "70vh", 54 title: window.siyuan.languages.riffCard, 55 content: `<div class="b3-dialog__content fn__flex-column" style="box-sizing: border-box;height: 100%"> 56 <div class="fn__flex"> 57 <input class="b3-text-field fn__flex-1"> 58 <span class="fn__space"></span> 59 <span data-type="create" class="block__icon block__icon--show b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.createDeck}"> 60 <svg><use xlink:href="#iconAdd"></use></svg> 61 </span> 62 <span class="fn__space"></span> 63 <span data-type="viewall" class="block__icon block__icon--show b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.cardPreview}"> 64 <svg><use xlink:href="#iconEye"></use></svg> 65 </span> 66 </div> 67 <div class="fn__hr"></div> 68 <ul class="b3-list b3-list--background fn__flex-1">${html}</ul> 69</div>`, 70 }); 71 dialog.element.setAttribute("data-key", Constants.DIALOG_MAKECARD); 72 dialog.element.addEventListener("click", (event) => { 73 let target = event.target as HTMLElement; 74 while (target && target !== dialog.element) { 75 const type = target.getAttribute("data-type"); 76 if (type === "create") { 77 let msgId = ""; 78 const inputElement = dialog.element.querySelector(".b3-text-field") as HTMLInputElement; 79 if (inputElement.value) { 80 if (msgId) { 81 hideMessage(msgId); 82 } 83 fetchPost("/api/riff/createRiffDeck", {name: inputElement.value}, (response) => { 84 dialog.element.querySelector(".b3-list").insertAdjacentHTML("afterbegin", genCardItem(response.data)); 85 inputElement.value = ""; 86 }); 87 } else { 88 msgId = showMessage(window.siyuan.languages._kernel[142]); 89 inputElement.focus(); 90 } 91 event.stopPropagation(); 92 event.preventDefault(); 93 break; 94 } else if (type === "add") { 95 fetchPost("/api/riff/addRiffCards", { 96 deckID: target.parentElement.getAttribute("data-id"), 97 blockIDs: ids 98 }, (addResponse) => { 99 target.parentElement.outerHTML = genCardItem(addResponse.data); 100 }); 101 event.stopPropagation(); 102 event.preventDefault(); 103 break; 104 } else if (type === "remove") { 105 fetchPost("/api/riff/removeRiffCards", { 106 deckID: target.parentElement.getAttribute("data-id"), 107 blockIDs: ids 108 }, (removeResponse) => { 109 target.parentElement.outerHTML = genCardItem(removeResponse.data); 110 }); 111 event.stopPropagation(); 112 event.preventDefault(); 113 break; 114 } else if (type === "delete") { 115 confirmDialog(window.siyuan.languages.deleteOpConfirm, `${window.siyuan.languages.confirmDelete} <b>${escapeHtml(target.parentElement.getAttribute("data-name"))}</b>?`, () => { 116 fetchPost("/api/riff/removeRiffDeck", { 117 deckID: target.parentElement.getAttribute("data-id"), 118 }, () => { 119 target.parentElement.remove(); 120 }); 121 }, undefined, true); 122 event.stopPropagation(); 123 event.preventDefault(); 124 break; 125 } else if (type === "view") { 126 viewCards(app, target.parentElement.getAttribute("data-id"), target.parentElement.getAttribute("data-name"), "", (removeResponse) => { 127 target.parentElement.outerHTML = genCardItem(removeResponse.data); 128 }); 129 event.stopPropagation(); 130 event.preventDefault(); 131 break; 132 } else if (type === "viewall") { 133 viewCards(app, "", window.siyuan.languages.all, ""); 134 event.stopPropagation(); 135 event.preventDefault(); 136 break; 137 } else if (type === "rename") { 138 const renameDialog = new Dialog({ 139 title: window.siyuan.languages.rename, 140 content: `<div class="b3-dialog__content"><input class="b3-text-field fn__block" value=""></div> 141<div class="b3-dialog__action"> 142 <button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div> 143 <button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button> 144</div>`, 145 width: isMobile() ? "92vw" : "520px", 146 }); 147 const inputElement = renameDialog.element.querySelector("input") as HTMLInputElement; 148 const btnsElement = renameDialog.element.querySelectorAll(".b3-button"); 149 renameDialog.bindInput(inputElement, () => { 150 (btnsElement[1] as HTMLButtonElement).click(); 151 }); 152 inputElement.value = target.parentElement.getAttribute("data-name"); 153 inputElement.focus(); 154 inputElement.select(); 155 btnsElement[0].addEventListener("click", () => { 156 renameDialog.destroy(); 157 }); 158 btnsElement[1].addEventListener("click", () => { 159 fetchPost("/api/riff/renameRiffDeck", { 160 name: inputElement.value, 161 deckID: target.parentElement.getAttribute("data-id"), 162 }, () => { 163 target.parentElement.querySelector(".b3-list-item__text span").textContent = inputElement.value; 164 target.parentElement.setAttribute("data-name", inputElement.value); 165 }); 166 renameDialog.destroy(); 167 }); 168 event.stopPropagation(); 169 event.preventDefault(); 170 break; 171 } 172 target = target.parentElement; 173 } 174 }); 175 }); 176}; 177 178export const quickMakeCard = (protyle: IProtyle, nodeElement: Element[]) => { 179 let isRemove = true; 180 const ids: string[] = []; 181 nodeElement.forEach(item => { 182 if (item.getAttribute("data-type") === "NodeThematicBreak") { 183 return; 184 } 185 item.classList.remove("protyle-wysiwyg--select"); 186 ids.push(item.getAttribute("data-node-id")); 187 if ((item.getAttribute(Constants.CUSTOM_RIFF_DECKS) || "").indexOf(Constants.QUICK_DECK_ID) === -1) { 188 isRemove = false; 189 } 190 }); 191 if (isRemove) { 192 transaction(protyle, [{ 193 action: "removeFlashcards", 194 deckID: Constants.QUICK_DECK_ID, 195 blockIDs: ids 196 }], [{ 197 action: "addFlashcards", 198 deckID: Constants.QUICK_DECK_ID, 199 blockIDs: ids 200 }]); 201 } else { 202 transaction(protyle, [{ 203 action: "addFlashcards", 204 deckID: Constants.QUICK_DECK_ID, 205 blockIDs: ids 206 }], [{ 207 action: "removeFlashcards", 208 deckID: Constants.QUICK_DECK_ID, 209 blockIDs: ids 210 }]); 211 } 212}; 213 214 215