From 22c46bbc6b87132021f18ad219e9543fc2feb234 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Sun, 2 Jul 2023 20:52:16 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/7536 --- app/src/assets/scss/base.scss | 2 + app/src/assets/scss/business/_av.scss | 10 ++ app/src/assets/scss/component/_menu.scss | 1 + app/src/boot/globalShortcut.ts | 3 +- app/src/protyle/hint/extend.ts | 4 +- app/src/protyle/render/av/action.ts | 120 ++++----------------- app/src/protyle/render/av/addCol.ts | 107 ++++++++++++++++++ app/src/protyle/render/av/cell.ts | 33 +++--- app/src/protyle/render/av/openMenuPanel.ts | 103 ++++++++++++++++++ app/src/protyle/render/av/render.ts | 18 +++- 10 files changed, 283 insertions(+), 118 deletions(-) create mode 100644 app/src/protyle/render/av/addCol.ts create mode 100644 app/src/protyle/render/av/openMenuPanel.ts diff --git a/app/src/assets/scss/base.scss b/app/src/assets/scss/base.scss index 4c5d46a2a..93c16cbdf 100644 --- a/app/src/assets/scss/base.scss +++ b/app/src/assets/scss/base.scss @@ -78,6 +78,8 @@ progressLoading: 400 #windowControls: 502 .b3-snackbar: 503 + +.av__panel: 504 */ html { diff --git a/app/src/assets/scss/business/_av.scss b/app/src/assets/scss/business/_av.scss index f1f1fcb2c..45e5a3cf8 100644 --- a/app/src/assets/scss/business/_av.scss +++ b/app/src/assets/scss/business/_av.scss @@ -12,6 +12,7 @@ outline: none; font-size: 18px; font-weight: bold; + &:empty::after { color: var(--b3-theme-on-surface); content: attr(data-tip); @@ -109,6 +110,15 @@ } } + &__panel { + z-index: 504; + position: relative; + + .b3-menu__item:not([data-type="title"]):hover { + background-color: var(--b3-list-hover); + } + } + &.protyle-wysiwyg--select { .layout-tab-bar, .av__row--header, diff --git a/app/src/assets/scss/component/_menu.scss b/app/src/assets/scss/component/_menu.scss index e1b0bd8cd..25f8ab7dd 100644 --- a/app/src/assets/scss/component/_menu.scss +++ b/app/src/assets/scss/component/_menu.scss @@ -231,6 +231,7 @@ &:hover { opacity: 1; + color: var(--b3-theme-on-background); } } diff --git a/app/src/boot/globalShortcut.ts b/app/src/boot/globalShortcut.ts index 188768426..2ed24de46 100644 --- a/app/src/boot/globalShortcut.ts +++ b/app/src/boot/globalShortcut.ts @@ -874,7 +874,8 @@ export const globalShortcut = (app: App) => { window.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => { if (!window.siyuan.menus.menu.element.contains(event.target) && !hasClosestByAttribute(event.target, "data-menu", "true")) { - if (getSelection().rangeCount > 0 && window.siyuan.menus.menu.element.contains(getSelection().getRangeAt(0).startContainer)) { + if (getSelection().rangeCount > 0 && window.siyuan.menus.menu.element.contains(getSelection().getRangeAt(0).startContainer) && + window.siyuan.menus.menu.element.contains(document.activeElement)) { // https://ld246.com/article/1654567749834/comment/1654589171218#comments } else { window.siyuan.menus.menu.remove(); diff --git a/app/src/protyle/hint/extend.ts b/app/src/protyle/hint/extend.ts index 2dddeab03..16102dcc1 100644 --- a/app/src/protyle/hint/extend.ts +++ b/app/src/protyle/hint/extend.ts @@ -46,11 +46,11 @@ export const hintSlash = (key: string, protyle: IProtyle) => { filter: ["ai chat"], value: Constants.ZWSP + 5, html: '
AI Chat
', - }, { + }, /*{ filter: ["属性视图", "shuxingshitu", "sxst", "attribute view"], value: '
', html: `
${window.siyuan.languages.attributeView}
`, - }, { + },*/ { filter: ["文档", "子文档", "wendang", "wd", "ziwendang", "zwd", "xjwd"], value: Constants.ZWSP + 4, html: `
${window.siyuan.languages.newFile}${updateHotkeyTip(window.siyuan.config.keymap.general.newFile.custom)}
`, diff --git a/app/src/protyle/render/av/action.ts b/app/src/protyle/render/av/action.ts index 023bbaadb..74cc0babc 100644 --- a/app/src/protyle/render/av/action.ts +++ b/app/src/protyle/render/av/action.ts @@ -6,6 +6,8 @@ import {copySubMenu} from "../../../menus/commonMenuItem"; import {popTextCell, showHeaderCellMenu} from "./cell"; import {getColIconByType, updateHeader} from "./col"; import {emitOpenMenu} from "../../../plugin/EventBus"; +import {addCol} from "./addCol"; +import {openMenuPanel} from "./openMenuPanel"; export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLElement }) => { const blockElement = hasClosestBlock(event.target); @@ -14,108 +16,7 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle } const addElement = hasClosestByAttribute(event.target, "data-type", "av-header-add"); if (addElement) { - const menu = new Menu("av-header-add"); - menu.addItem({ - icon: "iconAlignLeft", - label: window.siyuan.languages.text, - click() { - const id = Lute.NewNodeID(); - const type = "text"; - transaction(protyle, [{ - action: "addAttrViewCol", - name: "Text", - parentID: blockElement.getAttribute("data-av-id"), - type, - id - }], [{ - action: "removeAttrViewCol", - id, - parentID: blockElement.getAttribute("data-av-id"), - }]); - } - }); - menu.addItem({ - icon: "iconNumber", - label: window.siyuan.languages.number, - click() { - const id = Lute.NewNodeID(); - const type = "text"; - transaction(protyle, [{ - action: "addAttrViewCol", - name: "Text", - parentID: blockElement.getAttribute("data-av-id"), - type, - id - }], [{ - action: "removeAttrViewCol", - id, - parentID: blockElement.getAttribute("data-av-id"), - }]); - } - }); - menu.addItem({ - icon: "iconListItem", - label: window.siyuan.languages.select, - click() { - const id = Lute.NewNodeID(); - const type = "text"; - transaction(protyle, [{ - action: "addAttrViewCol", - name: "Text", - parentID: blockElement.getAttribute("data-av-id"), - type, - id - }], [{ - action: "removeAttrViewCol", - id, - parentID: blockElement.getAttribute("data-av-id"), - }]); - } - }); - menu.addItem({ - icon: "iconList", - label: window.siyuan.languages.multiSelect, - click() { - const id = Lute.NewNodeID(); - const type = "text"; - transaction(protyle, [{ - action: "addAttrViewCol", - name: "Text", - parentID: blockElement.getAttribute("data-av-id"), - type, - id - }], [{ - action: "removeAttrViewCol", - id, - parentID: blockElement.getAttribute("data-av-id"), - }]); - } - }); - menu.addItem({ - icon: "iconCalendar", - label: window.siyuan.languages.date, - click() { - const id = Lute.NewNodeID(); - const type = "text"; - transaction(protyle, [{ - action: "addAttrViewCol", - name: "Text", - parentID: blockElement.getAttribute("data-av-id"), - type, - id - }], [{ - action: "removeAttrViewCol", - id, - parentID: blockElement.getAttribute("data-av-id"), - }]); - } - }); - const addRect = addElement.getBoundingClientRect(); - menu.open({ - x: addRect.left, - y: addRect.bottom, - h: addRect.height - }); + addCol(protyle, blockElement, addElement); event.preventDefault(); event.stopPropagation(); return true; @@ -161,6 +62,21 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle return true; } + const headerMoreElement = hasClosestByAttribute(event.target, "data-type","av-header-more"); + if (headerMoreElement) { + openMenuPanel(protyle, blockElement, "properties"); + event.preventDefault(); + event.stopPropagation(); + return true; + } + + const moreElement = hasClosestByAttribute(event.target, "data-type","av-more"); + if (moreElement) { + openMenuPanel(protyle, blockElement, "config"); + event.preventDefault(); + event.stopPropagation(); + return true; + } const cellElement = hasClosestByClassName(event.target, "av__cell"); if (cellElement) { if (cellElement.parentElement.classList.contains("av__row--header")) { diff --git a/app/src/protyle/render/av/addCol.ts b/app/src/protyle/render/av/addCol.ts new file mode 100644 index 000000000..d4aa5717b --- /dev/null +++ b/app/src/protyle/render/av/addCol.ts @@ -0,0 +1,107 @@ +import {Menu} from "../../../plugin/Menu"; +import {transaction} from "../../wysiwyg/transaction"; + +export const addCol = (protyle:IProtyle, blockElement:HTMLElement, addElement:HTMLElement) => { + const menu = new Menu("av-header-add"); + menu.addItem({ + icon: "iconAlignLeft", + label: window.siyuan.languages.text, + click() { + const id = Lute.NewNodeID(); + const type = "text"; + transaction(protyle, [{ + action: "addAttrViewCol", + name: "Text", + parentID: blockElement.getAttribute("data-av-id"), + type, + id + }], [{ + action: "removeAttrViewCol", + id, + parentID: blockElement.getAttribute("data-av-id"), + }]); + } + }); + menu.addItem({ + icon: "iconNumber", + label: window.siyuan.languages.number, + click() { + const id = Lute.NewNodeID(); + const type = "text"; + transaction(protyle, [{ + action: "addAttrViewCol", + name: "Text", + parentID: blockElement.getAttribute("data-av-id"), + type, + id + }], [{ + action: "removeAttrViewCol", + id, + parentID: blockElement.getAttribute("data-av-id"), + }]); + } + }); + menu.addItem({ + icon: "iconListItem", + label: window.siyuan.languages.select, + click() { + const id = Lute.NewNodeID(); + const type = "text"; + transaction(protyle, [{ + action: "addAttrViewCol", + name: "Text", + parentID: blockElement.getAttribute("data-av-id"), + type, + id + }], [{ + action: "removeAttrViewCol", + id, + parentID: blockElement.getAttribute("data-av-id"), + }]); + } + }); + menu.addItem({ + icon: "iconList", + label: window.siyuan.languages.multiSelect, + click() { + const id = Lute.NewNodeID(); + const type = "text"; + transaction(protyle, [{ + action: "addAttrViewCol", + name: "Text", + parentID: blockElement.getAttribute("data-av-id"), + type, + id + }], [{ + action: "removeAttrViewCol", + id, + parentID: blockElement.getAttribute("data-av-id"), + }]); + } + }); + menu.addItem({ + icon: "iconCalendar", + label: window.siyuan.languages.date, + click() { + const id = Lute.NewNodeID(); + const type = "text"; + transaction(protyle, [{ + action: "addAttrViewCol", + name: "Text", + parentID: blockElement.getAttribute("data-av-id"), + type, + id + }], [{ + action: "removeAttrViewCol", + id, + parentID: blockElement.getAttribute("data-av-id"), + }]); + } + }); + const addRect = addElement.getBoundingClientRect(); + menu.open({ + x: addRect.left, + y: addRect.bottom, + h: addRect.height + }); +} diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index 8b0ab34cf..71d750ba4 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -89,6 +89,8 @@ const removeCol = (cellElement: HTMLElement) => { export const showHeaderCellMenu = (protyle: IProtyle, blockElement: HTMLElement, cellElement: HTMLElement) => { const type = cellElement.getAttribute("data-dtype") as TAVCol; + const colId = cellElement.getAttribute("data-id"); + const avId = blockElement.getAttribute("data-av-id"); const menu = new Menu("av-header-cell", () => { const newValue = (window.siyuan.menus.menu.element.querySelector(".b3-text-field") as HTMLInputElement).value; if (newValue === cellElement.textContent.trim()) { @@ -96,14 +98,14 @@ export const showHeaderCellMenu = (protyle: IProtyle, blockElement: HTMLElement, } transaction(protyle, [{ action: "updateAttrViewCol", - id: cellElement.getAttribute("data-id"), - parentID: blockElement.getAttribute("data-av-id"), + id: colId, + parentID: avId, name: newValue, type, }], [{ action: "updateAttrViewCol", - id: cellElement.getAttribute("data-id"), - parentID: blockElement.getAttribute("data-av-id"), + id: colId, + parentID: avId, name: cellElement.textContent.trim(), type, }]); @@ -150,10 +152,14 @@ export const showHeaderCellMenu = (protyle: IProtyle, blockElement: HTMLElement, label: window.siyuan.languages.hide, click() { transaction(protyle, [{ - action:"setAttrViewColHidden", + action: "setAttrViewColHidden", + id: colId, + parentID: avId, data: true }], [{ - action:"setAttrViewColHidden", + action: "setAttrViewColHidden", + id: colId, + parentID: avId, data: false }]); } @@ -169,17 +175,16 @@ export const showHeaderCellMenu = (protyle: IProtyle, blockElement: HTMLElement, icon: "iconTrashcan", label: window.siyuan.languages.delete, click() { - const id = cellElement.getAttribute("data-id"); transaction(protyle, [{ action: "removeAttrViewCol", - id, - parentID: blockElement.getAttribute("data-av-id"), + id: colId, + parentID: avId, }], [{ action: "addAttrViewCol", name: cellElement.textContent.trim(), - parentID: blockElement.getAttribute("data-av-id"), + parentID: avId, type: type, - id + id: colId }]); removeCol(cellElement); } @@ -199,5 +204,9 @@ export const showHeaderCellMenu = (protyle: IProtyle, blockElement: HTMLElement, y: cellRect.bottom, h: cellRect.height }); - (window.siyuan.menus.menu.element.querySelector(".b3-text-field") as HTMLInputElement)?.select(); + const inputElement = window.siyuan.menus.menu.element.querySelector(".b3-text-field") as HTMLInputElement + if (inputElement) { + inputElement.select(); + inputElement.focus(); + } }; diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts new file mode 100644 index 000000000..2c20bf22b --- /dev/null +++ b/app/src/protyle/render/av/openMenuPanel.ts @@ -0,0 +1,103 @@ +import {Menu} from "../../../plugin/Menu"; +import {transaction} from "../../wysiwyg/transaction"; +import {fetchPost} from "../../../util/fetch"; +import {hideElements} from "../../ui/hideElements"; + +export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type: "properties" | "config" = "config") => { + let avMenuPanel = document.querySelector(".av__panel"); + if (avMenuPanel) { + avMenuPanel.remove(); + return; + } + window.siyuan.menus.menu.remove(); + fetchPost("/api/av/renderAttributeView", {id: blockElement.getAttribute("data-av-id")}, (response) => { + const data = response.data.av; + const tabRect = blockElement.querySelector(".layout-tab-bar").getBoundingClientRect() + let html + if (type === "config") { + html = `
+
+
+ + + + + +
+
` + } else if (type === "properties") { + html = `
+
+
+ + + + + +
+
` + } + document.body.insertAdjacentHTML("beforeend", html); + avMenuPanel = document.querySelector(".av__panel"); + avMenuPanel.addEventListener("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + let target = event.target as HTMLElement; + while (target && !target.isSameNode(avMenuPanel)) { + const type = target.dataset.type; + if (type === "close") { + avMenuPanel.remove(); + break; + } + target = target.parentElement; + } + }); + }); +} diff --git a/app/src/protyle/render/av/render.ts b/app/src/protyle/render/av/render.ts index 44a3690b5..7330e0e77 100644 --- a/app/src/protyle/render/av/render.ts +++ b/app/src/protyle/render/av/render.ts @@ -49,6 +49,9 @@ export const avRender = (element: Element, cb?: () => void) => {
`; row.cells.forEach((cell, index) => { + if (data.columns[index].hidden) { + return; + } let text: string; if (cell.valueType === "text") { text = cell.value?.text.content || ""; @@ -78,8 +81,21 @@ export const avRender = (element: Element, cb?: () => void) => { Table +
+ + + +
+ + + +
+ + + +
-
${data.title||""}
+
${data.title || ""}