diff --git a/app/src/assets/scss/business/_custom.scss b/app/src/assets/scss/business/_custom.scss index 1dafec9ff..356f9c132 100644 --- a/app/src/assets/scss/business/_custom.scss +++ b/app/src/assets/scss/business/_custom.scss @@ -16,16 +16,13 @@ &__avheader { border-bottom: 1px solid var(--b3-border-color); padding: 8px; + color: var(--b3-protyle-inline-blockref-color); + opacity: .86; + transition: var(--b3-transition); + cursor: pointer; - .block__logo { - color: var(--b3-protyle-inline-blockref-color); - opacity: .86; - transition: var(--b3-transition); - cursor: pointer; - - &:hover { - opacity: 1; - } + &:hover { + opacity: 1; } } diff --git a/app/src/protyle/render/av/blockAttr.ts b/app/src/protyle/render/av/blockAttr.ts index 2c0c989f8..88b992094 100644 --- a/app/src/protyle/render/av/blockAttr.ts +++ b/app/src/protyle/render/av/blockAttr.ts @@ -6,6 +6,7 @@ import {popTextCell} from "./cell"; import {hasClosestBlock, hasClosestByClassName} from "../../util/hasClosest"; import {unicode2Emoji} from "../../../emoji"; import {transaction} from "../../wysiwyg/transaction"; +import {openMenuPanel} from "./openMenuPanel"; const genAVRollupHTML = (value: IAVCellValue) => { let html = ""; @@ -127,7 +128,7 @@ export const genAVValueHTML = (value: IAVCellValue) => { return html; }; -export const renderAVAttribute = (element: HTMLElement, id: string, protyle: IProtyle) => { +export const renderAVAttribute = (element: HTMLElement, id: string, protyle: IProtyle, cb?: (element: HTMLElement) => void) => { fetchPost("/api/av/getAttributeViewKeys", {id}, (response) => { let html = ""; response.data.forEach((table: { @@ -154,17 +155,15 @@ export const renderAVAttribute = (element: HTMLElement, id: string, protyle: IPr avName: string }) => { html += `
-
- +`; table.keyValues?.forEach(item => { - html += `
+ html += `
-
`; }); - html += "
"; + html += `
+
+
+ +
+
`; }); if (element.innerHTML === "") { let dragBlockElement: HTMLElement; @@ -203,7 +207,7 @@ class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"] transaction(protyle, [{ action: "sortAttrViewCol", avID: dragBlockElement.dataset.avId, - previousID:isBottom ? targetElement.dataset.colId : targetElement.previousElementSibling?.getAttribute("data-col-id"), + previousID: isBottom ? targetElement.dataset.colId : targetElement.previousElementSibling?.getAttribute("data-col-id"), id: window.siyuan.dragElement.dataset.colId, }, { action: "sortAttrViewCol", @@ -255,6 +259,10 @@ class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"] }); element.addEventListener("click", (event) => { let target = event.target as HTMLElement; + const blockElement = hasClosestBlock(target); + if (!blockElement) { + return; + } while (target && !element.isSameNode(target)) { const type = target.getAttribute("data-type"); if (type === "date") { @@ -293,7 +301,8 @@ class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"] event.preventDefault(); break; } else if (type === "addColumn") { - const addMenu = addCol(protyle, hasClosestBlock(target) as HTMLElement, ""); + const rowElements = blockElement.querySelectorAll(".av__row") + const addMenu = addCol(protyle, blockElement, rowElements[rowElements.length - 1].getAttribute("data-col-id")); const addRect = target.getBoundingClientRect(); addMenu.open({ x: addRect.left, @@ -303,6 +312,18 @@ class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"] event.stopPropagation(); event.preventDefault(); break; + } else if (type === "editCol") { + if (target.classList.contains("fn__pointer")) { + openMenuPanel({ + protyle, + blockElement, + type: "edit", + colId: target.parentElement.dataset.colId + }); + } + event.stopPropagation(); + event.preventDefault(); + break; } target = target.parentElement; } @@ -334,5 +355,8 @@ class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"] }); }); }); + if (cb) { + cb(element); + } }); }; diff --git a/app/src/protyle/render/av/col.ts b/app/src/protyle/render/av/col.ts index 9fb9274ff..c459355de 100644 --- a/app/src/protyle/render/av/col.ts +++ b/app/src/protyle/render/av/col.ts @@ -84,7 +84,8 @@ export const duplicateCol = (options: { export const getEditHTML = (options: { protyle: IProtyle, colId: string, - data: IAV + data: IAV, + isCustomAttr: boolean }) => { let colData: IAVColumn; options.data.view.columns.find((item) => { @@ -94,7 +95,7 @@ export const getEditHTML = (options: { } }); let html = ` - @@ -207,7 +208,8 @@ export const getEditHTML = (options: { export const bindEditEvent = (options: { protyle: IProtyle, data: IAV, - menuElement: HTMLElement + menuElement: HTMLElement, + isCustomAttr: boolean }) => { const avID = options.data.id; const colId = options.menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id"); @@ -316,8 +318,18 @@ export const bindEditEvent = (options: { avID, data: addOptionElement.value }]); - options.menuElement.innerHTML = getEditHTML({protyle: options.protyle, colId, data: options.data}); - bindEditEvent({protyle: options.protyle, menuElement: options.menuElement, data: options.data}); + options.menuElement.innerHTML = getEditHTML({ + protyle: options.protyle, + colId, + data: options.data, + isCustomAttr: options.isCustomAttr + }); + bindEditEvent({ + protyle: options.protyle, + menuElement: options.menuElement, + data: options.data, + isCustomAttr: options.isCustomAttr + }); (options.menuElement.querySelector('[data-type="addOption"]') as HTMLInputElement).focus(); } }); diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts index 204d5b001..b3f1eb0d1 100644 --- a/app/src/protyle/render/av/openMenuPanel.ts +++ b/app/src/protyle/render/av/openMenuPanel.ts @@ -50,6 +50,7 @@ export const openMenuPanel = (options: { id: avID, pageSize: parseInt(options.blockElement.getAttribute("data-page-size")) || undefined, }, (response) => { + const isCustomAttr = !options.blockElement.classList.contains("av"); const data = response.data as IAV; let html; if (options.type === "config") { @@ -67,7 +68,7 @@ export const openMenuPanel = (options: { } else if (options.type === "asset") { html = getAssetHTML(options.cellElements); } else if (options.type === "edit") { - html = getEditHTML({protyle: options.protyle, data, colId: options.colId}); + html = getEditHTML({protyle: options.protyle, data, colId: options.colId, isCustomAttr}); } else if (options.type === "date") { html = getDateHTML(data.view, options.cellElements); } else if (options.type === "rollup") { @@ -75,14 +76,12 @@ export const openMenuPanel = (options: { } else if (options.type === "relation") { html = getRelationHTML(data, options.cellElements); if (!html) { - if (options.blockElement.classList.contains("av")) { - openMenuPanel({ - protyle: options.protyle, - blockElement: options.blockElement, - type: "edit", - colId: options.cellElements[0].dataset.colId - }); - } + openMenuPanel({ + protyle: options.protyle, + blockElement: options.blockElement, + type: "edit", + colId: options.cellElements[0].dataset.colId + }); return; } } @@ -93,7 +92,7 @@ export const openMenuPanel = (options: {
`); avPanelElement = document.querySelector(".av__panel"); const menuElement = avPanelElement.lastElementChild as HTMLElement; - const tabRect = options.blockElement.querySelector(".av__views")?.getBoundingClientRect(); + const tabRect = options.blockElement.querySelector(`.av__views, .av__row[data-col-id="${options.colId}"] > .block__logo`)?.getBoundingClientRect(); if (["select", "date", "asset", "relation", "rollup"].includes(options.type)) { const cellRect = options.cellElements[options.cellElements.length - 1].getBoundingClientRect(); if (options.type === "select") { @@ -135,7 +134,7 @@ export const openMenuPanel = (options: { if (options.type === "sorts") { bindSortsEvent(options.protyle, menuElement, data); } else if (options.type === "edit") { - bindEditEvent({protyle: options.protyle, data, menuElement}); + bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr}); } else if (options.type === "config") { bindViewEvent({protyle: options.protyle, data, menuElement}); } @@ -322,9 +321,10 @@ export const openMenuPanel = (options: { menuElement.innerHTML = getEditHTML({ protyle: options.protyle, data, - colId + colId, + isCustomAttr }); - bindEditEvent({protyle: options.protyle, data, menuElement}); + bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr}); } return; } @@ -678,7 +678,12 @@ export const openMenuPanel = (options: { data: target.dataset.icon, }]); target.innerHTML = unicode ? unicode2Emoji(unicode) : ``; - updateAttrViewCellAnimation(options.blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`), undefined, {icon: unicode}); + if (isCustomAttr) { + const iconElement = options.blockElement.querySelector(`.av__row[data-col-id="${colId}"] .block__logoicon`) + iconElement.outerHTML = unicode ? unicode2Emoji(unicode, "block__logoicon", true) : ``; + } else { + updateAttrViewCellAnimation(options.blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`), undefined, {icon: unicode}); + } target.dataset.icon = unicode; }); event.preventDefault(); @@ -744,9 +749,10 @@ export const openMenuPanel = (options: { menuElement.innerHTML = getEditHTML({ protyle: options.protyle, data, - colId: target.parentElement.dataset.id + colId: target.parentElement.dataset.id, + isCustomAttr }); - bindEditEvent({protyle: options.protyle, data, menuElement}); + bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr}); setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); event.preventDefault(); event.stopPropagation(); @@ -854,9 +860,10 @@ export const openMenuPanel = (options: { menuElement.innerHTML = getEditHTML({ protyle: options.protyle, data, - colId + colId, + isCustomAttr }); - bindEditEvent({protyle: options.protyle, data, menuElement}); + bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr}); } else { menuElement.innerHTML = getPropertiesHTML(data.view); } @@ -883,9 +890,10 @@ export const openMenuPanel = (options: { menuElement.innerHTML = getEditHTML({ protyle: options.protyle, data, - colId + colId, + isCustomAttr }); - bindEditEvent({protyle: options.protyle, data, menuElement}); + bindEditEvent({protyle: options.protyle, data, menuElement, isCustomAttr}); } else { menuElement.innerHTML = getPropertiesHTML(data.view); } @@ -935,7 +943,7 @@ export const openMenuPanel = (options: { event.stopPropagation(); break; } else if (type === "setColOption") { - setColOption(options.protyle, data, target, options.blockElement, options.cellElements); + setColOption(options.protyle, data, target, options.blockElement, isCustomAttr, options.cellElements); event.preventDefault(); event.stopPropagation(); break; diff --git a/app/src/protyle/render/av/render.ts b/app/src/protyle/render/av/render.ts index 1e8331251..af67b584e 100644 --- a/app/src/protyle/render/av/render.ts +++ b/app/src/protyle/render/av/render.ts @@ -296,12 +296,15 @@ export const refreshAV = (protyle: IProtyle, operation: IOperation) => { if (operation.action === "addAttrViewCol" && isPulse) { openMenuPanel({protyle, blockElement: item, type: "edit", colId: operation.id}); } - if (["updateAttrViewColRollup","updateAttrViewColTemplate", "updateAttrViewCell", "addAttrViewCol"].includes(operation.action)) { - const attrElement = document.querySelector(`.b3-dialog--open[data-key="${Constants.DIALOG_ATTR}"] div[data-av-id="${operation.avID}"]`) as HTMLElement; - if (attrElement) { - // 更新属性面板 - renderAVAttribute(attrElement.parentElement, attrElement.dataset.nodeId, protyle); - } + + const attrElement = document.querySelector(`.b3-dialog--open[data-key="${Constants.DIALOG_ATTR}"] div[data-av-id="${operation.avID}"]`) as HTMLElement; + if (attrElement) { + // 更新属性面板 + renderAVAttribute(attrElement.parentElement, attrElement.dataset.nodeId, protyle, (newElment) => { + if (operation.action === "addAttrViewCol") { + openMenuPanel({protyle, blockElement: newElment.querySelector(`div[data-av-id="${operation.avID}"]`), type: "edit", colId: operation.id}); + } + }); } }, ["addAttrViewView", "duplicateAttrViewView"].includes(operation.action) ? operation.id : (operation.action === "removeAttrViewView" ? null : undefined)); diff --git a/app/src/protyle/render/av/select.ts b/app/src/protyle/render/av/select.ts index e375f3600..4000811a3 100644 --- a/app/src/protyle/render/av/select.ts +++ b/app/src/protyle/render/av/select.ts @@ -110,7 +110,7 @@ export const removeCellOption = (protyle: IProtyle, data: IAV, cellElements: HTM target.remove(); }; -export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, blockElement: Element, cellElements?: HTMLElement[]) => { +export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, blockElement: Element, isCustomAttr: boolean, cellElements?: HTMLElement[]) => { const menuElement = hasClosestByClassName(target, "b3-menu"); if (!menuElement) { return; @@ -168,8 +168,8 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, } }); if (!cellElements) { - menuElement.innerHTML = getEditHTML({protyle, data, colId}); - bindEditEvent({protyle, data, menuElement}); + menuElement.innerHTML = getEditHTML({protyle, data, colId, isCustomAttr}); + bindEditEvent({protyle, data, menuElement, isCustomAttr}); } else { cellElements.forEach((cellElement: HTMLMediaElement) => { data.view.rows.find(row => { @@ -246,8 +246,8 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, } }); if (!cellElements) { - menuElement.innerHTML = getEditHTML({protyle, data, colId}); - bindEditEvent({protyle, data, menuElement}); + menuElement.innerHTML = getEditHTML({protyle, data, colId, isCustomAttr}); + bindEditEvent({protyle, data, menuElement, isCustomAttr}); } else { cellElements.forEach((cellElement: HTMLElement) => { data.view.rows.find(row => { @@ -325,8 +325,8 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, } }); if (!cellElements) { - menuElement.innerHTML = getEditHTML({protyle, data, colId}); - bindEditEvent({protyle, data, menuElement}); + menuElement.innerHTML = getEditHTML({protyle, data, colId, isCustomAttr}); + bindEditEvent({protyle, data, menuElement, isCustomAttr}); } else { cellElements.forEach((cellElement: HTMLElement) => { data.view.rows.find(row => { diff --git a/app/src/protyle/wysiwyg/transaction.ts b/app/src/protyle/wysiwyg/transaction.ts index fe43f5fb7..acf163ad3 100644 --- a/app/src/protyle/wysiwyg/transaction.ts +++ b/app/src/protyle/wysiwyg/transaction.ts @@ -722,7 +722,7 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, isUndo: "updateAttrViewColOption", "updateAttrViewCell", "sortAttrViewRow", "sortAttrViewCol", "setAttrViewColHidden", "setAttrViewColWrap", "setAttrViewColWidth", "removeAttrViewColOption", "setAttrViewName", "setAttrViewFilters", "setAttrViewSorts", "setAttrViewColCalc", "removeAttrViewCol", "updateAttrViewColNumberFormat", "removeAttrViewBlock", - "replaceAttrViewBlock", "updateAttrViewColTemplate", "setAttrViewColPin", "addAttrViewView", + "replaceAttrViewBlock", "updateAttrViewColTemplate", "setAttrViewColPin", "addAttrViewView", "setAttrViewColIcon", "removeAttrViewView", "setAttrViewViewName", "setAttrViewViewIcon", "duplicateAttrViewView", "sortAttrViewView", "updateAttrViewColRelation", "setAttrViewPageSize", "updateAttrViewColRollup"].includes(operation.action)) { refreshAV(protyle, operation);