diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index fb1b71e22..e6e4f0054 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -276,6 +276,8 @@ export const popTextCell = (protyle: IProtyle, cellElements: HTMLElement[], type updateCellValueByInput(protyle, type, cellElements); } else if (type === "relation") { openMenuPanel({protyle, blockElement, type: "relation", cellElements}); + } else if (type === "rollup") { + openMenuPanel({protyle, blockElement, type: "rollup", cellElements, colId: cellElements[0].dataset.colId}); } if (!hasClosestByClassName(cellElements[0], "custom-attr")) { cellElements[0].classList.add("av__cell--select"); @@ -644,8 +646,8 @@ export const renderCell = (cellValue: IAVCellValue, wrap: boolean) => { } else if (cellValue.type === "checkbox") { text += ``; } else if (cellValue.type === "rollup") { - cellValue?.rollup?.contents?.forEach((item) => { - text += renderCell(item, wrap); + cellValue?.rollup?.contents?.forEach((item, index) => { + text += renderRollup(item, wrap) + (index === cellValue.rollup.contents.length - 1 ? "" : " ,"); }); } else if (cellValue.type === "relation") { cellValue?.relation?.contents?.forEach((item, index) => { @@ -659,6 +661,71 @@ export const renderCell = (cellValue: IAVCellValue, wrap: boolean) => { return text; }; +const renderRollup = (cellValue: IAVCellValue, wrap: boolean) => { + let text = "" + if (["text", "template"].includes(cellValue.type)) { + text = `${cellValue ? (cellValue[cellValue.type as "text"].content || "") : ""}`; + } else if (["url", "email", "phone"].includes(cellValue.type)) { + const urlContent = cellValue ? cellValue[cellValue.type as "url"].content : ""; + // https://github.com/siyuan-note/siyuan/issues/9291 + let urlAttr = ""; + if (cellValue.type === "url") { + urlAttr = ` data-href="${urlContent}"`; + } + text = `${urlContent}`; + } else if (cellValue.type === "block") { + if (cellValue?.isDetached) { + text = `${cellValue.block.content || ""} +${window.siyuan.languages.more}`; + } else { + text = `${cellValue.block.content || ""} +${window.siyuan.languages.update}`; + } + } else if (cellValue.type === "number") { + text = `${cellValue?.number.formattedContent || cellValue?.number.content || ""}`; + } else if (cellValue.type === "mSelect" || cellValue.type === "select") { + cellValue?.mSelect?.forEach((item) => { + text += `${item.content}`; + }); + } else if (cellValue.type === "date") { + const dataValue = cellValue ? cellValue.date : null; + text = ``; + if (dataValue && dataValue.isNotEmpty) { + text += dayjs(dataValue.content).format(dataValue.isNotTime ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm"); + } + if (dataValue && dataValue.hasEndDate && dataValue.isNotEmpty && dataValue.isNotEmpty2) { + text += `${dayjs(dataValue.content2).format(dataValue.isNotTime ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm")}`; + } + text += ""; + } else if (["created", "updated"].includes(cellValue.type)) { + const dataValue = cellValue ? cellValue[cellValue.type as "date"] : null; + text = ``; + if (dataValue && dataValue.isNotEmpty) { + text += dayjs(dataValue.content).format("YYYY-MM-DD HH:mm"); + } + text += ""; + } else if (cellValue.type === "mAsset") { + cellValue?.mAsset?.forEach((item) => { + if (item.type === "image") { + text += ``; + } else { + text += `${item.name}`; + } + }); + } else if (cellValue.type === "checkbox") { + text += ``; + } else if (cellValue.type === "rollup") { + cellValue?.rollup?.contents?.forEach((item) => { + text += renderCell(item, wrap) + ''; + }); + } else if (cellValue.type === "relation") { + cellValue?.relation?.contents?.forEach((item, index) => { + text += `${item}`; + }); + } + return text; +} + export const updateHeaderCell = (cellElement: HTMLElement, headerValue: { icon?: string, name?: string, diff --git a/app/src/protyle/render/av/col.ts b/app/src/protyle/render/av/col.ts index 028324cf8..85abf8104 100644 --- a/app/src/protyle/render/av/col.ts +++ b/app/src/protyle/render/av/col.ts @@ -9,7 +9,7 @@ import {removeAttrViewColAnimation, updateAttrViewCellAnimation} from "./action" import {openEmojiPanel, unicode2Emoji} from "../../../emoji"; import {focusBlock} from "../../util/selection"; import {toggleUpdateRelationBtn} from "./relation"; -import {getNameByOperator} from "./calc"; +import {bindRollupEvent, getRollupHTML} from "./rollup"; export const duplicateCol = (options: { protyle: IProtyle, @@ -160,21 +160,7 @@ export const getEditHTML = (options: { `; } else if (colData.type === "rollup") { - html += ` - -`; + html += getRollupHTML({colData}); } return `
${html} @@ -364,36 +350,7 @@ export const bindEditEvent = (options: { toggleUpdateRelationBtn(options.menuElement, avID); } } - - const goSearchRollupColElement = options.menuElement.querySelector('[data-type="goSearchRollupCol"]') as HTMLElement; - if (goSearchRollupColElement) { - const oldValue = JSON.parse(goSearchRollupColElement.dataset.oldValue) as IAVCellRollupValue; - const goSearchRollupTargetElement = options.menuElement.querySelector('[data-type="goSearchRollupTarget"]') as HTMLElement; - let targetKeyAVId = "" - if (oldValue.relationKeyID) { - options.data.view.columns.find((item) => { - if (item.id === oldValue.relationKeyID) { - goSearchRollupColElement.querySelector(".b3-menu__accelerator").textContent = item.name; - targetKeyAVId = item.relation.avID; - goSearchRollupTargetElement.dataset.avId = targetKeyAVId; - return true; - } - }) - } - if (oldValue.keyID && targetKeyAVId) { - fetchPost("/api/av/getAttributeView", {id: targetKeyAVId}, (response) => { - response.data.av.keyValues.find((item: { key: { id: string, name: string, type: TAVCol } }) => { - if (item.key.id === oldValue.keyID) { - goSearchRollupTargetElement.querySelector('.b3-menu__accelerator').textContent = item.key.name; - const goSearchRollupCalcElement = options.menuElement.querySelector('[data-type="goSearchRollupCalc"]') as HTMLElement; - goSearchRollupCalcElement.dataset.colType = item.key.type; - goSearchRollupCalcElement.dataset.calc = oldValue.calc.operator; - return true; - } - }); - }); - } - } + bindRollupEvent(options); }; export const getColNameByType = (type: TAVCol) => { diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts index 10324e8f0..7c0504f94 100644 --- a/app/src/protyle/render/av/openMenuPanel.ts +++ b/app/src/protyle/render/av/openMenuPanel.ts @@ -27,15 +27,15 @@ import {focusBlock, getEditorRange} from "../../util/selection"; import {avRender} from "./render"; import {setPageSize} from "./row"; import {bindRelationEvent, getRelationHTML, openSearchAV, setRelationCell, updateRelation} from "./relation"; -import {goSearchRollupCol} from "./rollup"; +import {bindRollupEvent, getRollupHTML, goSearchRollupCol} from "./rollup"; import {updateCellsValue} from "./cell"; import {openCalcMenu} from "./calc"; export const openMenuPanel = (options: { protyle: IProtyle, blockElement: Element, - type: "select" | "properties" | "config" | "sorts" | "filters" | "edit" | "date" | "asset" | "switcher" | "relation", - colId?: string, // for edit + type: "select" | "properties" | "config" | "sorts" | "filters" | "edit" | "date" | "asset" | "switcher" | "relation" | "rollup", + colId?: string, // for edit, rollup cellElements?: HTMLElement[], // for select & date & relation & asset cb?: (avPanelElement: Element) => void }) => { @@ -70,6 +70,8 @@ export const openMenuPanel = (options: { html = getEditHTML({protyle: options.protyle, data, colId: options.colId}); } else if (options.type === "date") { html = getDateHTML(data.view, options.cellElements); + } else if (options.type === "rollup") { + html = `
${getRollupHTML({data, cellElements: options.cellElements})}
`; } else if (options.type === "relation") { html = getRelationHTML(data, options.cellElements); if (!html) { @@ -90,7 +92,7 @@ export const openMenuPanel = (options: { avPanelElement = document.querySelector(".av__panel"); const menuElement = avPanelElement.lastElementChild as HTMLElement; const tabRect = options.blockElement.querySelector(".av__views")?.getBoundingClientRect(); - if (["select", "date", "asset", "relation"].includes(options.type)) { + if (["select", "date", "asset", "relation", "rollup"].includes(options.type)) { const cellRect = options.cellElements[options.cellElements.length - 1].getBoundingClientRect(); if (options.type === "select") { bindSelectEvent(options.protyle, data, menuElement, options.cellElements, options.blockElement); @@ -115,8 +117,10 @@ export const openMenuPanel = (options: { }, Constants.TIMEOUT_LOAD); // 等待加载 } else if (options.type === "relation") { bindRelationEvent({protyle: options.protyle, data, menuElement, cellElements: options.cellElements}); + } else if (options.type === "rollup") { + bindRollupEvent({protyle: options.protyle, data, menuElement}); } - if (["select", "date", "relation"].includes(options.type)) { + if (["select", "date", "relation", "rollup"].includes(options.type)) { const inputElement = menuElement.querySelector("input"); if (inputElement) { inputElement.select(); @@ -787,7 +791,7 @@ export const openMenuPanel = (options: { data, isRelation: true, protyle: options.protyle, - colId: menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id") + colId: options.colId || menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id") }); event.preventDefault(); event.stopPropagation(); @@ -798,7 +802,7 @@ export const openMenuPanel = (options: { data, isRelation: false, protyle: options.protyle, - colId: menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id") + colId: options.colId || menuElement.querySelector(".b3-menu__item").getAttribute("data-col-id") }); event.preventDefault(); event.stopPropagation(); diff --git a/app/src/protyle/render/av/rollup.ts b/app/src/protyle/render/av/rollup.ts index fcccaaca3..40c278dad 100644 --- a/app/src/protyle/render/av/rollup.ts +++ b/app/src/protyle/render/av/rollup.ts @@ -8,6 +8,7 @@ import {genIconHTML} from "../util"; import {unicode2Emoji} from "../../../emoji"; import {getColIconByType} from "./col"; import {showMessage} from "../../../dialog/message"; +import {getNameByOperator} from "./calc"; const updateCol = (options: { target: HTMLElement, @@ -144,3 +145,68 @@ export const goSearchRollupCol = (options: { }); menu.element.querySelector(".b3-menu__items").setAttribute("style", "overflow: initial"); }; + +export const getRollupHTML = (options: { data?: IAV, cellElements?: HTMLElement[], colData?: IAVColumn }) => { + let colData: IAVColumn; + if (options.colData) { + colData = options.colData; + } else { + options.data.view.columns.find((item) => { + if (item.id === options.cellElements[0].dataset.colId) { + colData = item; + return true; + } + }); + } + return ` + +` +} + +export const bindRollupEvent = (options: { + protyle: IProtyle, + data: IAV, + menuElement: HTMLElement +}) => { + const goSearchRollupColElement = options.menuElement.querySelector('[data-type="goSearchRollupCol"]') as HTMLElement; + if (goSearchRollupColElement) { + const oldValue = JSON.parse(goSearchRollupColElement.dataset.oldValue) as IAVCellRollupValue; + const goSearchRollupTargetElement = options.menuElement.querySelector('[data-type="goSearchRollupTarget"]') as HTMLElement; + let targetKeyAVId = "" + if (oldValue.relationKeyID) { + options.data.view.columns.find((item) => { + if (item.id === oldValue.relationKeyID) { + goSearchRollupColElement.querySelector(".b3-menu__accelerator").textContent = item.name; + targetKeyAVId = item.relation.avID; + goSearchRollupTargetElement.dataset.avId = targetKeyAVId; + return true; + } + }) + } + if (oldValue.keyID && targetKeyAVId) { + fetchPost("/api/av/getAttributeView", {id: targetKeyAVId}, (response) => { + response.data.av.keyValues.find((item: { key: { id: string, name: string, type: TAVCol } }) => { + if (item.key.id === oldValue.keyID) { + goSearchRollupTargetElement.querySelector('.b3-menu__accelerator').textContent = item.key.name; + const goSearchRollupCalcElement = options.menuElement.querySelector('[data-type="goSearchRollupCalc"]') as HTMLElement; + goSearchRollupCalcElement.dataset.colType = item.key.type; + goSearchRollupCalcElement.dataset.calc = oldValue.calc.operator; + return true; + } + }); + }); + } + } +}