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 += `
+ +
+ ${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 += `
- -
- ${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 - }); - }); - }); - }); -};