A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 1746 lines 88 kB view raw
1import {transaction} from "../../wysiwyg/transaction"; 2import {fetchPost} from "../../../util/fetch"; 3import { 4 addCol, 5 bindEditEvent, 6 duplicateCol, 7 getColIconByType, 8 getColId, 9 getColNameByType, 10 getEditHTML, 11 removeCol 12} from "./col"; 13import {setPosition} from "../../../util/setPosition"; 14import {hasClosestByAttribute, hasClosestByClassName} from "../../util/hasClosest"; 15import {addColOptionOrCell, bindSelectEvent, getSelectHTML, removeCellOption, setColOption} from "./select"; 16import {addFilter, getFiltersHTML, setFilter} from "./filter"; 17import {addSort, bindSortsEvent, getSortsHTML} from "./sort"; 18import {bindDateEvent, getDateHTML} from "./date"; 19import {formatNumber} from "./number"; 20import {updateAttrViewCellAnimation} from "./action"; 21import {addAssetLink, bindAssetEvent, editAssetItem, getAssetHTML, updateAssetCell} from "./asset"; 22import {Constants} from "../../../constants"; 23import {hideElements} from "../../ui/hideElements"; 24import {isLocalPath, pathPosix} from "../../../util/pathName"; 25import {openEmojiPanel, unicode2Emoji} from "../../../emoji"; 26import {getSearch, isMobile} from "../../../util/functions"; 27/// #if !MOBILE 28import {openAsset} from "../../../editor/util"; 29/// #endif 30import {previewAttrViewImages} from "../../preview/image"; 31import {assetMenu} from "../../../menus/protyle"; 32import { 33 addView, 34 bindSwitcherEvent, 35 bindViewEvent, 36 getFieldsByData, 37 getSwitcherHTML, 38 getViewHTML, 39 openViewMenu 40} from "./view"; 41import {focusBlock} from "../../util/selection"; 42import {getFieldIdByCellElement, setPageSize} from "./row"; 43import {bindRelationEvent, getRelationHTML, openSearchAV, setRelationCell, updateRelation} from "./relation"; 44import {bindRollupData, getRollupHTML, goSearchRollupCol} from "./rollup"; 45import {updateCellsValue} from "./cell"; 46import {openCalcMenu} from "./calc"; 47import {escapeAttr, escapeHtml} from "../../../util/escape"; 48import {Dialog} from "../../../dialog"; 49import {bindLayoutEvent, getLayoutHTML, updateLayout} from "./layout"; 50import {setGalleryCover, setGalleryRatio, setGallerySize} from "./gallery/util"; 51import { 52 bindGroupsEvent, bindGroupsNumber, 53 getGroupsHTML, 54 getGroupsMethodHTML, getGroupsNumberHTML, getLanguageByIndex, getPageSize, 55 goGroupsDate, 56 goGroupsSort, 57 setGroupMethod 58} from "./groups"; 59 60export const openMenuPanel = (options: { 61 protyle: IProtyle, 62 blockElement: Element, 63 type: "select" | "properties" | "config" | "sorts" | "filters" | "edit" | "date" | "asset" | "switcher" | "relation" | "rollup", 64 colId?: string, // for edit, rollup 65 // 使用前端构造的数据 66 editData?: { 67 previousID: string, 68 colData: IAVColumn, 69 }, 70 cellElements?: HTMLElement[], // for select & date & relation & asset 71 cb?: (avPanelElement: Element) => void 72}) => { 73 let avPanelElement = document.querySelector(".av__panel"); 74 if (avPanelElement) { 75 avPanelElement.remove(); 76 return; 77 } 78 const avID = options.blockElement.getAttribute("data-av-id"); 79 const avPageSize = getPageSize(options.blockElement); 80 fetchPost("/api/av/renderAttributeView", { 81 id: avID, 82 query: (options.blockElement.querySelector('[data-type="av-search"]') as HTMLInputElement)?.value.trim() || "", 83 pageSize: avPageSize.unGroupPageSize, 84 groupPaging: avPageSize.groupPageSize, 85 viewID: options.blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW) 86 }, (response) => { 87 avPanelElement = document.querySelector(".av__panel"); 88 if (avPanelElement) { 89 avPanelElement.remove(); 90 return; 91 } 92 window.siyuan.menus.menu.remove(); 93 const blockID = options.blockElement.getAttribute("data-node-id"); 94 95 const isCustomAttr = !options.blockElement.classList.contains("av"); 96 let data = response.data as IAV; 97 let html; 98 let fields = getFieldsByData(data); 99 if (options.type === "config") { 100 html = getViewHTML(data); 101 } else if (options.type === "properties") { 102 html = getPropertiesHTML(fields); 103 } else if (options.type === "sorts") { 104 html = getSortsHTML(fields, data.view.sorts); 105 } else if (options.type === "switcher") { 106 html = getSwitcherHTML(data.views, data.viewID); 107 } else if (options.type === "filters") { 108 html = getFiltersHTML(data); 109 } else if (options.type === "select") { 110 html = getSelectHTML(fields, options.cellElements, true, options.blockElement); 111 } else if (options.type === "asset") { 112 html = getAssetHTML(options.cellElements); 113 } else if (options.type === "edit") { 114 if (options.editData) { 115 if (typeof options.editData.colData.wrap === "undefined") { 116 options.editData.colData.wrap = data.view.wrapField; 117 } 118 if (options.editData.previousID) { 119 fields.find((item, index) => { 120 if (item.id === options.editData.previousID) { 121 fields.splice(index + 1, 0, options.editData.colData); 122 return true; 123 } 124 }); 125 } else { 126 if (data.viewType === "table") { 127 fields.splice(0, 0, options.editData.colData); 128 } else { 129 fields.push(options.editData.colData); 130 } 131 } 132 } 133 html = getEditHTML({protyle: options.protyle, data, colId: options.colId, isCustomAttr}); 134 } else if (options.type === "date") { 135 html = getDateHTML(options.cellElements); 136 } else if (options.type === "rollup") { 137 html = `<div class="b3-menu__items">${getRollupHTML({data, cellElements: options.cellElements})}</div>`; 138 } else if (options.type === "relation") { 139 html = getRelationHTML(data, options.cellElements); 140 if (!html) { 141 openMenuPanel({ 142 protyle: options.protyle, 143 blockElement: options.blockElement, 144 type: "edit", 145 colId: getColId(options.cellElements[0], data.viewType) 146 }); 147 return; 148 } 149 } 150 151 document.body.insertAdjacentHTML("beforeend", `<div class="av__panel" style="z-index: ${++window.siyuan.zIndex};"> 152 <div class="b3-dialog__scrim" data-type="close"></div> 153 <div class="b3-menu" ${["select", "date", "asset", "relation", "rollup"].includes(options.type) ? `style="min-width: 200px;${isMobile() ? "max-width: 90vw;" : "max-width: 50vw;"}"` : ""}>${html}</div> 154</div>`); 155 avPanelElement = document.querySelector(".av__panel"); 156 let closeCB: () => void; 157 const menuElement = avPanelElement.lastElementChild as HTMLElement; 158 let tabRect = options.blockElement.querySelector(`.av__views, .av__row[data-col-id="${options.colId}"] > .block__logo`)?.getBoundingClientRect(); 159 if (["select", "date", "asset", "relation", "rollup"].includes(options.type)) { 160 let lastElement = options.cellElements[options.cellElements.length - 1]; 161 if (!options.blockElement.contains(lastElement)) { 162 // https://github.com/siyuan-note/siyuan/issues/15839 163 const rowID = getFieldIdByCellElement(lastElement, data.viewType); 164 if (data.viewType === "table") { 165 lastElement = options.blockElement.querySelector(`.av__row[data-id="${rowID}"] .av__cell[data-col-id="${lastElement.dataset.colId}"]`); 166 } else { 167 lastElement = options.blockElement.querySelector(`.av__gallery-item[data-id="${rowID}"] .av__cell[data-field-id="${lastElement.dataset.fieldId}"]`); 168 } 169 } 170 const cellRect = (lastElement || options.cellElements[options.cellElements.length - 1]).getBoundingClientRect(); 171 172 if (options.type === "select") { 173 bindSelectEvent(options.protyle, data, menuElement, options.cellElements, options.blockElement); 174 } else if (options.type === "date") { 175 closeCB = bindDateEvent({ 176 protyle: options.protyle, 177 data, 178 menuElement, 179 cellElements: options.cellElements, 180 blockElement: options.blockElement 181 }); 182 } else if (options.type === "asset") { 183 bindAssetEvent({ 184 protyle: options.protyle, 185 menuElement, 186 cellElements: options.cellElements, 187 blockElement: options.blockElement 188 }); 189 setTimeout(() => { 190 setPosition(menuElement, cellRect.left, cellRect.bottom, cellRect.height); 191 }, Constants.TIMEOUT_LOAD); // 等待加载 192 } else if (options.type === "relation") { 193 bindRelationEvent({ 194 menuElement, 195 cellElements: options.cellElements, 196 protyle: options.protyle, 197 blockElement: options.blockElement 198 }); 199 } else if (options.type === "rollup") { 200 bindRollupData({protyle: options.protyle, data, menuElement}); 201 } 202 if (["select", "date", "relation", "rollup"].includes(options.type)) { 203 const inputElement = menuElement.querySelector("input"); 204 if (inputElement) { 205 inputElement.select(); 206 inputElement.focus(); 207 } 208 setPosition(menuElement, cellRect.left, cellRect.bottom, cellRect.height); 209 } 210 } else { 211 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 212 if (options.type === "sorts") { 213 bindSortsEvent(options.protyle, menuElement, data, blockID); 214 } else if (options.type === "edit") { 215 bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr, blockID}); 216 } else if (options.type === "config") { 217 bindViewEvent({protyle: options.protyle, data, menuElement, blockElement: options.blockElement}); 218 } else if (options.type === "switcher") { 219 bindSwitcherEvent({protyle: options.protyle, menuElement, blockElement: options.blockElement}); 220 } 221 } 222 if (options.cb) { 223 options.cb(avPanelElement); 224 } 225 avPanelElement.addEventListener("dragstart", (event: DragEvent) => { 226 window.siyuan.dragElement = event.target as HTMLElement; 227 window.siyuan.dragElement.style.opacity = ".38"; 228 return; 229 }); 230 avPanelElement.addEventListener("drop", (event) => { 231 counter = 0; 232 if (!window.siyuan.dragElement) { 233 event.preventDefault(); 234 event.stopPropagation(); 235 return; 236 } 237 window.siyuan.dragElement.style.opacity = ""; 238 const sourceElement = window.siyuan.dragElement; 239 window.siyuan.dragElement = undefined; 240 if (options.protyle && options.protyle.disabled) { 241 event.preventDefault(); 242 event.stopPropagation(); 243 return; 244 } 245 if (!options.protyle && window.siyuan.config.readonly) { 246 event.preventDefault(); 247 event.stopPropagation(); 248 return; 249 } 250 const targetElement = avPanelElement.querySelector(".dragover__bottom, .dragover__top") as HTMLElement; 251 if (!targetElement) { 252 return; 253 } 254 const isTop = targetElement.classList.contains("dragover__top"); 255 const sourceId = sourceElement.dataset.id; 256 const targetId = targetElement.dataset.id; 257 if (targetElement.querySelector('[data-type="removeSort"]')) { 258 const changeData = data.view.sorts; 259 const oldData = Object.assign([], changeData); 260 let sortFilter: IAVSort; 261 changeData.find((sort, index: number) => { 262 if (sort.column === sourceId) { 263 sortFilter = changeData.splice(index, 1)[0]; 264 return true; 265 } 266 }); 267 changeData.find((sort, index: number) => { 268 if (sort.column === targetId) { 269 if (isTop) { 270 changeData.splice(index, 0, sortFilter); 271 } else { 272 changeData.splice(index + 1, 0, sortFilter); 273 } 274 return true; 275 } 276 }); 277 278 transaction(options.protyle, [{ 279 action: "setAttrViewSorts", 280 avID, 281 data: changeData, 282 blockID 283 }], [{ 284 action: "setAttrViewSorts", 285 avID, 286 data: oldData, 287 blockID 288 }]); 289 menuElement.innerHTML = getSortsHTML(fields, data.view.sorts); 290 bindSortsEvent(options.protyle, menuElement, data, blockID); 291 return; 292 } 293 if (targetElement.querySelector('[data-type="removeFilter"]')) { 294 const changeData = data.view.filters; 295 const oldData = Object.assign([], changeData); 296 let targetFilter: IAVFilter; 297 changeData.find((filter, index: number) => { 298 if (filter.column === sourceId) { 299 targetFilter = changeData.splice(index, 1)[0]; 300 return true; 301 } 302 }); 303 changeData.find((filter, index: number) => { 304 if (filter.column === targetId) { 305 if (isTop) { 306 changeData.splice(index, 0, targetFilter); 307 } else { 308 changeData.splice(index + 1, 0, targetFilter); 309 } 310 return true; 311 } 312 }); 313 314 transaction(options.protyle, [{ 315 action: "setAttrViewFilters", 316 avID, 317 data: changeData, 318 blockID 319 }], [{ 320 action: "setAttrViewFilters", 321 avID, 322 data: oldData, 323 blockID 324 }]); 325 menuElement.innerHTML = getFiltersHTML(data); 326 return; 327 } 328 if (targetElement.querySelector('[data-type="av-view-edit"]')) { 329 transaction(options.protyle, [{ 330 action: "sortAttrViewView", 331 avID, 332 blockID, 333 id: sourceId, 334 previousID: isTop ? targetElement.previousElementSibling?.getAttribute("data-id") : targetElement.getAttribute("data-id") 335 }], [{ 336 action: "sortAttrViewView", 337 avID, 338 blockID, 339 id: sourceId, 340 previousID: sourceElement.previousElementSibling?.getAttribute("data-id") 341 }]); 342 if (isTop) { 343 targetElement.before(sourceElement); 344 targetElement.classList.remove("dragover__top"); 345 } else { 346 targetElement.after(sourceElement); 347 targetElement.classList.remove("dragover__bottom"); 348 } 349 return; 350 } 351 if (targetElement.querySelector('[data-type="editAssetItem"]')) { 352 if (isTop) { 353 targetElement.before(sourceElement); 354 } else { 355 targetElement.after(sourceElement); 356 } 357 const replaceValue: IAVCellAssetValue[] = []; 358 Array.from(targetElement.parentElement.children).forEach((item: HTMLElement) => { 359 if (["image", "file"].includes(item.dataset.type)) { 360 replaceValue.push({ 361 content: item.dataset.content, 362 name: item.dataset.name, 363 type: item.dataset.type as "image" | "file", 364 }); 365 } 366 }); 367 updateAssetCell({ 368 protyle: options.protyle, 369 cellElements: options.cellElements, 370 replaceValue, 371 blockElement: options.blockElement 372 }); 373 return; 374 } 375 if (targetElement.querySelector('[data-type="setColOption"]')) { 376 const colId = options.cellElements ? getColId(options.cellElements[0], data.viewType) : menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id"); 377 const changeData = fields.find((column) => column.id === colId).options; 378 const oldData = Object.assign([], changeData); 379 let targetOption: { name: string, color: string }; 380 changeData.find((option, index: number) => { 381 if (option.name === sourceElement.dataset.name) { 382 targetOption = changeData.splice(index, 1)[0]; 383 return true; 384 } 385 }); 386 changeData.find((option, index: number) => { 387 if (option.name === targetElement.dataset.name) { 388 if (isTop) { 389 changeData.splice(index, 0, targetOption); 390 } else { 391 changeData.splice(index + 1, 0, targetOption); 392 } 393 return true; 394 } 395 }); 396 transaction(options.protyle, [{ 397 action: "updateAttrViewColOptions", 398 id: colId, 399 avID, 400 data: changeData, 401 }], [{ 402 action: "updateAttrViewColOptions", 403 id: colId, 404 avID, 405 data: oldData, 406 }]); 407 const oldScroll = menuElement.querySelector(".b3-menu__items").scrollTop; 408 if (options.cellElements) { 409 menuElement.innerHTML = getSelectHTML(fields, options.cellElements, false, options.blockElement); 410 bindSelectEvent(options.protyle, data, menuElement, options.cellElements, options.blockElement); 411 } else { 412 menuElement.innerHTML = getEditHTML({ 413 protyle: options.protyle, 414 data, 415 colId, 416 isCustomAttr 417 }); 418 bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr, blockID}); 419 } 420 menuElement.querySelector(".b3-menu__items").scrollTop = oldScroll; 421 return; 422 } 423 if (targetElement.getAttribute("data-type") === "setRelationCell") { 424 if (isTop) { 425 targetElement.before(sourceElement); 426 } else { 427 targetElement.after(sourceElement); 428 } 429 targetElement.classList.remove("dragover__bottom", "dragover__top"); 430 const blockIDs: string[] = []; 431 const contents: IAVCellValue[] = []; 432 targetElement.parentElement.querySelectorAll(".fn__grab").forEach(item => { 433 const dateElement = item.nextElementSibling as HTMLElement; 434 blockIDs.push(dateElement.parentElement.dataset.rowId); 435 contents.push({ 436 isDetached: !dateElement.style.color, 437 type: "block", 438 block: { 439 content: dateElement.textContent, 440 id: dateElement.dataset.id 441 } 442 }); 443 }); 444 updateCellsValue(options.protyle, options.blockElement as HTMLElement, { 445 blockIDs, 446 contents, 447 }, options.cellElements); 448 return; 449 } 450 if (targetElement.getAttribute("data-type") === "editCol") { 451 const previousID = (isTop ? targetElement.previousElementSibling?.getAttribute("data-id") : targetElement.getAttribute("data-id")) || ""; 452 const undoPreviousID = sourceElement.previousElementSibling?.getAttribute("data-id") || ""; 453 if (previousID !== undoPreviousID && previousID !== sourceId) { 454 transaction(options.protyle, [{ 455 action: "sortAttrViewCol", 456 avID, 457 previousID, 458 id: sourceId, 459 blockID, 460 }], [{ 461 action: "sortAttrViewCol", 462 avID, 463 previousID: undoPreviousID, 464 id: sourceId, 465 blockID 466 }]); 467 let column: IAVColumn; 468 fields.find((item, index: number) => { 469 if (item.id === sourceId) { 470 column = fields.splice(index, 1)[0]; 471 return true; 472 } 473 }); 474 fields.find((item, index: number) => { 475 if (item.id === targetId) { 476 if (isTop) { 477 fields.splice(index, 0, column); 478 } else { 479 fields.splice(index + 1, 0, column); 480 } 481 return true; 482 } 483 }); 484 } 485 menuElement.innerHTML = getPropertiesHTML(fields); 486 return; 487 } 488 if (targetElement.querySelector('[data-type="hideGroup"]')) { 489 const previousID = (isTop ? targetElement.previousElementSibling?.getAttribute("data-id") : targetElement.getAttribute("data-id")) || ""; 490 const undoPreviousID = sourceElement.previousElementSibling?.getAttribute("data-id") || ""; 491 if (previousID !== undoPreviousID && previousID !== sourceId) { 492 transaction(options.protyle, [{ 493 action: "sortAttrViewGroup", 494 avID, 495 blockID, 496 previousID, 497 id: sourceId, 498 }], [{ 499 action: "sortAttrViewGroup", 500 avID, 501 blockID, 502 previousID: undoPreviousID, 503 id: sourceId, 504 }]); 505 menuElement.querySelector('[data-type="goGroupsSort"] .b3-menu__accelerator').textContent = getLanguageByIndex(2, "sort"); 506 data.view.group.order = 2; 507 data.view.groups.find((group, index) => { 508 if (group.id === sourceId) { 509 const groupData = data.view.groups.splice(index, 1)[0]; 510 data.view.groups.find((item, index: number) => { 511 if (item.id === targetId) { 512 if (isTop) { 513 data.view.groups.splice(index, 0, groupData); 514 } else { 515 data.view.groups.splice(index + 1, 0, groupData); 516 } 517 return true; 518 } 519 }); 520 return true; 521 } 522 }); 523 if (isTop) { 524 targetElement.before(sourceElement); 525 } else { 526 targetElement.after(sourceElement); 527 } 528 } 529 targetElement.classList.remove("dragover__top", "dragover__bottom"); 530 return; 531 } 532 }); 533 let dragoverElement: HTMLElement; 534 avPanelElement.addEventListener("dragover", (event: DragEvent) => { 535 if (event.dataTransfer.types.includes("Files")) { 536 event.preventDefault(); 537 return; 538 } 539 const target = event.target as HTMLElement; 540 let targetElement = hasClosestByAttribute(target, "draggable", "true"); 541 if (!targetElement) { 542 targetElement = hasClosestByAttribute(document.elementFromPoint(event.clientX, event.clientY - 1), "draggable", "true"); 543 } 544 if (!targetElement || targetElement === window.siyuan.dragElement) { 545 return; 546 } 547 event.preventDefault(); 548 if (dragoverElement && targetElement === dragoverElement) { 549 const nodeRect = targetElement.getBoundingClientRect(); 550 avPanelElement.querySelectorAll(".dragover__bottom, .dragover__top").forEach((item: HTMLElement) => { 551 item.classList.remove("dragover__bottom", "dragover__top"); 552 }); 553 if (event.clientY > nodeRect.top + nodeRect.height / 2) { 554 targetElement.classList.add("dragover__bottom"); 555 } else { 556 targetElement.classList.add("dragover__top"); 557 } 558 return; 559 } 560 dragoverElement = targetElement; 561 }); 562 let counter = 0; 563 avPanelElement.addEventListener("dragleave", () => { 564 counter--; 565 if (counter === 0) { 566 avPanelElement.querySelectorAll(".dragover__bottom, .dragover__top").forEach((item: HTMLElement) => { 567 item.classList.remove("dragover__bottom", "dragover__top"); 568 }); 569 } 570 }); 571 avPanelElement.addEventListener("dragenter", (event) => { 572 event.preventDefault(); 573 counter++; 574 }); 575 avPanelElement.addEventListener("dragend", () => { 576 if (window.siyuan.dragElement) { 577 window.siyuan.dragElement.style.opacity = ""; 578 window.siyuan.dragElement = undefined; 579 } 580 }); 581 avPanelElement.addEventListener("mousedown", (event: MouseEvent & { target: HTMLElement }) => { 582 if (event.button === 1 && !hasClosestByClassName(event.target, "b3-menu")) { 583 document.querySelector(".av__panel").dispatchEvent(new CustomEvent("click", {detail: "close"})); 584 } 585 }); 586 avPanelElement.addEventListener("click", async (event: MouseEvent) => { 587 let type: string; 588 let target = event.target as HTMLElement; 589 if (typeof event.detail === "string") { 590 type = event.detail; 591 } else if (typeof event.detail === "object") { 592 type = (event.detail as { type: string }).type; 593 target = (event.detail as { target: HTMLElement }).target; 594 } 595 while (target && target !== avPanelElement || type) { 596 type = target?.dataset.type || type; 597 if (type === "close") { 598 if (!options.protyle.toolbar.subElement.classList.contains("fn__none")) { 599 // 优先关闭资源文件搜索 600 hideElements(["util"], options.protyle); 601 } else if (!window.siyuan.menus.menu.element.classList.contains("fn__none")) { 602 // 过滤面板先关闭过滤条件 603 window.siyuan.menus.menu.remove(); 604 } else { 605 closeCB?.(); 606 avPanelElement.remove(); 607 focusBlock(options.blockElement); 608 } 609 window.siyuan.menus.menu.remove(); 610 event.preventDefault(); 611 event.stopPropagation(); 612 break; 613 } else if (type === "go-config") { 614 menuElement.innerHTML = getViewHTML(data); 615 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 616 bindViewEvent({protyle: options.protyle, data, menuElement, blockElement: options.blockElement}); 617 window.siyuan.menus.menu.remove(); 618 event.preventDefault(); 619 event.stopPropagation(); 620 break; 621 } else if (type === "go-properties") { 622 // 复制列后点击返回到属性面板,宽度不一致,需重新计算 623 tabRect = options.blockElement.querySelector(".av__views").getBoundingClientRect(); 624 menuElement.innerHTML = getPropertiesHTML(fields); 625 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 626 window.siyuan.menus.menu.remove(); 627 event.preventDefault(); 628 event.stopPropagation(); 629 break; 630 } else if (type === "go-layout") { 631 menuElement.innerHTML = getLayoutHTML(data); 632 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 633 bindLayoutEvent({protyle: options.protyle, data, menuElement, blockElement: options.blockElement}); 634 window.siyuan.menus.menu.remove(); 635 event.preventDefault(); 636 event.stopPropagation(); 637 break; 638 } else if (type === "goSorts") { 639 menuElement.innerHTML = getSortsHTML(fields, data.view.sorts); 640 bindSortsEvent(options.protyle, menuElement, data, blockID); 641 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 642 window.siyuan.menus.menu.remove(); 643 event.preventDefault(); 644 event.stopPropagation(); 645 break; 646 } else if (type === "removeSorts") { 647 transaction(options.protyle, [{ 648 action: "setAttrViewSorts", 649 avID, 650 data: [], 651 blockID 652 }], [{ 653 action: "setAttrViewSorts", 654 avID, 655 data: data.view.sorts, 656 blockID 657 }]); 658 data.view.sorts = []; 659 menuElement.innerHTML = getSortsHTML(fields, data.view.sorts); 660 bindSortsEvent(options.protyle, menuElement, data, blockID); 661 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 662 event.preventDefault(); 663 event.stopPropagation(); 664 break; 665 } else if (type === "addSort") { 666 addSort({ 667 data, 668 rect: target.getBoundingClientRect(), 669 menuElement, 670 tabRect, 671 avId: avID, 672 protyle: options.protyle, 673 blockID, 674 }); 675 event.preventDefault(); 676 event.stopPropagation(); 677 break; 678 } else if (type === "removeSort") { 679 const oldSorts = Object.assign([], data.view.sorts); 680 data.view.sorts.find((item: IAVSort, index: number) => { 681 if (item.column === target.parentElement.dataset.id) { 682 data.view.sorts.splice(index, 1); 683 return true; 684 } 685 }); 686 transaction(options.protyle, [{ 687 action: "setAttrViewSorts", 688 avID, 689 data: data.view.sorts, 690 blockID 691 }], [{ 692 action: "setAttrViewSorts", 693 avID, 694 data: oldSorts, 695 blockID 696 }]); 697 menuElement.innerHTML = getSortsHTML(fields, data.view.sorts); 698 bindSortsEvent(options.protyle, menuElement, data, blockID); 699 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 700 event.preventDefault(); 701 event.stopPropagation(); 702 break; 703 } else if (type === "goFilters") { 704 menuElement.innerHTML = getFiltersHTML(data); 705 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 706 window.siyuan.menus.menu.remove(); 707 event.preventDefault(); 708 event.stopPropagation(); 709 break; 710 } else if (type === "removeFilters") { 711 transaction(options.protyle, [{ 712 action: "setAttrViewFilters", 713 avID, 714 data: [], 715 blockID 716 }], [{ 717 action: "setAttrViewFilters", 718 avID, 719 data: data.view.filters, 720 blockID 721 }]); 722 data.view.filters = []; 723 menuElement.innerHTML = getFiltersHTML(data); 724 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 725 window.siyuan.menus.menu.remove(); 726 event.preventDefault(); 727 event.stopPropagation(); 728 break; 729 } else if (type === "addFilter") { 730 addFilter({ 731 data, 732 rect: target.getBoundingClientRect(), 733 menuElement, 734 tabRect, 735 avId: avID, 736 protyle: options.protyle, 737 blockElement: options.blockElement 738 }); 739 event.preventDefault(); 740 event.stopPropagation(); 741 break; 742 } else if (type === "removeFilter") { 743 window.siyuan.menus.menu.remove(); 744 const oldFilters = Object.assign([], data.view.filters); 745 data.view.filters.find((item: IAVFilter, index: number) => { 746 if (item.column === target.parentElement.dataset.id && item.value.type === target.parentElement.dataset.filterType) { 747 data.view.filters.splice(index, 1); 748 return true; 749 } 750 }); 751 transaction(options.protyle, [{ 752 action: "setAttrViewFilters", 753 avID, 754 data: data.view.filters, 755 blockID 756 }], [{ 757 action: "setAttrViewFilters", 758 avID, 759 data: oldFilters, 760 blockID 761 }]); 762 menuElement.innerHTML = getFiltersHTML(data); 763 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 764 event.preventDefault(); 765 event.stopPropagation(); 766 break; 767 } else if (type === "setFilter") { 768 data.view.filters.find((item: IAVFilter) => { 769 if (item.column === target.parentElement.parentElement.dataset.id && item.value.type === target.parentElement.parentElement.dataset.filterType) { 770 setFilter({ 771 empty: false, 772 filter: item, 773 protyle: options.protyle, 774 data, 775 target, 776 blockElement: options.blockElement 777 }); 778 return true; 779 } 780 }); 781 event.preventDefault(); 782 event.stopPropagation(); 783 break; 784 } else if (type === "numberFormat") { 785 formatNumber({ 786 avPanelElement, 787 element: target, 788 protyle: options.protyle, 789 oldFormat: target.dataset.format, 790 colId: menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id"), 791 avID 792 }); 793 event.preventDefault(); 794 event.stopPropagation(); 795 break; 796 } else if (type === "newCol") { 797 avPanelElement.remove(); 798 const addMenu = addCol(options.protyle, options.blockElement); 799 addMenu.open({ 800 x: tabRect.right, 801 y: tabRect.bottom, 802 h: tabRect.height, 803 isLeft: true 804 }); 805 event.preventDefault(); 806 event.stopPropagation(); 807 break; 808 } else if (type === "update-view-icon") { 809 const rect = target.getBoundingClientRect(); 810 openEmojiPanel("", "av", { 811 x: rect.left, 812 y: rect.bottom + 4, 813 h: rect.height, 814 w: rect.width 815 }, (unicode) => { 816 transaction(options.protyle, [{ 817 action: "setAttrViewViewIcon", 818 avID, 819 id: data.viewID, 820 data: unicode, 821 }], [{ 822 action: "setAttrViewViewIcon", 823 id: data.viewID, 824 avID, 825 data: target.dataset.icon, 826 }]); 827 target.innerHTML = unicode ? unicode2Emoji(unicode) : '<svg style="width: 14px;height: 14px;"><use xlink:href="#iconTable"></use></svg>'; 828 target.dataset.icon = unicode; 829 }, target.querySelector("img")); 830 event.preventDefault(); 831 event.stopPropagation(); 832 break; 833 } else if (type === "set-page-size") { 834 setPageSize({ 835 target, 836 protyle: options.protyle, 837 avID, 838 nodeElement: options.blockElement 839 }); 840 event.preventDefault(); 841 event.stopPropagation(); 842 break; 843 } else if (type === "duplicate-view") { 844 const id = Lute.NewNodeID(); 845 transaction(options.protyle, [{ 846 action: "duplicateAttrViewView", 847 avID, 848 previousID: data.viewID, 849 id, 850 blockID 851 }], [{ 852 action: "removeAttrViewView", 853 avID, 854 id, 855 blockID 856 }]); 857 avPanelElement.remove(); 858 event.preventDefault(); 859 event.stopPropagation(); 860 break; 861 } else if (type === "delete-view") { 862 transaction(options.protyle, [{ 863 action: "removeAttrViewView", 864 avID, 865 id: data.viewID, 866 blockID 867 }]); 868 avPanelElement.remove(); 869 event.preventDefault(); 870 event.stopPropagation(); 871 break; 872 } else if (type === "update-icon") { 873 const rect = target.getBoundingClientRect(); 874 openEmojiPanel("", "av", { 875 x: rect.left, 876 y: rect.bottom + 4, 877 h: rect.height, 878 w: rect.width 879 }, (unicode) => { 880 const colId = menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id"); 881 transaction(options.protyle, [{ 882 action: "setAttrViewColIcon", 883 id: colId, 884 avID, 885 data: unicode, 886 }], [{ 887 action: "setAttrViewColIcon", 888 id: colId, 889 avID, 890 data: target.dataset.icon, 891 }]); 892 target.innerHTML = unicode ? unicode2Emoji(unicode) : `<svg style="height: 14px;width: 14px"><use xlink:href="#${getColIconByType(target.dataset.colType as TAVCol)}"></use></svg>`; 893 if (isCustomAttr) { 894 const iconElement = options.blockElement.querySelector(`.av__row[data-col-id="${colId}"] .block__logoicon`); 895 iconElement.outerHTML = unicode ? unicode2Emoji(unicode, "block__logoicon", true) : `<svg class="block__logoicon"><use xlink:href="#${getColIconByType(iconElement.nextElementSibling.getAttribute("data-type") as TAVCol)}"></use></svg>`; 896 } else { 897 updateAttrViewCellAnimation(options.blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`), undefined, {icon: unicode}); 898 } 899 target.dataset.icon = unicode; 900 }, target.querySelector("img")); 901 event.preventDefault(); 902 event.stopPropagation(); 903 break; 904 } else if (type === "showAllCol") { 905 const doOperations: IOperation[] = []; 906 const undoOperations: IOperation[] = []; 907 fields.forEach((item: IAVColumn) => { 908 if (item.hidden) { 909 doOperations.push({ 910 action: "setAttrViewColHidden", 911 id: item.id, 912 avID, 913 data: false, 914 blockID, 915 }); 916 undoOperations.push({ 917 action: "setAttrViewColHidden", 918 id: item.id, 919 avID, 920 data: true, 921 blockID 922 }); 923 item.hidden = false; 924 } 925 }); 926 if (doOperations.length > 0) { 927 transaction(options.protyle, doOperations, undoOperations); 928 menuElement.innerHTML = getPropertiesHTML(fields); 929 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 930 } 931 event.preventDefault(); 932 event.stopPropagation(); 933 break; 934 } else if (type === "hideAllCol") { 935 const doOperations: IOperation[] = []; 936 const undoOperations: IOperation[] = []; 937 fields.forEach((item: IAVColumn) => { 938 if (!item.hidden && item.type !== "block") { 939 doOperations.push({ 940 action: "setAttrViewColHidden", 941 id: item.id, 942 avID, 943 data: true, 944 blockID 945 }); 946 undoOperations.push({ 947 action: "setAttrViewColHidden", 948 id: item.id, 949 avID, 950 data: false, 951 blockID 952 }); 953 item.hidden = true; 954 } 955 }); 956 if (doOperations.length > 0) { 957 transaction(options.protyle, doOperations, undoOperations); 958 menuElement.innerHTML = getPropertiesHTML(fields); 959 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 960 } 961 event.preventDefault(); 962 event.stopPropagation(); 963 break; 964 } else if (type === "editCol") { 965 menuElement.innerHTML = getEditHTML({ 966 protyle: options.protyle, 967 data, 968 colId: target.dataset.id, 969 isCustomAttr 970 }); 971 bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr, blockID}); 972 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 973 event.preventDefault(); 974 event.stopPropagation(); 975 break; 976 } else if (type === "updateColType") { 977 const colId = options.colId || menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id"); 978 if (target.dataset.newType !== target.dataset.oldType) { 979 const nameElement = avPanelElement.querySelector('.b3-text-field[data-type="name"]') as HTMLInputElement; 980 const name = nameElement.value; 981 let newName = name; 982 fields.find((item: IAVColumn) => { 983 if (item.id === colId) { 984 item.type = target.dataset.newType as TAVCol; 985 if (getColNameByType(target.dataset.oldType as TAVCol) === name) { 986 newName = getColNameByType(target.dataset.newType as TAVCol); 987 item.name = newName; 988 } 989 return true; 990 } 991 }); 992 993 transaction(options.protyle, [{ 994 action: "updateAttrViewCol", 995 id: colId, 996 avID, 997 name: newName, 998 type: target.dataset.newType as TAVCol, 999 }], [{ 1000 action: "updateAttrViewCol", 1001 id: colId, 1002 avID, 1003 name, 1004 type: target.dataset.oldType as TAVCol, 1005 }]); 1006 1007 // 需要取消行号列的筛选和排序 1008 if (target.dataset.newType === "lineNumber") { 1009 const sortExist = data.view.sorts.find((sort) => sort.column === colId); 1010 if (sortExist) { 1011 const oldSorts = Object.assign([], data.view.sorts); 1012 const newSorts = data.view.sorts.filter((sort) => sort.column !== colId); 1013 1014 transaction(options.protyle, [{ 1015 action: "setAttrViewSorts", 1016 avID: data.id, 1017 data: newSorts, 1018 blockID, 1019 }], [{ 1020 action: "setAttrViewSorts", 1021 avID: data.id, 1022 data: oldSorts, 1023 blockID, 1024 }]); 1025 } 1026 1027 const filterExist = data.view.filters.find((filter) => filter.column === colId); 1028 if (filterExist) { 1029 const oldFilters = JSON.parse(JSON.stringify(data.view.filters)); 1030 const newFilters = data.view.filters.filter((filter) => filter.column !== colId); 1031 1032 transaction(options.protyle, [{ 1033 action: "setAttrViewFilters", 1034 avID: data.id, 1035 data: newFilters, 1036 blockID 1037 }], [{ 1038 action: "setAttrViewFilters", 1039 avID: data.id, 1040 data: oldFilters, 1041 blockID 1042 }]); 1043 } 1044 } 1045 } 1046 menuElement.innerHTML = getEditHTML({ 1047 protyle: options.protyle, 1048 data, 1049 colId, 1050 isCustomAttr 1051 }); 1052 bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr, blockID}); 1053 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 1054 event.preventDefault(); 1055 event.stopPropagation(); 1056 break; 1057 } else if (type === "goUpdateColType") { 1058 const editMenuElement = hasClosestByClassName(target, "b3-menu"); 1059 if (editMenuElement) { 1060 editMenuElement.firstElementChild.classList.add("fn__none"); 1061 editMenuElement.lastElementChild.classList.remove("fn__none"); 1062 } 1063 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 1064 event.preventDefault(); 1065 event.stopPropagation(); 1066 break; 1067 } else if (type === "goSearchAV") { 1068 openSearchAV(avID, target, undefined, false); 1069 event.preventDefault(); 1070 event.stopPropagation(); 1071 break; 1072 } else if (type === "goSearchRollupCol") { 1073 goSearchRollupCol({ 1074 target, 1075 data, 1076 isRelation: true, 1077 protyle: options.protyle, 1078 colId: options.colId || menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id") 1079 }); 1080 event.preventDefault(); 1081 event.stopPropagation(); 1082 break; 1083 } else if (type === "goSearchRollupTarget") { 1084 goSearchRollupCol({ 1085 target, 1086 data, 1087 isRelation: false, 1088 protyle: options.protyle, 1089 colId: options.colId || menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id") 1090 }); 1091 event.preventDefault(); 1092 event.stopPropagation(); 1093 break; 1094 } else if (type === "goSearchRollupCalc") { 1095 openCalcMenu(options.protyle, target, { 1096 data, 1097 colId: options.colId || menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id"), 1098 blockID 1099 }); 1100 event.preventDefault(); 1101 event.stopPropagation(); 1102 break; 1103 } else if (type === "updateRelation") { 1104 updateRelation({ 1105 protyle: options.protyle, 1106 avElement: avPanelElement, 1107 avID, 1108 colsData: fields, 1109 blockElement: options.blockElement, 1110 }); 1111 event.preventDefault(); 1112 event.stopPropagation(); 1113 break; 1114 } else if (type === "goEditCol") { 1115 const editMenuElement = hasClosestByClassName(target, "b3-menu"); 1116 if (editMenuElement) { 1117 editMenuElement.firstElementChild.classList.remove("fn__none"); 1118 editMenuElement.lastElementChild.classList.add("fn__none"); 1119 } 1120 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 1121 event.preventDefault(); 1122 event.stopPropagation(); 1123 break; 1124 } else if (type === "hideCol") { 1125 const isEdit = menuElement.querySelector('[data-type="go-properties"]'); 1126 const colId = isEdit ? menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id") : target.parentElement.getAttribute("data-id"); 1127 transaction(options.protyle, [{ 1128 action: "setAttrViewColHidden", 1129 id: colId, 1130 avID, 1131 data: true, 1132 blockID 1133 }], [{ 1134 action: "setAttrViewColHidden", 1135 id: colId, 1136 avID, 1137 data: false, 1138 blockID 1139 }]); 1140 fields.find((item: IAVColumn) => item.id === colId).hidden = true; 1141 if (isEdit) { 1142 menuElement.innerHTML = getEditHTML({ 1143 protyle: options.protyle, 1144 data, 1145 colId, 1146 isCustomAttr 1147 }); 1148 bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr, blockID}); 1149 } else { 1150 menuElement.innerHTML = getPropertiesHTML(fields); 1151 } 1152 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 1153 event.preventDefault(); 1154 event.stopPropagation(); 1155 break; 1156 } else if (type === "showCol") { 1157 const isEdit = menuElement.querySelector('[data-type="go-properties"]'); 1158 const colId = isEdit ? menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id") : target.parentElement.getAttribute("data-id"); 1159 transaction(options.protyle, [{ 1160 action: "setAttrViewColHidden", 1161 id: colId, 1162 avID, 1163 data: false, 1164 blockID 1165 }], [{ 1166 action: "setAttrViewColHidden", 1167 id: colId, 1168 avID, 1169 data: true, 1170 blockID 1171 }]); 1172 fields.find((item: IAVColumn) => item.id === colId).hidden = false; 1173 if (isEdit) { 1174 menuElement.innerHTML = getEditHTML({ 1175 protyle: options.protyle, 1176 data, 1177 colId, 1178 isCustomAttr 1179 }); 1180 bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr, blockID}); 1181 } else { 1182 menuElement.innerHTML = getPropertiesHTML(fields); 1183 } 1184 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 1185 event.preventDefault(); 1186 event.stopPropagation(); 1187 break; 1188 } else if (type === "duplicateCol") { 1189 duplicateCol({ 1190 blockElement: options.blockElement, 1191 protyle: options.protyle, 1192 colId: menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id"), 1193 data, 1194 viewID: data.viewID, 1195 }); 1196 event.preventDefault(); 1197 event.stopPropagation(); 1198 break; 1199 } else if (type === "removeCol") { 1200 if (!isCustomAttr) { 1201 tabRect = options.blockElement.querySelector(".av__views").getBoundingClientRect(); 1202 } 1203 const colId = menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id"); 1204 const colData = fields.find((item: IAVColumn) => { 1205 if (item.id === colId) { 1206 return true; 1207 } 1208 }); 1209 const isTwoWay = colData.type === "relation" && colData.relation?.isTwoWay; 1210 if (isCustomAttr || isTwoWay) { 1211 const dialog = new Dialog({ 1212 title: isTwoWay ? window.siyuan.languages.removeColConfirm : window.siyuan.languages.deleteOpConfirm, 1213 content: `<div class="b3-dialog__content"> 1214 ${isTwoWay ? window.siyuan.languages.confirmRemoveRelationField 1215 .replace("${x}", menuElement.querySelector("input").value || window.siyuan.languages._kernel[272]) 1216 .replace("${y}", menuElement.querySelector('.b3-menu__item[data-type="goSearchAV"] .b3-menu__accelerator').textContent) 1217 .replace("${z}", (menuElement.querySelector('input[data-type="colName"]') as HTMLInputElement).value || window.siyuan.languages._kernel[272]) 1218 : window.siyuan.languages.removeCol.replace("${x}", menuElement.querySelector("input").value || window.siyuan.languages._kernel[272])} 1219 <div class="fn__hr--b"></div> 1220 <button class="fn__block b3-button b3-button--remove" data-action="delete">${isTwoWay ? window.siyuan.languages.removeBothRelationField : window.siyuan.languages.delete}</button> 1221 <div class="fn__hr"></div> 1222 <button class="fn__block b3-button b3-button--remove${isTwoWay ? "" : " fn__none"}" data-action="keep-relation">${window.siyuan.languages.removeButKeepRelationField}</button> 1223 <div class="fn__hr"></div> 1224 <button class="fn__block b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button> 1225</div>`, 1226 width: "520px", 1227 }); 1228 dialog.element.addEventListener("click", (dialogEvent) => { 1229 let target = dialogEvent.target as HTMLElement; 1230 const isDispatch = typeof dialogEvent.detail === "string"; 1231 while (target && target !== dialog.element || isDispatch) { 1232 const action = target.getAttribute("data-action"); 1233 if (action === "delete" || (isDispatch && dialogEvent.detail === "Enter")) { 1234 removeCol({ 1235 protyle: options.protyle, 1236 fields, 1237 avID, 1238 blockID, 1239 menuElement, 1240 isCustomAttr, 1241 blockElement: options.blockElement, 1242 avPanelElement, 1243 tabRect, 1244 isTwoWay: true 1245 }); 1246 dialog.destroy(); 1247 break; 1248 } else if (action === "keep-relation") { 1249 removeCol({ 1250 protyle: options.protyle, 1251 fields, 1252 avID, 1253 blockID, 1254 menuElement, 1255 isCustomAttr, 1256 blockElement: options.blockElement, 1257 avPanelElement, 1258 tabRect, 1259 isTwoWay: false 1260 }); 1261 dialog.destroy(); 1262 break; 1263 } else if (target.classList.contains("b3-button--cancel") || (isDispatch && dialogEvent.detail === "Escape")) { 1264 dialog.destroy(); 1265 break; 1266 } 1267 target = target.parentElement; 1268 } 1269 }); 1270 dialog.element.setAttribute("data-key", Constants.DIALOG_CONFIRM); 1271 } else { 1272 removeCol({ 1273 protyle: options.protyle, 1274 fields, 1275 avID, 1276 blockID, 1277 menuElement, 1278 isCustomAttr, 1279 blockElement: options.blockElement, 1280 avPanelElement, 1281 tabRect, 1282 isTwoWay: false 1283 }); 1284 } 1285 event.preventDefault(); 1286 event.stopPropagation(); 1287 break; 1288 } else if (type === "setColOption") { 1289 setColOption(options.protyle, data, target, options.blockElement, isCustomAttr, options.cellElements); 1290 event.preventDefault(); 1291 event.stopPropagation(); 1292 break; 1293 } else if (type === "setRelationCell") { 1294 menuElement.querySelector(".b3-menu__item--current")?.classList.remove("b3-menu__item--current"); 1295 target.classList.add("b3-menu__item--current"); 1296 setRelationCell(options.protyle, options.blockElement as HTMLElement, target, options.cellElements); 1297 event.preventDefault(); 1298 event.stopPropagation(); 1299 break; 1300 } else if (type === "addColOptionOrCell") { 1301 menuElement.querySelector(".b3-menu__item--current")?.classList.remove("b3-menu__item--current"); 1302 target.classList.add("b3-menu__item--current"); 1303 if (target.querySelector(".b3-menu__checked")) { 1304 removeCellOption(options.protyle, options.cellElements, menuElement.querySelector(`.b3-chips .b3-chip[data-content="${escapeAttr(target.dataset.name)}"]`), options.blockElement); 1305 } else { 1306 addColOptionOrCell(options.protyle, data, options.cellElements, target, menuElement, options.blockElement); 1307 } 1308 window.siyuan.menus.menu.remove(); 1309 event.preventDefault(); 1310 event.stopPropagation(); 1311 break; 1312 } else if (type === "removeCellOption") { 1313 removeCellOption(options.protyle, options.cellElements, target.parentElement, options.blockElement); 1314 event.preventDefault(); 1315 event.stopPropagation(); 1316 break; 1317 } else if (type === "addAssetLink") { 1318 addAssetLink(options.protyle, options.cellElements, target, options.blockElement); 1319 event.preventDefault(); 1320 event.stopPropagation(); 1321 break; 1322 } else if (type === "addAssetExist") { 1323 const rect = target.getBoundingClientRect(); 1324 assetMenu(options.protyle, { 1325 x: rect.right, 1326 y: rect.bottom, 1327 w: target.parentElement.clientWidth + 8, 1328 h: rect.height 1329 }, (url, name) => { 1330 let value: IAVCellAssetValue; 1331 if (Constants.SIYUAN_ASSETS_IMAGE.includes(pathPosix().extname(url).toLowerCase())) { 1332 value = { 1333 type: "image", 1334 content: url, 1335 name: "" 1336 }; 1337 } else { 1338 value = { 1339 type: "file", 1340 content: url, 1341 name 1342 }; 1343 } 1344 updateAssetCell({ 1345 protyle: options.protyle, 1346 cellElements: options.cellElements, 1347 addValue: [value], 1348 blockElement: options.blockElement 1349 }); 1350 window.siyuan.menus.menu.remove(); 1351 }); 1352 event.preventDefault(); 1353 event.stopPropagation(); 1354 break; 1355 } else if (type === "openAssetItem") { 1356 const assetLink = target.parentElement.dataset.content; 1357 const suffix = pathPosix().extname(assetLink); 1358 /// #if !MOBILE 1359 if (isLocalPath(assetLink) && ( 1360 [".pdf"].concat(Constants.SIYUAN_ASSETS_AUDIO).concat(Constants.SIYUAN_ASSETS_VIDEO).includes(suffix) && ( 1361 suffix !== ".pdf" || (suffix === ".pdf" && !assetLink.startsWith("file://")) 1362 ) 1363 )) { 1364 openAsset(options.protyle.app, assetLink.trim(), parseInt(getSearch("page", assetLink)), "right"); 1365 } else if (Constants.SIYUAN_ASSETS_IMAGE.includes(suffix)) { 1366 previewAttrViewImages(assetLink, avID, options.blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW), 1367 (options.blockElement.querySelector('[data-type="av-search"]') as HTMLInputElement)?.value.trim() || ""); 1368 } else { 1369 window.open(assetLink); 1370 } 1371 /// #else 1372 if (Constants.SIYUAN_ASSETS_IMAGE.includes(suffix)) { 1373 previewAttrViewImages(assetLink, avID, options.blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW), 1374 (options.blockElement.querySelector('[data-type="av-search"]') as HTMLInputElement)?.value.trim() || ""); 1375 } else { 1376 window.open(assetLink); 1377 } 1378 /// #endif 1379 event.preventDefault(); 1380 event.stopPropagation(); 1381 break; 1382 } else if (type === "editAssetItem") { 1383 editAssetItem({ 1384 protyle: options.protyle, 1385 cellElements: options.cellElements, 1386 blockElement: options.blockElement, 1387 content: target.parentElement.dataset.content, 1388 type: target.parentElement.dataset.type as "image" | "file", 1389 name: target.parentElement.dataset.name, 1390 index: parseInt(target.parentElement.dataset.index), 1391 rect: target.parentElement.getBoundingClientRect() 1392 }); 1393 event.preventDefault(); 1394 event.stopPropagation(); 1395 break; 1396 } else if (type === "clearDate") { 1397 const colData = fields.find((item: IAVColumn) => { 1398 if (item.id === getColId(options.cellElements[0], data.viewType)) { 1399 return true; 1400 } 1401 }); 1402 updateCellsValue(options.protyle, options.blockElement as HTMLElement, { 1403 isNotEmpty2: false, 1404 isNotEmpty: false, 1405 content: null, 1406 content2: null, 1407 hasEndDate: false, 1408 isNotTime: colData.date ? !colData.date.fillSpecificTime : true, 1409 }, options.cellElements); 1410 avPanelElement.remove(); 1411 event.preventDefault(); 1412 event.stopPropagation(); 1413 break; 1414 } else if (type === "av-add") { 1415 window.siyuan.menus.menu.remove(); 1416 addView(options.protyle, options.blockElement); 1417 avPanelElement.remove(); 1418 event.preventDefault(); 1419 event.stopPropagation(); 1420 break; 1421 } else if (type === "av-view-switch") { 1422 if (!target.parentElement.classList.contains("b3-menu__item--current")) { 1423 avPanelElement.querySelector(".b3-menu__item--current")?.classList.remove("b3-menu__item--current"); 1424 target.parentElement.classList.add("b3-menu__item--current"); 1425 transaction(options.protyle, [{ 1426 action: "setAttrViewBlockView", 1427 blockID, 1428 id: target.parentElement.dataset.id, 1429 avID 1430 }], [{ 1431 action: "setAttrViewBlockView", 1432 blockID, 1433 id: options.blockElement.querySelector(".av__views .item--focus").getAttribute("data-id"), 1434 avID 1435 }]); 1436 } 1437 event.preventDefault(); 1438 event.stopPropagation(); 1439 break; 1440 } else if (type === "av-view-edit") { 1441 if (target.parentElement.classList.contains("b3-menu__item--current")) { 1442 openViewMenu({ 1443 protyle: options.protyle, 1444 blockElement: options.blockElement as HTMLElement, 1445 element: target.parentElement 1446 }); 1447 } else { 1448 avPanelElement.querySelector(".b3-menu__item--current")?.classList.remove("b3-menu__item--current"); 1449 target.parentElement.classList.add("b3-menu__item--current"); 1450 transaction(options.protyle, [{ 1451 action: "setAttrViewBlockView", 1452 blockID, 1453 id: target.parentElement.dataset.id, 1454 avID, 1455 }], [{ 1456 action: "setAttrViewBlockView", 1457 blockID, 1458 id: options.blockElement.querySelector(".av__views .item--focus").getAttribute("data-id"), 1459 avID, 1460 }]); 1461 window.siyuan.menus.menu.remove(); 1462 openViewMenu({ 1463 protyle: options.protyle, 1464 blockElement: options.blockElement as HTMLElement, 1465 element: target.parentElement 1466 }); 1467 } 1468 event.preventDefault(); 1469 event.stopPropagation(); 1470 break; 1471 } else if (type === "set-gallery-cover") { 1472 setGalleryCover({ 1473 target, 1474 protyle: options.protyle, 1475 nodeElement: options.blockElement, 1476 view: data.view as IAVGallery 1477 }); 1478 event.preventDefault(); 1479 event.stopPropagation(); 1480 break; 1481 } else if (type === "set-gallery-size") { 1482 setGallerySize({ 1483 target, 1484 protyle: options.protyle, 1485 nodeElement: options.blockElement, 1486 view: data.view as IAVGallery 1487 }); 1488 event.preventDefault(); 1489 event.stopPropagation(); 1490 break; 1491 } else if (type === "set-gallery-ratio") { 1492 setGalleryRatio({ 1493 target, 1494 protyle: options.protyle, 1495 nodeElement: options.blockElement, 1496 view: data.view as IAVGallery 1497 }); 1498 event.preventDefault(); 1499 event.stopPropagation(); 1500 break; 1501 } else if (type === "set-layout") { 1502 data = await updateLayout({ 1503 target, 1504 protyle: options.protyle, 1505 nodeElement: options.blockElement, 1506 data 1507 }); 1508 fields = getFieldsByData(data); 1509 event.preventDefault(); 1510 event.stopPropagation(); 1511 break; 1512 } else if (type === "goGroupsDate") { 1513 goGroupsDate({ 1514 target, 1515 menuElement, 1516 protyle: options.protyle, 1517 blockElement: options.blockElement, 1518 data 1519 }); 1520 fields = getFieldsByData(data); 1521 event.stopPropagation(); 1522 event.preventDefault(); 1523 break; 1524 } else if (type === "goGroupsSort") { 1525 goGroupsSort({ 1526 target, 1527 menuElement, 1528 protyle: options.protyle, 1529 blockElement: options.blockElement, 1530 data 1531 }); 1532 fields = getFieldsByData(data); 1533 event.stopPropagation(); 1534 event.preventDefault(); 1535 break; 1536 } else if (type === "setGroupMethod") { 1537 setGroupMethod({ 1538 protyle: options.protyle, 1539 fieldId: target.getAttribute("data-id"), 1540 data, 1541 menuElement, 1542 blockElement: options.blockElement, 1543 }); 1544 event.preventDefault(); 1545 event.stopPropagation(); 1546 break; 1547 } else if (type === "goGroups") { 1548 if (menuElement.querySelector('[data-type="avGroupRange"]') && closeCB) { 1549 await closeCB(); 1550 } 1551 closeCB = undefined; 1552 if ((data.view.group && data.view.group.field) || target.classList.contains("block__icon")) { 1553 menuElement.innerHTML = getGroupsHTML(fields, data.view); 1554 bindGroupsEvent({ 1555 protyle: options.protyle, 1556 menuElement: menuElement, 1557 blockElement: options.blockElement, 1558 data 1559 }); 1560 } else { 1561 menuElement.innerHTML = getGroupsMethodHTML(fields, data.view.group); 1562 } 1563 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 1564 event.preventDefault(); 1565 event.stopPropagation(); 1566 break; 1567 } else if (type === "goGroupsMethod") { 1568 window.siyuan.menus.menu.remove(); 1569 menuElement.innerHTML = getGroupsMethodHTML(fields, data.view.group); 1570 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 1571 event.preventDefault(); 1572 event.stopPropagation(); 1573 break; 1574 } else if (type === "getGroupsNumber") { 1575 window.siyuan.menus.menu.remove(); 1576 menuElement.innerHTML = getGroupsNumberHTML(data.view.group); 1577 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 1578 closeCB = bindGroupsNumber({ 1579 protyle: options.protyle, 1580 data, 1581 menuElement, 1582 blockElement: options.blockElement 1583 }); 1584 event.preventDefault(); 1585 event.stopPropagation(); 1586 break; 1587 } else if (type === "hideGroup") { 1588 window.siyuan.menus.menu.remove(); 1589 const useElement = target.firstElementChild; 1590 const isHide = useElement.getAttribute("xlink:href") !== "#iconEye"; 1591 useElement.setAttribute("xlink:href", isHide ? "#iconEye" : "#iconEyeoff"); 1592 let oldGroupHidden; 1593 let showCount = 0; 1594 data.view.groups.forEach((item) => { 1595 if (item.id === target.dataset.id) { 1596 oldGroupHidden = item.groupHidden; 1597 item.groupHidden = isHide ? 0 : 2; 1598 } 1599 if (item.groupHidden === 0) { 1600 showCount++; 1601 } 1602 }); 1603 target.parentElement.classList[isHide ? "remove" : "add"]("b3-menu__item--hidden"); 1604 menuElement.querySelector('[data-type="hideGroups"]').innerHTML = `${window.siyuan.languages[showCount === 0 ? "showAll" : "hideAll"]} 1605<span class="fn__space"></span> 1606<svg><use xlink:href="#iconEye${showCount === 0 ? "" : "off"}"></use></svg>`; 1607 transaction(options.protyle, [{ 1608 action: "hideAttrViewGroup", 1609 avID: data.id, 1610 blockID, 1611 id: target.dataset.id, 1612 data: isHide ? 0 : 2, 1613 }], [{ 1614 action: "hideAttrViewGroup", 1615 avID: data.id, 1616 blockID, 1617 id: target.dataset.id, 1618 data: oldGroupHidden 1619 }]); 1620 event.preventDefault(); 1621 event.stopPropagation(); 1622 break; 1623 } else if (type === "hideGroups") { 1624 window.siyuan.menus.menu.remove(); 1625 const isShow = target.querySelector("use").getAttribute("xlink:href") === "#iconEyeoff"; 1626 target.innerHTML = `${window.siyuan.languages[isShow ? "showAll" : "hideAll"]} 1627<span class="fn__space"></span> 1628<svg><use xlink:href="#iconEye${isShow ? "" : "off"}"></use></svg>`; 1629 data.view.groups.forEach((item) => { 1630 item.groupHidden = isShow ? 2 : 0; 1631 const itemElement = target.parentElement.parentElement.querySelector(`.b3-menu__item[data-id="${item.id}"]`); 1632 itemElement.classList[isShow ? "add" : "remove"]("b3-menu__item--hidden"); 1633 itemElement.querySelector(".b3-menu__action use")?.setAttribute("xlink:href", `#iconEye${isShow ? "off" : ""}`); 1634 }); 1635 transaction(options.protyle, [{ 1636 action: "hideAttrViewAllGroups", 1637 avID: data.id, 1638 blockID, 1639 data: isShow, 1640 }], [{ 1641 action: "hideAttrViewAllGroups", 1642 avID: data.id, 1643 blockID, 1644 data: !isShow 1645 }]); 1646 event.preventDefault(); 1647 event.stopPropagation(); 1648 break; 1649 } else if (type === "removeGroups") { 1650 window.siyuan.menus.menu.remove(); 1651 transaction(options.protyle, [{ 1652 action: "removeAttrViewGroup", 1653 avID: data.id, 1654 blockID, 1655 }], [{ 1656 action: "setAttrViewGroup", 1657 avID: data.id, 1658 blockID, 1659 data: data.view.group 1660 }]); 1661 data.view.group = null; 1662 delete data.view.groups; 1663 menuElement.innerHTML = getGroupsHTML(fields, data.view); 1664 setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); 1665 event.preventDefault(); 1666 event.stopPropagation(); 1667 break; 1668 } 1669 // 有错误日志,没找到重现步骤,需先判断一下 1670 if (!target || !target.parentElement) { 1671 break; 1672 } 1673 target = target.parentElement; 1674 } 1675 }); 1676 }); 1677}; 1678 1679export const getPropertiesHTML = (fields: IAVColumn[]) => { 1680 let showHTML = ""; 1681 let hideHTML = ""; 1682 fields.forEach((item: IAVColumn) => { 1683 if (item.hidden) { 1684 hideHTML += `<button class="b3-menu__item" data-type="editCol" draggable="true" data-id="${item.id}"> 1685 <svg class="b3-menu__icon fn__grab"><use xlink:href="#iconDrag"></use></svg> 1686 <div class="b3-menu__label fn__flex"> 1687 ${item.icon ? unicode2Emoji(item.icon, "b3-menu__icon", true) : `<svg class="b3-menu__icon"><use xlink:href="#${getColIconByType(item.type)}"></use></svg>`} 1688 ${escapeHtml(item.name) || "&nbsp;"} 1689 </div> 1690 <svg class="b3-menu__action" data-type="showCol"><use xlink:href="#iconEye"></use></svg> 1691 <svg class="b3-menu__icon b3-menu__icon--small"><use xlink:href="#iconRight"></use></svg> 1692</button>`; 1693 } else { 1694 showHTML += `<button class="b3-menu__item" data-type="editCol" draggable="true" data-id="${item.id}"> 1695 <svg class="b3-menu__icon fn__grab"><use xlink:href="#iconDrag"></use></svg> 1696 <div class="b3-menu__label fn__flex"> 1697 ${item.icon ? unicode2Emoji(item.icon, "b3-menu__icon", true) : `<svg class="b3-menu__icon"><use xlink:href="#${getColIconByType(item.type)}"></use></svg>`} 1698 ${escapeHtml(item.name) || "&nbsp;"} 1699 </div> 1700 <svg class="b3-menu__action${item.type === "block" ? " fn__none" : ""}" data-type="hideCol"><use xlink:href="#iconEyeoff"></use></svg> 1701 <svg class="b3-menu__icon b3-menu__icon--small"><use xlink:href="#iconRight"></use></svg> 1702</button>`; 1703 } 1704 }); 1705 if (hideHTML) { 1706 hideHTML = `<button class="b3-menu__separator"></button> 1707<button class="b3-menu__item" data-type="nobg"> 1708 <span class="b3-menu__label"> 1709 ${window.siyuan.languages.hideCol} 1710 </span> 1711 <span class="block__icon" data-type="showAllCol"> 1712 ${window.siyuan.languages.showAll} 1713 <span class="fn__space"></span> 1714 <svg><use xlink:href="#iconEye"></use></svg> 1715 </span> 1716</button> 1717${hideHTML}`; 1718 } 1719 return `<div class="b3-menu__items"> 1720<button class="b3-menu__item" data-type="nobg"> 1721 <span class="block__icon" style="padding: 8px;margin-left: -4px;" data-type="go-config"> 1722 <svg><use xlink:href="#iconLeft"></use></svg> 1723 </span> 1724 <span class="b3-menu__label ft__center">${window.siyuan.languages.fields}</span> 1725</button> 1726<button class="b3-menu__separator"></button> 1727<button class="b3-menu__item" data-type="nobg"> 1728 <span class="b3-menu__label"> 1729 ${window.siyuan.languages.showCol} 1730 </span> 1731 <span class="block__icon" data-type="hideAllCol"> 1732 ${window.siyuan.languages.hideAll} 1733 <span class="fn__space"></span> 1734 <svg><use xlink:href="#iconEyeoff"></use></svg> 1735 </span> 1736</button> 1737${showHTML} 1738${hideHTML} 1739<button class="b3-menu__separator"></button> 1740<button class="b3-menu__item" data-type="newCol"> 1741 <svg class="b3-menu__icon"><use xlink:href="#iconAdd"></use></svg> 1742 <span class="b3-menu__label">${window.siyuan.languages.new}</span> 1743</button> 1744</div>`; 1745}; 1746