import {fetchPost} from "../../../util/fetch"; import {getColIconByType, showColMenu} 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, cb?: () => void) => { let avElements: Element[] = []; if (element.getAttribute("data-type") === "NodeAttributeView") { // 编辑器内代码块编辑渲染 avElements = [element]; } else { avElements = Array.from(element.querySelectorAll('[data-type="NodeAttributeView"]')); } if (avElements.length === 0) { return; } if (avElements.length > 0) { avElements.forEach((e: HTMLElement) => { if (e.getAttribute("data-render") === "true") { return; } const left = e.querySelector(".av__scroll")?.scrollLeft || 0; fetchPost("/api/av/renderAttributeView", { id: e.getAttribute("data-av-id"), nodeID: e.getAttribute("data-node-id") }, (response) => { const data = response.data.view as IAVTable; // header let tableHTML = '
'; let calcHTML = ""; data.columns.forEach((column: IAVColumn) => { if (column.hidden) { return; } tableHTML += `
${column.name}
`; calcHTML += `
${getCalcValue(column) || '' + window.siyuan.languages.calc}
`; }); tableHTML += `
`; // body data.rows.forEach((row: IAVRow) => { tableHTML += `
`; row.cells.forEach((cell, index) => { if (data.columns[index].hidden) { return; } let text = ""; if (cell.valueType === "text") { text = `${cell.value?.text.content || ""}`; } else if (["url", "email", "phone"].includes(cell.valueType)) { text = `${cell.value ? cell.value[cell.valueType as "url"].content : ""}`; if (cell.value && cell.value[cell.valueType as "url"].content) { text += ``; } } else if (cell.valueType === "block") { text = `${cell.value?.block.content || ""}`; if (cell.value?.block.id) { text += `${window.siyuan.languages.openBy}`; } } else if (cell.valueType === "number") { text = `${cell.value?.number.formattedContent || ""}`; } else if (cell.valueType === "mSelect" || cell.valueType === "select") { cell.value?.mSelect?.forEach((item: { content: string, color: string }) => { text += `${item.content}`; }); if (!text) { text = ''; } else { text = `${text}`; } } else if (cell.valueType === "date") { text = ''; if (cell.value?.date.isNotEmpty) { text += dayjs(cell.value.date.content).format("YYYY-MM-DD HH:mm"); } if (cell.value?.date.hasEndDate && cell.value?.date.isNotEmpty && cell.value?.date.isNotEmpty2) { text += `${dayjs(cell.value.date.content2).format("YYYY-MM-DD HH:mm")}`; } text += ""; } tableHTML += `
${text}
`; }); tableHTML += "
"; }); let tabHTML = ""; response.data.views.forEach((item: IAVView) => { tabHTML += `
${item.name}
`; }); const paddingLeft = e.parentElement.style.paddingLeft; const paddingRight = e.parentElement.style.paddingRight; e.style.width = e.parentElement.clientWidth + "px"; e.style.alignSelf = "center"; e.firstElementChild.outerHTML = `
${tabHTML}
${response.data.name || ""}
${tableHTML}
${window.siyuan.languages.addAttr}
`; e.setAttribute("data-render", "true"); e.querySelector(".av__scroll").scrollLeft = left; if (cb) { cb(); } }); }); } }; let lastParentID: string; let lastElement: HTMLElement; export const refreshAV = (protyle: IProtyle, operation: IOperation) => { if (lastParentID === operation.parentID && protyle.contentElement.isSameNode(lastElement)) { return; } lastElement = protyle.contentElement; lastParentID = operation.parentID; const avId = operation.avID; if (operation.action === "addAttrViewCol") { Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-av-id="${avId}"]`)).forEach((item: HTMLElement) => { item.removeAttribute("data-render"); avRender(item, () => { showColMenu(protyle, item, item.querySelector(`.av__row--header .av__cell[data-col-id="${operation.id}"]`)); }); }); } else if (operation.action === "setAttrViewColWidth") { Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-av-id="${avId}"]`)).forEach((item: HTMLElement) => { const cellElement = item.querySelector(`.av__cell[data-col-id="${operation.id}"]`) as HTMLElement; if (!cellElement || cellElement.style.width === operation.data) { return; } item.querySelectorAll(".av__row").forEach(rowItem => { (rowItem.querySelector(`[data-col-id="${operation.id}"]`) as HTMLElement).style.width = operation.data; }); }); } else if (operation.action === "setAttrViewName") { Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-av-id="${avId}"]`)).forEach((item: HTMLElement) => { const titleElement = item.querySelector(".av__title") as HTMLElement; if (!titleElement || titleElement.textContent.trim() === operation.data) { return; } titleElement.textContent = operation.data; titleElement.dataset.title = operation.data; }); } else { Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-av-id="${avId}"]`)).forEach((item: HTMLElement) => { item.removeAttribute("data-render"); avRender(item); }); } setTimeout(() => { 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 }); }); }); }); };