diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index 1cc96e743..3a8e638bd 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -31,23 +31,20 @@ export const getCellText = (cellElement: HTMLElement | false) => { return cellText; }; -const genCellValueByElement = (colType: TAVCol, cellElement: HTMLElement) => { - let cellValue: IAVCellValue; +export const genCellValueByElement = (colType: TAVCol, cellElement: HTMLElement) => { + const cellValue: IAVCellValue = { + type: colType, + id: cellElement.dataset.id, + }; if (colType === "number") { const value = cellElement.querySelector(".av__celltext").getAttribute("data-content"); - cellValue = { - type: colType, - number: { - content: parseFloat(value) || 0, - isNotEmpty: !!value - } + cellValue.number = { + content: parseFloat(value) || 0, + isNotEmpty: !!value }; } else if (["text", "block", "url", "phone", "email", "template"].includes(colType)) { - cellValue = { - type: colType, - [colType]: { - content: cellElement.querySelector(".av__celltext").textContent.trim() - } + cellValue[colType as "text"] = { + content: cellElement.querySelector(".av__celltext").textContent.trim() }; } else if (colType === "mSelect" || colType === "select") { const mSelect: IAVCellSelectValue[] = []; @@ -57,29 +54,17 @@ const genCellValueByElement = (colType: TAVCol, cellElement: HTMLElement) => { color: item.style.color.replace("var(--b3-font-color", "").replace(")", "") }); }); - cellValue = { - type: colType, - mSelect - }; + cellValue.mSelect = mSelect; } else if (["date", "created", "updated"].includes(colType)) { - cellValue = { - type: colType, - [colType]: JSON.parse(cellElement.querySelector(".av__celltext").getAttribute("data-value")) - }; + cellValue[colType as "date"] = JSON.parse(cellElement.querySelector(".av__celltext").getAttribute("data-value")) } else if (colType === "checkbox") { - cellValue = { - type: colType, - checkbox: { - checked: cellElement.querySelector("use").getAttribute("xlink:href") === "#iconCheck" ? true : false - } + cellValue.checkbox = { + checked: cellElement.querySelector("use").getAttribute("xlink:href") === "#iconCheck" ? true : false }; } else if (colType === "relation") { - cellValue = { - type: colType, - relation: { - blockIDs: Array.from(cellElement.querySelectorAll("span")).map((item: HTMLElement) => item.getAttribute("data-id")), - contents: Array.from(cellElement.querySelectorAll("span")).map((item: HTMLElement) => item.textContent), - } + cellValue.relation = { + blockIDs: Array.from(cellElement.querySelectorAll("span")).map((item: HTMLElement) => item.getAttribute("data-id")), + contents: Array.from(cellElement.querySelectorAll("span")).map((item: HTMLElement) => item.textContent), }; } else if (colType === "mAsset") { const mAsset: IAVCellAssetValue[] = [] @@ -91,10 +76,7 @@ const genCellValueByElement = (colType: TAVCol, cellElement: HTMLElement) => { name: isImg ? "" : item.textContent }) }) - cellValue = { - type: colType, - mAsset - }; + cellValue.mAsset = mAsset } if (colType === "block") { cellValue.isDetached = cellElement.dataset.detached === "true"; diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts index e80627b54..f06e92203 100644 --- a/app/src/protyle/render/av/openMenuPanel.ts +++ b/app/src/protyle/render/av/openMenuPanel.ts @@ -91,7 +91,7 @@ export const openMenuPanel = (options: { if (["select", "date", "asset", "relation"].includes(options.type)) { const cellRect = options.cellElements[options.cellElements.length - 1].getBoundingClientRect(); if (options.type === "select") { - bindSelectEvent(options.protyle, data, menuElement, options.cellElements); + bindSelectEvent(options.protyle, data, menuElement, options.cellElements, options.blockElement); } else if (options.type === "date") { bindDateEvent({protyle: options.protyle, data, menuElement, cellElements: options.cellElements}); } else if (options.type === "asset") { @@ -296,7 +296,7 @@ export const openMenuPanel = (options: { }]); if (options.cellElements) { menuElement.innerHTML = getSelectHTML(data.view, options.cellElements); - bindSelectEvent(options.protyle, data, menuElement, options.cellElements); + bindSelectEvent(options.protyle, data, menuElement, options.cellElements, options.blockElement); } else { menuElement.innerHTML = getEditHTML({ protyle: options.protyle, @@ -905,7 +905,7 @@ export const openMenuPanel = (options: { event.stopPropagation(); break; } else if (type === "setColOption") { - setColOption(options.protyle, data, target, options.cellElements); + setColOption(options.protyle, data, target, options.blockElement, options.cellElements); event.preventDefault(); event.stopPropagation(); break; @@ -915,13 +915,13 @@ export const openMenuPanel = (options: { event.stopPropagation(); break; } else if (type === "addColOptionOrCell") { - addColOptionOrCell(options.protyle, data, options.cellElements, target, menuElement); + addColOptionOrCell(options.protyle, data, options.cellElements, target, menuElement, options.blockElement); window.siyuan.menus.menu.remove(); event.preventDefault(); event.stopPropagation(); break; } else if (type === "removeCellOption") { - removeCellOption(options.protyle, data, options.cellElements, target.parentElement); + removeCellOption(options.protyle, data, options.cellElements, target.parentElement, options.blockElement); event.preventDefault(); event.stopPropagation(); break; diff --git a/app/src/protyle/render/av/select.ts b/app/src/protyle/render/av/select.ts index 8f9413bcb..4870f85e1 100644 --- a/app/src/protyle/render/av/select.ts +++ b/app/src/protyle/render/av/select.ts @@ -1,12 +1,13 @@ import {Menu} from "../../../plugin/Menu"; import {transaction} from "../../wysiwyg/transaction"; -import {hasClosestByClassName} from "../../util/hasClosest"; +import {hasClosestBlock, hasClosestByClassName} from "../../util/hasClosest"; import {confirmDialog} from "../../../dialog/confirmDialog"; import {upDownHint} from "../../../util/upDownHint"; import {bindEditEvent, getEditHTML} from "./col"; import {updateAttrViewCellAnimation} from "./action"; import {genAVValueHTML} from "./blockAttr"; import {escapeAttr} from "../../../util/escape"; +import {genCellValueByElement, getTypeByCellElement} from "./cell"; const filterSelectHTML = (key: string, options: { name: string, color: string }[]) => { let html = ""; @@ -46,71 +47,67 @@ const filterSelectHTML = (key: string, options: { name: string, color: string }[ return html; }; -export const removeCellOption = (protyle: IProtyle, data: IAV, cellElements: HTMLElement[], target: HTMLElement) => { +export const removeCellOption = (protyle: IProtyle, data: IAV, cellElements: HTMLElement[], target: HTMLElement, blockElement: Element) => { if (!target) { return; } const colId = cellElements[0].dataset.colId; const doOperations: IOperation[] = []; const undoOperations: IOperation[] = []; - let newData: IAVCellSelectValue[]; cellElements.forEach((item, elementIndex) => { + if (!blockElement.contains(item)) { + item = cellElements[elementIndex] = blockElement.querySelector(`.av__cell[data-id="${item.dataset.id}"]`) as HTMLElement; + } const rowID = (hasClosestByClassName(item, "av__row") as HTMLElement).dataset.id; - const cellId = item.dataset.id; - let cellData: IAVCell; + const cellValue = genCellValueByElement(getTypeByCellElement(item) || item.dataset.type as TAVCol, item); + const oldValue = Object.assign({}, cellValue.mSelect); + if (elementIndex === 0) { + cellValue.mSelect?.find((item: { content: string }, index: number) => { + if (item.content === target.dataset.content) { + cellValue.mSelect.splice(index, 1); + return true; + } + }); + } + + doOperations.push({ + action: "updateAttrViewCell", + id: cellValue.id, + keyID: colId, + rowID, + avID: data.id, + data: cellValue + }); + undoOperations.push({ + action: "updateAttrViewCell", + id: cellValue.id, + keyID: colId, + rowID, + avID: data.id, + data: oldValue + }); data.view.rows.find(row => { if (row.id === rowID) { row.cells.find(cell => { - if (cell.id === cellId) { - cellData = cell; + if (cell.id === cellValue.id) { + cell.value = cellValue; return true; } }); return true; } }); - const oldValue = Object.assign([], cellData.value.mSelect); - if (elementIndex === 0) { - cellData.value.mSelect?.find((item: { content: string }, index: number) => { - if (item.content === target.dataset.content) { - cellData.value.mSelect.splice(index, 1); - return true; - } - }); - newData = cellData.value.mSelect; - } else { - cellData.value.mSelect = newData; - } - - doOperations.push({ - action: "updateAttrViewCell", - id: cellId, - keyID: colId, - rowID, - avID: data.id, - data: cellData.value - }); - undoOperations.push({ - action: "updateAttrViewCell", - id: cellId, - keyID: colId, - rowID, - avID: data.id, - data: { - mSelect: oldValue - } - }); if (item.classList.contains("custom-attr__avvalue")) { - item.innerHTML = genAVValueHTML(cellData.value); + item.innerHTML = genAVValueHTML(cellValue); } else { - updateAttrViewCellAnimation(item, cellData.value); + updateAttrViewCellAnimation(item, cellValue); } }); transaction(protyle, doOperations, undoOperations); target.remove(); }; -export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, cellElements?: HTMLElement[]) => { +export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, blockElement: Element, cellElements?: HTMLElement[]) => { const menuElement = hasClosestByClassName(target, "b3-menu"); if (!menuElement) { return; @@ -195,7 +192,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, }); }); menuElement.innerHTML = getSelectHTML(data.view, cellElements); - bindSelectEvent(protyle, data, menuElement, cellElements); + bindSelectEvent(protyle, data, menuElement, cellElements, blockElement); } }); if (menu.isOpen) { @@ -273,7 +270,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, }); }); menuElement.innerHTML = getSelectHTML(data.view, cellElements); - bindSelectEvent(protyle, data, menuElement, cellElements); + bindSelectEvent(protyle, data, menuElement, cellElements, blockElement); } }); } @@ -353,7 +350,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, }); }); menuElement.innerHTML = getSelectHTML(data.view, cellElements); - bindSelectEvent(protyle, data, menuElement, cellElements); + bindSelectEvent(protyle, data, menuElement, cellElements, blockElement); } name = inputElement.value; color = (index + 1).toString(); @@ -372,7 +369,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, inputElement.select(); }; -export const bindSelectEvent = (protyle: IProtyle, data: IAV, menuElement: HTMLElement, cellElements: HTMLElement[]) => { +export const bindSelectEvent = (protyle: IProtyle, data: IAV, menuElement: HTMLElement, cellElements: HTMLElement[], blockElement: Element) => { const inputElement = menuElement.querySelector("input"); const colId = cellElements[0].dataset.colId; let colData: IAVColumn; @@ -407,14 +404,14 @@ export const bindSelectEvent = (protyle: IProtyle, data: IAV, menuElement: HTMLE if (!currentElement) { currentElement = menuElement.querySelector(".b3-menu__item--current"); } - addColOptionOrCell(protyle, data, cellElements, currentElement, menuElement); + addColOptionOrCell(protyle, data, cellElements, currentElement, menuElement, blockElement); } else if (event.key === "Backspace" && inputElement.value === "") { - removeCellOption(protyle, data, cellElements, inputElement.previousElementSibling as HTMLElement); + removeCellOption(protyle, data, cellElements, inputElement.previousElementSibling as HTMLElement, blockElement); } }); }; -export const addColOptionOrCell = (protyle: IProtyle, data: IAV, cellElements: HTMLElement[], currentElement: HTMLElement, menuElement: HTMLElement) => { +export const addColOptionOrCell = (protyle: IProtyle, data: IAV, cellElements: HTMLElement[], currentElement: HTMLElement, menuElement: HTMLElement, blockElement: Element) => { let hasSelected = false; Array.from(menuElement.querySelectorAll(".b3-chips .b3-chip")).find((item: HTMLElement) => { if (item.dataset.content === currentElement.dataset.name) { @@ -427,17 +424,12 @@ export const addColOptionOrCell = (protyle: IProtyle, data: IAV, cellElements: H return; } - const rowElement = hasClosestByClassName(cellElements[0], "av__row"); - if (!rowElement) { - return; + const nodeElement = hasClosestBlock(cellElements[0]); + if (!nodeElement) { + cellElements.forEach((item, index) => { + cellElements[index] = blockElement.querySelector(`.av__cell[data-id="${item.dataset.id}"]`) as HTMLElement; + }); } - let cellIndex: number; - Array.from(rowElement.querySelectorAll(".av__cell")).find((item: HTMLElement, index) => { - if (item.dataset.id === cellElements[0].dataset.id) { - cellIndex = index; - return true; - } - }); const colId = cellElements[0].dataset.colId; let colData: IAVColumn; data.view.columns.find((item: IAVColumn) => { @@ -452,87 +444,67 @@ export const addColOptionOrCell = (protyle: IProtyle, data: IAV, cellElements: H const cellDoOperations: IOperation[] = []; const cellUndoOperations: IOperation[] = []; - let newValue: IAVCellSelectValue[]; cellElements.forEach((item, index) => { const itemRowElement = hasClosestByClassName(item, "av__row"); if (!itemRowElement) { return; } - let cellData: IAVCell; - const rowID = itemRowElement.dataset.id; - data.view.rows.find(row => { - if (row.id === rowID) { - if (typeof cellIndex === "number") { - cellData = row.cells[cellIndex]; - // 为空时 cellId 每次请求都不一致 - cellData.id = item.dataset.id; - if (!cellData.value || !cellData.value.mSelect) { - cellData.value = {mSelect: []} as IAVCellValue; - } - } else { - cellData = row.cells.find(cellItem => { - if (cellItem.id === item.dataset.id) { - return true; - } - }); - } - return true; - } - }); - - const oldValue = Object.assign([], cellData.value.mSelect); - if (colData.type === "mSelect") { - if (index === 0) { + const cellValue = genCellValueByElement(colData.type, item); + const oldValue = Object.assign({}, cellValue); + if (index === 0) { + if (colData.type === "mSelect") { let hasOption = false; - cellData.value.mSelect.find((item) => { + cellValue.mSelect.find((item) => { if (item.content === currentElement.dataset.name) { hasOption = true; return true; } }); if (!hasOption) { - cellData.value.mSelect.push({ + cellValue.mSelect.push({ color: currentElement.dataset.color, content: currentElement.dataset.name }); } - newValue = cellData.value.mSelect; } else { - cellData.value.mSelect = newValue; - } - } else { - if (index === 0) { - cellData.value.mSelect = [{ + cellValue.mSelect = [{ color: currentElement.dataset.color, content: currentElement.dataset.name }]; - newValue = cellData.value.mSelect; - } else { - cellData.value.mSelect = newValue; } } + const rowID = itemRowElement.dataset.id; cellDoOperations.push({ action: "updateAttrViewCell", - id: cellData.id, + id: cellValue.id, keyID: colId, rowID, avID: data.id, - data: cellData.value + data: cellValue }); cellUndoOperations.push({ action: "updateAttrViewCell", - id: cellData.id, + id: cellValue.id, keyID: colId, rowID, avID: data.id, - data: { - [colData.type]: oldValue - } + data: oldValue }); + data.view.rows.find(row => { + if (row.id === rowID) { + row.cells.find(cell => { + if (cell.id === cellValue.id) { + cell.value = cellValue; + return true; + } + }); + return true; + } + }) if (item.classList.contains("custom-attr__avvalue")) { - item.innerHTML = genAVValueHTML(cellData.value); + item.innerHTML = genAVValueHTML(cellValue); } else { - updateAttrViewCellAnimation(item, cellData.value); + updateAttrViewCellAnimation(item, cellValue); } }); @@ -560,7 +532,7 @@ export const addColOptionOrCell = (protyle: IProtyle, data: IAV, cellElements: H menuElement.parentElement.remove(); } else { menuElement.innerHTML = getSelectHTML(data.view, cellElements); - bindSelectEvent(protyle, data, menuElement, cellElements); + bindSelectEvent(protyle, data, menuElement, cellElements, blockElement); menuElement.querySelector("input").focus(); } };