mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-16 14:40:12 +01:00
This commit is contained in:
parent
b1a00c6ebd
commit
a0b238075d
8 changed files with 174 additions and 7 deletions
|
|
@ -56,7 +56,7 @@
|
|||
<svg>
|
||||
<use xlink:href="#iconBoard"></use>
|
||||
</svg>
|
||||
<del>iconBoard</del>
|
||||
iconBoard
|
||||
</div>
|
||||
<div>
|
||||
<svg>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"useBackground": "填充列背景颜色",
|
||||
"print": "打印",
|
||||
"clickArrow": "点击箭头",
|
||||
"foldAll": "全部折叠",
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 = `<div class="av__kanban fn__flex">
|
||||
<span style="width: 260px;height: 178px;" class="av__pulse"></span>
|
||||
<span style="width: 260px;height: 178px;" class="av__pulse"></span>
|
||||
<span style="width: 260px;height: 178px;" class="av__pulse"></span>
|
||||
</div>`;
|
||||
}
|
||||
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 += `<div class="av__kanban-group">
|
||||
${getGroupTitleHTML(group, group.cards.length)}
|
||||
<div data-group-id="${group.id}" data-page-size="${group.pageSize}" data-dtype="${group.groupKey.type}" data-content="${Lute.EscapeHTMLStr(group.groupValue.text?.content)}" class="av__body${group.groupFolded ? " fn__none" : ""}">${getGalleryHTML(group)}</div>
|
||||
</div>`;
|
||||
}
|
||||
});
|
||||
if (options.renderAll) {
|
||||
options.blockElement.firstElementChild.outerHTML = `<div class="av__container fn__block">
|
||||
${genTabHeaderHTML(data, resetData.isSearching || !!resetData.query, !options.protyle.disabled && !hasClosestByAttribute(options.blockElement, "data-type", "NodeBlockQueryEmbed"))}
|
||||
<div class="av__kanban">
|
||||
${bodyHTML}
|
||||
</div>
|
||||
<div class="av__cursor" contenteditable="true">${Constants.ZWSP}</div>
|
||||
</div>`;
|
||||
} 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");
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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) => {
|
|||
<input data-type="toggle-gallery-name" type="checkbox" class="b3-switch b3-switch--menu" ${view.displayFieldName ? "checked" : ""}>
|
||||
</label>`;
|
||||
}
|
||||
return `<div class="b3-menu__items">
|
||||
html = `<div class="b3-menu__items">
|
||||
<div class="b3-menu__items">
|
||||
<button class="b3-menu__item" data-type="nobg">
|
||||
<span class="block__icon" style="padding: 8px;margin-left: -4px;" data-type="go-config">
|
||||
|
|
@ -68,6 +68,11 @@ export const getLayoutHTML = (data: IAV) => {
|
|||
<div class="fn__hr"></div>
|
||||
<div>${window.siyuan.languages.table}</div>
|
||||
</div>
|
||||
<div data-type="set-layout" data-view-type="kanban" class="av__layout-item${data.viewType === "kanban" ? " av__layout-item--select" : ""}">
|
||||
<svg><use xlink:href="#iconBoard"></use></svg>
|
||||
<div class="fn__hr"></div>
|
||||
<div>${window.siyuan.languages.kanban}</div>
|
||||
</div>
|
||||
<div data-type="set-layout" data-view-type="gallery" class="av__layout-item${data.viewType === "gallery" ? " av__layout-item--select" : ""}">
|
||||
<svg><use xlink:href="#iconGallery"></use></svg>
|
||||
<div class="fn__hr"></div>
|
||||
|
|
@ -90,8 +95,21 @@ export const getLayoutHTML = (data: IAV) => {
|
|||
<span class="fn__flex-center">${window.siyuan.languages.wrapAllFields}</span>
|
||||
<span class="fn__space fn__flex-1"></span>
|
||||
<input data-type="toggle-entries-wrap" type="checkbox" class="b3-switch b3-switch--menu" ${view.wrapField ? "checked" : ""}>
|
||||
</label>
|
||||
<button class="b3-menu__item" data-type="set-page-size" data-size="${view.pageSize}">
|
||||
</label>`;
|
||||
if (data.viewType === "kanban") {
|
||||
html += `<button class="b3-menu__item" data-type="set-kanban-group">
|
||||
<span class="fn__flex-center">${window.siyuan.languages.groups}</span>
|
||||
<span class="fn__flex-1"></span>
|
||||
<span class="b3-menu__accelerator">${view.cardSize === 0 ? window.siyuan.languages.small : (view.cardSize === 1 ? window.siyuan.languages.medium : window.siyuan.languages.large)}</span>
|
||||
<svg class="b3-menu__icon b3-menu__icon--small"><use xlink:href="#iconRight"></use></svg>
|
||||
</button>
|
||||
<label class="b3-menu__item">
|
||||
<span class="fn__flex-center">${window.siyuan.languages.useBackground}</span>
|
||||
<span class="fn__space fn__flex-1"></span>
|
||||
<input data-type="toggle-kanban-bg" type="checkbox" class="b3-switch b3-switch--menu" ${view.displayFieldName ? "checked" : ""}>
|
||||
</label>`;
|
||||
}
|
||||
return html + `<button class="b3-menu__item" data-type="set-page-size" data-size="${view.pageSize}">
|
||||
<span class="fn__flex-center">${window.siyuan.languages.entryNum}</span>
|
||||
<span class="fn__flex-1"></span>
|
||||
<span class="b3-menu__accelerator">${view.pageSize === Constants.SIZE_DATABASE_MAZ_SIZE ? window.siyuan.languages.all : view.pageSize}</span>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {escapeAriaLabel, escapeAttr, escapeHtml} from "../../../util/escape";
|
|||
import {electronUndo} from "../../undo";
|
||||
import {isInAndroid, isInHarmony, isInIOS} from "../../util/compatibility";
|
||||
import {isMobile} from "../../../util/functions";
|
||||
import {renderGallery} from "./gallery/render";
|
||||
import {renderKanban, renderGallery} from "./gallery/render";
|
||||
import {getFieldsByData, getViewIcon} from "./view";
|
||||
import {openMenuPanel} from "./openMenuPanel";
|
||||
import {getPageSize} from "./groups";
|
||||
|
|
@ -467,6 +467,10 @@ export const avRender = (element: Element, protyle: IProtyle, cb?: (data: IAV) =
|
|||
renderGallery({blockElement: e, protyle, cb, renderAll});
|
||||
return;
|
||||
}
|
||||
if (e.getAttribute("data-av-type") === "kanban") {
|
||||
renderKanban({blockElement: e, protyle, cb, renderAll});
|
||||
return;
|
||||
}
|
||||
|
||||
let selectCellId;
|
||||
const selectCellElement = e.querySelector(".av__cell--select") as HTMLElement;
|
||||
|
|
|
|||
|
|
@ -344,6 +344,25 @@ export const addView = (protyle: IProtyle, blockElement: Element) => {
|
|||
}]);
|
||||
}
|
||||
});
|
||||
addMenu.addItem({
|
||||
icon: "iconBoard",
|
||||
label: window.siyuan.languages.kanban,
|
||||
click() {
|
||||
transaction(protyle, [{
|
||||
action: "addAttrViewView",
|
||||
avID,
|
||||
layout: "kanban",
|
||||
id,
|
||||
blockID: blockElement.getAttribute("data-node-id")
|
||||
}], [{
|
||||
action: "removeAttrViewView",
|
||||
layout: "kanban",
|
||||
avID,
|
||||
id,
|
||||
blockID: blockElement.getAttribute("data-node-id")
|
||||
}]);
|
||||
}
|
||||
});
|
||||
addMenu.addItem({
|
||||
icon: "iconGallery",
|
||||
label: window.siyuan.languages.gallery,
|
||||
|
|
@ -377,6 +396,8 @@ export const getViewIcon = (type: string) => {
|
|||
return "iconTable";
|
||||
case "gallery":
|
||||
return "iconGallery";
|
||||
case "kanban":
|
||||
return "iconBoard";
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -386,6 +407,8 @@ export const getViewName = (type: string) => {
|
|||
return window.siyuan.languages.table;
|
||||
case "gallery":
|
||||
return window.siyuan.languages.gallery;
|
||||
case "kanban":
|
||||
return window.siyuan.languages.kanban;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
2
app/src/types/index.d.ts
vendored
2
app/src/types/index.d.ts
vendored
|
|
@ -88,7 +88,7 @@ type TEventBus = "ws-main" | "sync-start" | "sync-end" | "sync-fail" |
|
|||
"lock-screen" |
|
||||
"mobile-keyboard-show" | "mobile-keyboard-hide" |
|
||||
"code-language-update" | "code-language-change"
|
||||
type TAVView = "table" | "gallery"
|
||||
type TAVView = "table" | "gallery" | "kanban"
|
||||
type TAVCol =
|
||||
"text"
|
||||
| "date"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue