Browse Source

:art: fix https://github.com/siyuan-note/siyuan/issues/10142

Vanessa 1 year ago
parent
commit
ad39590205

+ 6 - 9
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;
     }
   }
 

+ 35 - 11
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 += `<div data-av-id="${table.avID}" data-node-id="${id}" data-type="NodeAttributeView">
-<div class="fn__flex custom-attr__avheader">
-    <div class="block__logo popover__block" data-id='${JSON.stringify(table.blockIDs)}'>
-        <svg class="block__logoicon"><use xlink:href="#iconDatabase"></use></svg><span>${table.avName || window.siyuan.languages.database}</span>
-    </div>
+<div class="custom-attr__avheader block__logo popover__block" data-id='${JSON.stringify(table.blockIDs)}'>
+    <div class="fn__flex-1"></div>
+    <svg class="block__logoicon"><use xlink:href="#iconDatabase"></use></svg><span>${table.avName || window.siyuan.languages.database}</span>
     <div class="fn__flex-1"></div>
-    <button data-type="addColumn" class="b3-button b3-button--outline"><svg><use xlink:href="#iconAdd"></use></svg>${window.siyuan.languages.addAttr}</button>
 </div>`;
             table.keyValues?.forEach(item => {
-                html += `<div class="block__icons av__row" data-id="${id}" data-col-id="${item.key.id}">
+                html += `<div class="block__icons av__row" data-col-id="${item.key.id}">
     <div class="block__icon" draggable="true"><svg><use xlink:href="#iconDrag"></use></svg></div>
-    <div class="block__logo ariaLabel" data-position="parentW" aria-label="${escapeAttr(item.key.name)}"">
+    <div class="block__logo ariaLabel${item.values[0].type === "block" ? "" : " fn__pointer"}" data-type="editCol" data-position="parentW" aria-label="${escapeAttr(item.key.name)}"">
         ${item.key.icon ? unicode2Emoji(item.key.icon, "block__logoicon", true) : `<svg class="block__logoicon"><use xlink:href="#${getColIconByType(item.key.type)}"></use></svg>`}
         <span>${item.key.name}</span>
     </div>
@@ -175,7 +174,12 @@ class="fn__flex-1 fn__flex${["url", "text", "number", "email", "phone", "block"]
     </div>
 </div>`;
             });
-            html += "</div>";
+            html += `<div class="fn__hr"></div>
+<div class="fn__flex">
+    <div class="fn__flex-1"></div>
+    <button data-type="addColumn" class="b3-button b3-button--outline"><svg><use xlink:href="#iconAdd"></use></svg>${window.siyuan.languages.addAttr}</button>
+    <div class="fn__space"></div>
+</div></div>`;
         });
         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);
+        }
     });
 };

+ 18 - 6
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 = `<button class="b3-menu__item" data-type="nobg" data-col-id="${options.colId}">
-    <span class="block__icon" style="padding: 8px;margin-left: -4px;" data-type="go-properties">
+    <span class="block__icon${options.isCustomAttr ? " fn__none" : ""}" style="padding: 8px;margin-left: -4px;" data-type="go-properties">
         <svg><use xlink:href="#iconLeft"></use></svg>
     </span>
     <span class="b3-menu__label ft__center">${window.siyuan.languages.edit}</span>
@@ -165,7 +166,7 @@ export const getEditHTML = (options: {
     return `<div class="b3-menu__items">
     ${html}
     <button class="b3-menu__separator"></button>
-    <button class="b3-menu__item" data-type="${colData.hidden ? "showCol" : "hideCol"}">
+    <button class="b3-menu__item${options.isCustomAttr ? " fn__none" : ""}" data-type="${colData.hidden ? "showCol" : "hideCol"}">
         <svg class="b3-menu__icon" style=""><use xlink:href="#icon${colData.hidden ? "Eye" : "Eyeoff"}"></use></svg>
         <span class="b3-menu__label">${colData.hidden ? window.siyuan.languages.showCol : window.siyuan.languages.hideCol}</span>
     </button>
@@ -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();
             }
         });

+ 29 - 21
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: {
 </div>`);
         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) : `<svg><use xlink:href="#${getColIconByType(target.dataset.colType as TAVCol)}"></use></svg>`;
-                        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) : `<svg class="block__logoicon"><use xlink:href="#${getColIconByType(iconElement.nextElementSibling.getAttribute("data-type") as TAVCol)}"></use></svg>`;
+                        } 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;

+ 9 - 6
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));

+ 7 - 7
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 => {

+ 1 - 1
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);