diff --git a/app/src/assets/scss/business/_av.scss b/app/src/assets/scss/business/_av.scss
index de33d0a37..6e86215e6 100644
--- a/app/src/assets/scss/business/_av.scss
+++ b/app/src/assets/scss/business/_av.scss
@@ -191,13 +191,6 @@
opacity: 1;
background-color: var(--b3-theme-background-light) !important;
}
-
- .av__cellassetimg {
- max-height: 24px;
- border-radius: var(--b3-border-radius);
- margin: 1px 2px;
- max-width: none;
- }
}
&__cellheader {
@@ -352,4 +345,10 @@
}
}
+img.av__cellassetimg {
+ max-height: 24px;
+ border-radius: var(--b3-border-radius);
+ margin: 1px 2px;
+ max-width: none;
+}
diff --git a/app/src/menus/commonMenuItem.ts b/app/src/menus/commonMenuItem.ts
index f13124a22..8e9049a94 100644
--- a/app/src/menus/commonMenuItem.ts
+++ b/app/src/menus/commonMenuItem.ts
@@ -19,7 +19,7 @@ import * as dayjs from "dayjs";
import {Constants} from "../constants";
import {exportImage} from "../protyle/export/util";
import {App} from "../index";
-import {renderAVAttribute} from "../protyle/render/av/render";
+import {renderAVAttribute} from "../protyle/render/av/blockAttr";
const bindAttrInput = (inputElement: HTMLInputElement, id: string) => {
inputElement.addEventListener("change", () => {
diff --git a/app/src/protyle/render/av/blockAttr.ts b/app/src/protyle/render/av/blockAttr.ts
new file mode 100644
index 000000000..1ee8498dc
--- /dev/null
+++ b/app/src/protyle/render/av/blockAttr.ts
@@ -0,0 +1,278 @@
+import {fetchPost} from "../../../util/fetch";
+import {getColIconByType} from "./col";
+import {escapeAttr} from "../../../util/escape";
+import {hasClosestByAttribute} from "../../util/hasClosest";
+import {Menu} from "../../../plugin/Menu";
+import {Constants} from "../../../constants";
+import * as dayjs from "dayjs";
+
+const genAVValueHTML = (value: IAVCellValue) => {
+ let html = "";
+ switch (value.type) {
+ case "text":
+ html = ``;
+ break;
+ case "number":
+ html = ``;
+ break;
+ case "mSelect":
+ case "select":
+ value.mSelect?.forEach(item => {
+ html += `${item.content}`;
+ });
+ break;
+ case "mAsset":
+ value.mAsset?.forEach(item => {
+ if (item.type === "image") {
+ html += `
`;
+ } else {
+ html += `${item.name}`;
+ }
+ });
+ break;
+ case "date":
+ if (value.date.isNotEmpty) {
+ html = `${dayjs(value.date.content).format("YYYY-MM-DD HH:mm")}`;
+ }
+ if (value.date.hasEndDate && value.date.isNotEmpty2 && value.date.isNotEmpty) {
+ html += `${dayjs(value.date.content2).format("YYYY-MM-DD HH:mm")}`;
+ }
+ break;
+ case "url":
+ html = `
+
+`;
+ break;
+ case "phone":
+ html = `
+
+`;
+ break;
+ case "email":
+ html = `
+
+`;
+ break;
+ }
+ return html;
+};
+
+export const renderAVAttribute = (element: HTMLElement, id: string) => {
+ fetchPost("/api/av/getAttributeViewKeys", {id}, (response) => {
+ let html = "";
+ response.data.forEach((table: {
+ keyValues: {
+ key: {
+ type: TAVCol,
+ name: string,
+ options?: { name: string, color: string }[]
+ },
+ values: { keyID: string, id: string, blockID: string, type?: TAVCol & IAVCellValue } []
+ }[],
+ avID: string
+ avName: string
+ }) => {
+ html += `
`;
+ table.keyValues?.forEach(item => {
+ html += `
+
+
+ ${item.key.name}
+
+
+ ${genAVValueHTML(item.values[0])}
+
+
`;
+ });
+ });
+ element.innerHTML = html;
+ element.addEventListener("click", (event) => {
+ const target = event.target as HTMLElement;
+ const dateElement = hasClosestByAttribute(target, "data-type", "date");
+ if (dateElement) {
+ const dateMenu = new Menu("custom-attr-av-date", () => {
+ const textElements = window.siyuan.menus.menu.element.querySelectorAll(".b3-text-field") as NodeListOf;
+ const hasEndDate = (window.siyuan.menus.menu.element.querySelector(".b3-switch") as HTMLInputElement).checked;
+ fetchPost("/api/av/setAttributeViewBlockAttr", {
+ avID: dateElement.dataset.avId,
+ keyID: dateElement.dataset.keyId,
+ rowID: dateElement.dataset.blockId,
+ cellID: dateElement.dataset.id,
+ value: {
+ date: {
+ isNotEmpty: textElements[0].value !== "",
+ isNotEmpty2: textElements[1].value !== "",
+ content: new Date(textElements[0].value).getTime(),
+ content2: new Date(textElements[1].value).getTime(),
+ hasEndDate
+ }
+ }
+ });
+ let dataHTML = "";
+ if (textElements[0].value !== "") {
+ dataHTML = `${dayjs(textElements[0].value).format("YYYY-MM-DD HH:mm")}`;
+ }
+ if (hasEndDate && textElements[0].value !== "" && textElements[1].value !== "") {
+ dataHTML += `${dayjs(textElements[1].value).format("YYYY-MM-DD HH:mm")}`;
+ }
+ dateElement.innerHTML = dataHTML;
+ });
+ if (dateMenu.isOpen) {
+ return;
+ }
+ const hasEndDate = dateElement.querySelector("svg");
+ const timeElements = dateElement.querySelectorAll("span");
+ dateMenu.addItem({
+ iconHTML: "",
+ label: ``
+ });
+ dateMenu.addItem({
+ iconHTML: "",
+ label: ``
+ });
+ dateMenu.addSeparator();
+ dateMenu.addItem({
+ iconHTML: "",
+ label: ``,
+ click(element, event) {
+ const switchElement = element.querySelector(".b3-switch") as HTMLInputElement;
+ if ((event.target as HTMLElement).tagName !== "INPUT") {
+ switchElement.checked = !switchElement.checked;
+ } else {
+ switchElement.outerHTML = ``;
+ }
+ window.siyuan.menus.menu.element.querySelectorAll('[type="datetime-local"]')[1].classList.toggle("fn__none");
+ return true;
+ }
+ });
+ dateMenu.addSeparator();
+ dateMenu.addItem({
+ icon: "iconTrashcan",
+ label: window.siyuan.languages.clear,
+ click() {
+ const textElements = window.siyuan.menus.menu.element.querySelectorAll(".b3-text-field") as NodeListOf;
+ textElements[0].value = "";
+ textElements[1].value = "";
+ (window.siyuan.menus.menu.element.querySelector(".b3-switch") as HTMLInputElement).checked = false;
+ }
+ });
+ const datetRect = dateElement.getBoundingClientRect();
+ dateMenu.open({
+ x: datetRect.left,
+ y: datetRect.bottom
+ });
+ event.stopPropagation();
+ event.preventDefault();
+ return;
+ }
+ const mSelectElement = hasClosestByAttribute(target, "data-type", "select") || hasClosestByAttribute(target, "data-type", "mSelect");
+ if (mSelectElement) {
+ const mSelectMenu = new Menu("custom-attr-av-select", () => {
+ const mSelect: { content: string, color: string }[] = [];
+ let mSelectHTML = "";
+ window.siyuan.menus.menu.element.querySelectorAll(".svg").forEach(item => {
+ const chipElement = item.parentElement.previousElementSibling.firstElementChild as HTMLElement;
+ const content = chipElement.textContent.trim();
+ const color = chipElement.dataset.color;
+ mSelect.push({
+ content,
+ color
+ });
+ mSelectHTML += `${content}`;
+ });
+ fetchPost("/api/av/setAttributeViewBlockAttr", {
+ avID: mSelectElement.dataset.avId,
+ keyID: mSelectElement.dataset.keyId,
+ rowID: mSelectElement.dataset.blockId,
+ cellID: mSelectElement.dataset.id,
+ value: {
+ mSelect
+ }
+ });
+ mSelectElement.innerHTML = mSelectHTML;
+ });
+ if (mSelectMenu.isOpen) {
+ return;
+ }
+ const names: string[] = [];
+ mSelectElement.querySelectorAll(".b3-chip").forEach(item => {
+ names.push(item.textContent.trim());
+ });
+ JSON.parse(mSelectElement.dataset.options || "").forEach((item: { name: string, color: string }) => {
+ mSelectMenu.addItem({
+ iconHTML: "",
+ label: `
+ ${item.name}
+`,
+ accelerator: names.includes(item.name) ? '' : Constants.ZWSP,
+ click(element) {
+ const acceleratorElement = element.querySelector(".b3-menu__accelerator");
+ if (mSelectElement.dataset.type === "select") {
+ window.siyuan.menus.menu.element.querySelectorAll(".b3-menu__accelerator").forEach(itemElement => {
+ if (itemElement.isSameNode(acceleratorElement)) {
+ if (acceleratorElement.querySelector("svg")) {
+ acceleratorElement.innerHTML = "";
+ } else {
+ acceleratorElement.innerHTML = '';
+ }
+ } else {
+ itemElement.innerHTML = "";
+ }
+ });
+ return false;
+ }
+ if (acceleratorElement.querySelector("svg")) {
+ acceleratorElement.innerHTML = "";
+ } else {
+ acceleratorElement.innerHTML = '';
+ }
+ return true;
+ }
+ });
+ });
+ const mSelecttRect = mSelectElement.getBoundingClientRect();
+ mSelectMenu.open({
+ x: mSelecttRect.left,
+ y: mSelecttRect.bottom
+ });
+ event.stopPropagation();
+ event.preventDefault();
+ return;
+ }
+ });
+ element.querySelectorAll(".b3-text-field--text").forEach((item: HTMLInputElement) => {
+ item.addEventListener("change", () => {
+ let value;
+ if (["url", "text", "email", "phone"].includes(item.parentElement.dataset.type)) {
+ value = {
+ [item.parentElement.dataset.type]: {
+ content: item.value
+ }
+ };
+ } else if (item.parentElement.dataset.type === "number") {
+ value = {
+ number: {
+ content: parseFloat(item.value)
+ }
+ };
+ }
+ fetchPost("/api/av/setAttributeViewBlockAttr", {
+ avID: item.parentElement.dataset.avId,
+ keyID: item.parentElement.dataset.keyId,
+ rowID: item.parentElement.dataset.blockId,
+ cellID: item.parentElement.dataset.id,
+ value
+ });
+ });
+ });
+ });
+};
diff --git a/app/src/protyle/render/av/render.ts b/app/src/protyle/render/av/render.ts
index 405a1ea91..e563f9fe3 100644
--- a/app/src/protyle/render/av/render.ts
+++ b/app/src/protyle/render/av/render.ts
@@ -3,9 +3,6 @@ import {getColIconByType} from "./col";
import {Constants} from "../../../constants";
import {getCalcValue} from "./cell";
import * as dayjs from "dayjs";
-import {hasClosestByAttribute} from "../../util/hasClosest";
-import {Menu} from "../../../plugin/Menu";
-import {escapeAttr} from "../../../util/escape";
export const avRender = (element: Element, protyle: IProtyle, cb?: () => void) => {
let avElements: Element[] = [];
@@ -213,265 +210,3 @@ export const refreshAV = (protyle: IProtyle, operation: IOperation) => {
lastParentID = null;
}, Constants.TIMEOUT_TRANSITION);
};
-
-const genAVValueHTML = (value: IAVCellValue) => {
- let html = "";
- switch (value.type) {
- case "text":
- html = ``;
- break;
- case "number":
- html = ``;
- break;
- case "mSelect":
- case "select":
- value.mSelect?.forEach(item => {
- html += `${item.content}`;
- });
- break;
- case "date":
- if (value.date.isNotEmpty) {
- html = `${dayjs(value.date.content).format("YYYY-MM-DD HH:mm")}`;
- }
- if (value.date.hasEndDate && value.date.isNotEmpty2 && value.date.isNotEmpty) {
- html += `${dayjs(value.date.content2).format("YYYY-MM-DD HH:mm")}`;
- }
- break;
- case "url":
- html = `
-
-`;
- break;
- case "phone":
- html = `
-
-`;
- break;
- case "email":
- html = `
-
-`;
- break;
- }
- return html;
-};
-
-export const renderAVAttribute = (element: HTMLElement, id: string) => {
- fetchPost("/api/av/getAttributeViewKeys", {id}, (response) => {
- let html = "";
- response.data.forEach((table: {
- keyValues: {
- key: {
- type: TAVCol,
- name: string,
- options?: { name: string, color: string }[]
- },
- values: { keyID: string, id: string, blockID: string, type?: TAVCol & IAVCellValue } []
- }[],
- avID: string
- avName: string
- }) => {
- html += ``;
- table.keyValues?.forEach(item => {
- html += `
-
-
- ${item.key.name}
-
-
- ${genAVValueHTML(item.values[0])}
-
-
`;
- });
- });
- element.innerHTML = html;
- element.addEventListener("click", (event) => {
- const target = event.target as HTMLElement;
- const dateElement = hasClosestByAttribute(target, "data-type", "date");
- if (dateElement) {
- const dateMenu = new Menu("custom-attr-av-date", () => {
- const textElements = window.siyuan.menus.menu.element.querySelectorAll(".b3-text-field") as NodeListOf;
- const hasEndDate = (window.siyuan.menus.menu.element.querySelector(".b3-switch") as HTMLInputElement).checked;
- fetchPost("/api/av/setAttributeViewBlockAttr", {
- avID: dateElement.dataset.avId,
- keyID: dateElement.dataset.keyId,
- rowID: dateElement.dataset.blockId,
- cellID: dateElement.dataset.id,
- value: {
- date: {
- isNotEmpty: textElements[0].value !== "",
- isNotEmpty2: textElements[1].value !== "",
- content: new Date(textElements[0].value).getTime(),
- content2: new Date(textElements[1].value).getTime(),
- hasEndDate
- }
- }
- });
- let dataHTML = "";
- if (textElements[0].value !== "") {
- dataHTML = `${dayjs(textElements[0].value).format("YYYY-MM-DD HH:mm")}`;
- }
- if (hasEndDate && textElements[0].value !== "" && textElements[1].value !== "") {
- dataHTML += `${dayjs(textElements[1].value).format("YYYY-MM-DD HH:mm")}`;
- }
- dateElement.innerHTML = dataHTML;
- });
- if (dateMenu.isOpen) {
- return;
- }
- const hasEndDate = dateElement.querySelector("svg");
- const timeElements = dateElement.querySelectorAll("span");
- dateMenu.addItem({
- iconHTML: "",
- label: ``
- });
- dateMenu.addItem({
- iconHTML: "",
- label: ``
- });
- dateMenu.addSeparator();
- dateMenu.addItem({
- iconHTML: "",
- label: ``,
- click(element, event) {
- const switchElement = element.querySelector(".b3-switch") as HTMLInputElement;
- if ((event.target as HTMLElement).tagName !== "INPUT") {
- switchElement.checked = !switchElement.checked;
- } else {
- switchElement.outerHTML = ``;
- }
- window.siyuan.menus.menu.element.querySelectorAll('[type="datetime-local"]')[1].classList.toggle("fn__none");
- return true;
- }
- });
- dateMenu.addSeparator();
- dateMenu.addItem({
- icon: "iconTrashcan",
- label: window.siyuan.languages.clear,
- click() {
- const textElements = window.siyuan.menus.menu.element.querySelectorAll(".b3-text-field") as NodeListOf;
- textElements[0].value = "";
- textElements[1].value = "";
- (window.siyuan.menus.menu.element.querySelector(".b3-switch") as HTMLInputElement).checked = false;
- }
- });
- const datetRect = dateElement.getBoundingClientRect();
- dateMenu.open({
- x: datetRect.left,
- y: datetRect.bottom
- });
- event.stopPropagation();
- event.preventDefault();
- return;
- }
- const mSelectElement = hasClosestByAttribute(target, "data-type", "select") || hasClosestByAttribute(target, "data-type", "mSelect");
- if (mSelectElement) {
- const mSelectMenu = new Menu("custom-attr-av-select", () => {
- const mSelect: { content: string, color: string }[] = [];
- let mSelectHTML = "";
- window.siyuan.menus.menu.element.querySelectorAll(".svg").forEach(item => {
- const chipElement = item.parentElement.previousElementSibling.firstElementChild as HTMLElement;
- const content = chipElement.textContent.trim();
- const color = chipElement.dataset.color;
- mSelect.push({
- content,
- color
- });
- mSelectHTML += `${content}`;
- });
- fetchPost("/api/av/setAttributeViewBlockAttr", {
- avID: mSelectElement.dataset.avId,
- keyID: mSelectElement.dataset.keyId,
- rowID: mSelectElement.dataset.blockId,
- cellID: mSelectElement.dataset.id,
- value: {
- mSelect
- }
- });
- mSelectElement.innerHTML = mSelectHTML;
- });
- if (mSelectMenu.isOpen) {
- return;
- }
- const names: string[] = [];
- mSelectElement.querySelectorAll(".b3-chip").forEach(item => {
- names.push(item.textContent.trim());
- });
- JSON.parse(mSelectElement.dataset.options || "").forEach((item: { name: string, color: string }) => {
- mSelectMenu.addItem({
- iconHTML: "",
- label: `
- ${item.name}
-`,
- accelerator: names.includes(item.name) ? '' : Constants.ZWSP,
- click(element) {
- const acceleratorElement = element.querySelector(".b3-menu__accelerator");
- if (mSelectElement.dataset.type === "select") {
- window.siyuan.menus.menu.element.querySelectorAll(".b3-menu__accelerator").forEach(itemElement => {
- if (itemElement.isSameNode(acceleratorElement)) {
- if (acceleratorElement.querySelector("svg")) {
- acceleratorElement.innerHTML = "";
- } else {
- acceleratorElement.innerHTML = '';
- }
- } else {
- itemElement.innerHTML = "";
- }
- });
- return false;
- }
- if (acceleratorElement.querySelector("svg")) {
- acceleratorElement.innerHTML = "";
- } else {
- acceleratorElement.innerHTML = '';
- }
- return true;
- }
- });
- });
- const mSelecttRect = mSelectElement.getBoundingClientRect();
- mSelectMenu.open({
- x: mSelecttRect.left,
- y: mSelecttRect.bottom
- });
- event.stopPropagation();
- event.preventDefault();
- return;
- }
- });
- element.querySelectorAll(".b3-text-field--text").forEach((item: HTMLInputElement) => {
- item.addEventListener("change", () => {
- let value;
- if (["url", "text", "email", "phone"].includes(item.parentElement.dataset.type)) {
- value = {
- [item.parentElement.dataset.type]: {
- content: item.value
- }
- };
- } else if (item.parentElement.dataset.type === "number") {
- value = {
- number: {
- content: parseFloat(item.value)
- }
- };
- }
- fetchPost("/api/av/setAttributeViewBlockAttr", {
- avID: item.parentElement.dataset.avId,
- keyID: item.parentElement.dataset.keyId,
- rowID: item.parentElement.dataset.blockId,
- cellID: item.parentElement.dataset.id,
- value
- });
- });
- });
- });
-};