diff --git a/app/appearance/icons/index.html b/app/appearance/icons/index.html index 5e3915256..bb71128a4 100644 --- a/app/appearance/icons/index.html +++ b/app/appearance/icons/index.html @@ -56,7 +56,7 @@ - iconBoard + iconBoard
diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index 63de33254..8b9995c13 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -1,4 +1,5 @@ { + "useBackground": "填充列背景颜色", "print": "打印", "clickArrow": "点击箭头", "foldAll": "全部折叠", diff --git a/app/src/assets/scss/business/_av.scss b/app/src/assets/scss/business/_av.scss index 158ba692d..49994096c 100644 --- a/app/src/assets/scss/business/_av.scss +++ b/app/src/assets/scss/business/_av.scss @@ -972,6 +972,25 @@ transform: rotate(90deg); } } + + &__kanban { + overflow: auto; + gap: 16px; + padding: 0 1px 16px; + display: flex; + + &-group { + width: 260px; + + &--small { + width: 180px; + } + + &--big { + width: 320px; + } + } + } } img.av__cellassetimg { diff --git a/app/src/protyle/render/av/gallery/render.ts b/app/src/protyle/render/av/gallery/render.ts index 4418b5b86..f7ffa4b2e 100644 --- a/app/src/protyle/render/av/gallery/render.ts +++ b/app/src/protyle/render/av/gallery/render.ts @@ -368,3 +368,105 @@ export const renderGallery = async (options: { options.blockElement.querySelector(".av__gallery").classList.add("av__gallery--top"); } }; + +export const renderKanban = async (options: { + blockElement: HTMLElement, + protyle: IProtyle, + cb?: (data: IAV) => void, + renderAll: boolean, + data?: IAV, +}) => { + const searchInputElement = options.blockElement.querySelector('[data-type="av-search"]') as HTMLInputElement; + const editIds: IIds[] = []; + options.blockElement.querySelectorAll(".av__gallery-fields--edit").forEach(item => { + editIds.push({ + groupId: (hasClosestByClassName(item, "av__body") as HTMLElement).dataset.groupId || "", + fieldId: item.parentElement.getAttribute("data-id"), + }); + }); + const selectItemIds: IIds[] = []; + options.blockElement.querySelectorAll(".av__gallery-item--select").forEach(galleryItem => { + const fieldId = galleryItem.getAttribute("data-id"); + if (fieldId) { + selectItemIds.push({ + groupId: (hasClosestByClassName(galleryItem, "av__body") as HTMLElement).dataset.groupId || "", + fieldId + }); + } + }); + const pageSizes: { [key: string]: string } = {}; + options.blockElement.querySelectorAll(".av__body").forEach((item: HTMLElement) => { + pageSizes[item.dataset.groupId || "unGroup"] = item.dataset.pageSize; + }); + const resetData = { + isSearching: searchInputElement && document.activeElement === searchInputElement, + query: searchInputElement?.value || "", + alignSelf: options.blockElement.style.alignSelf, + oldOffset: options.protyle.contentElement.scrollTop, + editIds, + selectItemIds, + pageSizes, + }; + if (options.blockElement.firstElementChild.innerHTML === "") { + options.blockElement.style.alignSelf = ""; + options.blockElement.firstElementChild.outerHTML = `
+ + + +
`; + } + const created = options.protyle.options.history?.created; + const snapshot = options.protyle.options.history?.snapshot; + + let data: IAV = options.data; + if (!data) { + const avPageSize = getPageSize(options.blockElement); + const response = await fetchSyncPost(created ? "/api/av/renderHistoryAttributeView" : (snapshot ? "/api/av/renderSnapshotAttributeView" : "/api/av/renderAttributeView"), { + id: options.blockElement.getAttribute("data-av-id"), + created, + snapshot, + pageSize: avPageSize.unGroupPageSize, + groupPaging: avPageSize.groupPageSize, + viewID: options.blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW) || "", + query: resetData.query.trim() + }); + data = response.data; + } + if (data.viewType === "table") { + options.blockElement.setAttribute("data-av-type", "table"); + avRender(options.blockElement, options.protyle, options.cb, options.renderAll); + return; + } + const view: IAVGallery = data.view as IAVGallery; + let bodyHTML = "" + view.groups.forEach((group: IAVGallery) => { + if (group.groupHidden === 0) { + bodyHTML += `
+ ${getGroupTitleHTML(group, group.cards.length)} +
${getGalleryHTML(group)}
+
`; + } + }); + if (options.renderAll) { + options.blockElement.firstElementChild.outerHTML = `
+ ${genTabHeaderHTML(data, resetData.isSearching || !!resetData.query, !options.protyle.disabled && !hasClosestByAttribute(options.blockElement, "data-type", "NodeBlockQueryEmbed"))} +
+ ${bodyHTML} +
+
${Constants.ZWSP}
+
`; + } else { + options.blockElement.querySelector(".av__kanban").innerHTML = bodyHTML; + } + afterRenderGallery({ + resetData, + renderAll: options.renderAll, + data, + cb: options.cb, + protyle: options.protyle, + blockElement: options.blockElement, + }); + if (view.hideAttrViewName) { + options.blockElement.querySelector(".av__gallery").classList.add("av__gallery--top"); + } +}; diff --git a/app/src/protyle/render/av/layout.ts b/app/src/protyle/render/av/layout.ts index c6e0fb7d0..915bee70d 100644 --- a/app/src/protyle/render/av/layout.ts +++ b/app/src/protyle/render/av/layout.ts @@ -7,7 +7,7 @@ import {getFieldsByData} from "./view"; export const getLayoutHTML = (data: IAV) => { let html = ""; const view = data.view as IAVGallery; - if (data.viewType === "gallery") { + if (data.viewType === "gallery" || data.viewType === "kanban") { let coverFromTitle = ""; if (view.coverFrom === 0) { coverFromTitle = window.siyuan.languages.calcOperatorNone; @@ -52,7 +52,7 @@ export const getLayoutHTML = (data: IAV) => { `; } - return `
+ html = `
+
+ +
+
${window.siyuan.languages.kanban}
+
@@ -90,8 +95,21 @@ export const getLayoutHTML = (data: IAV) => { ${window.siyuan.languages.wrapAllFields} - - +`; + } + return html + `