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}
`,
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 || ""}