A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 142 lines 6.0 kB view raw
1import {Menu} from "../../../plugin/Menu"; 2import {getColIconByType} from "./col"; 3import {transaction} from "../../wysiwyg/transaction"; 4import {setPosition} from "../../../util/setPosition"; 5import {unicode2Emoji} from "../../../emoji"; 6import {getFieldsByData} from "./view"; 7import {Constants} from "../../../constants"; 8 9export const addSort = (options: { 10 data: IAV, 11 rect: DOMRect, 12 menuElement: HTMLElement, 13 tabRect: DOMRect, 14 avId: string, 15 protyle: IProtyle, 16 blockID: string, 17}) => { 18 const menu = new Menu(Constants.MENU_AV_ADD_SORT); 19 const fields = getFieldsByData(options.data); 20 fields.forEach((column) => { 21 let hasSort = false; 22 23 // 如果该列是行号类型列,不允许添加排序 24 if (column.type === "lineNumber") { 25 hasSort = true; 26 } else { 27 options.data.view.sorts.find((sort) => { 28 if (sort.column === column.id) { 29 hasSort = true; 30 return true; 31 } 32 }); 33 } 34 35 if (!hasSort) { 36 menu.addItem({ 37 label: column.name, 38 iconHTML: column.icon ? unicode2Emoji(column.icon, "b3-menu__icon", true) : `<svg class="b3-menu__icon"><use xlink:href="#${getColIconByType(column.type)}"></use></svg>`, 39 click: () => { 40 const oldSorts = Object.assign([], options.data.view.sorts); 41 options.data.view.sorts.push({ 42 column: column.id, 43 order: "ASC", 44 }); 45 transaction(options.protyle, [{ 46 action: "setAttrViewSorts", 47 avID: options.data.id, 48 data: options.data.view.sorts, 49 blockID: options.blockID, 50 }], [{ 51 action: "setAttrViewSorts", 52 avID: options.data.id, 53 data: oldSorts, 54 blockID: options.blockID, 55 }]); 56 options.menuElement.innerHTML = getSortsHTML(fields, options.data.view.sorts); 57 bindSortsEvent(options.protyle, options.menuElement, options.data, options.blockID); 58 setPosition(options.menuElement, options.tabRect.right - options.menuElement.clientWidth, options.tabRect.bottom, options.tabRect.height); 59 } 60 }); 61 } 62 }); 63 menu.open({ 64 x: options.rect.left, 65 y: options.rect.bottom, 66 h: options.rect.height, 67 }); 68}; 69 70export const bindSortsEvent = (protyle: IProtyle, menuElement: HTMLElement, data: IAV, blockID: string) => { 71 menuElement.querySelectorAll("select").forEach((item: HTMLSelectElement) => { 72 item.addEventListener("change", () => { 73 const colId = item.parentElement.getAttribute("data-id"); 74 const oldSort = JSON.parse(JSON.stringify(data.view.sorts)); 75 if (item.previousElementSibling.classList.contains("b3-menu__icon")) { 76 data.view.sorts.find((sort: IAVSort) => { 77 if (sort.column === colId) { 78 sort.column = item.value; 79 item.parentElement.setAttribute("data-id", item.value); 80 return true; 81 } 82 }); 83 } else { 84 data.view.sorts.find((sort: IAVSort) => sort.column === colId).order = item.value as "ASC" | "DESC"; 85 } 86 transaction(protyle, [{ 87 action: "setAttrViewSorts", 88 avID: data.id, 89 data: data.view.sorts, 90 blockID 91 }], [{ 92 action: "setAttrViewSorts", 93 avID: data.id, 94 data: oldSort, 95 blockID 96 }]); 97 }); 98 }); 99}; 100 101export const getSortsHTML = (columns: IAVColumn[], sorts: IAVSort[]) => { 102 let html = ""; 103 const genSortItem = (id: string) => { 104 let sortHTML = ""; 105 columns.forEach((item) => { 106 sortHTML += `<option value="${item.id}" ${item.id === id ? "selected" : ""}>${item.icon && unicode2Emoji(item.icon)}${item.name}</option>`; 107 }); 108 return sortHTML; 109 }; 110 sorts.forEach((item: IAVSort) => { 111 html += `<button draggable="true" class="b3-menu__item" data-id="${item.column}"> 112 <svg class="b3-menu__icon fn__grab"><use xlink:href="#iconDrag"></use></svg> 113 <select class="b3-select fn__flex-1" style="margin: 4px 0"> 114 ${genSortItem(item.column)} 115 </select> 116 <span class="fn__space"></span> 117 <select class="b3-select" style="margin: 4px 0"> 118 <option value="ASC" ${item.order === "ASC" ? "selected" : ""}>${window.siyuan.languages.asc}</option> 119 <option value="DESC" ${item.order === "DESC" ? "selected" : ""}>${window.siyuan.languages.desc}</option> 120 </select> 121 <svg class="b3-menu__action" data-type="removeSort"><use xlink:href="#iconTrashcan"></use></svg> 122</button>`; 123 }); 124 return `<div class="b3-menu__items"> 125<button class="b3-menu__item" data-type="nobg"> 126 <span class="block__icon" style="padding: 8px;margin-left: -4px;" data-type="go-config"> 127 <svg><use xlink:href="#iconLeft"></use></svg> 128 </span> 129 <span class="b3-menu__label ft__center">${window.siyuan.languages.sort}</span> 130</button> 131<button class="b3-menu__separator"></button> 132${html} 133<button class="b3-menu__item${sorts.length === columns.length ? " fn__none" : ""}" data-type="addSort"> 134 <svg class="b3-menu__icon"><use xlink:href="#iconAdd"></use></svg> 135 <span class="b3-menu__label">${window.siyuan.languages.addSort}</span> 136</button> 137<button class="b3-menu__item b3-menu__item--warning${html ? "" : " fn__none"}" data-type="removeSorts"> 138 <svg class="b3-menu__icon"><use xlink:href="#iconTrashcan"></use></svg> 139 <span class="b3-menu__label">${window.siyuan.languages.removeSorts}</span> 140</button> 141</div>`; 142};