diff --git a/app/src/protyle/render/av/col.ts b/app/src/protyle/render/av/col.ts
index ba92529e4..028324cf8 100644
--- a/app/src/protyle/render/av/col.ts
+++ b/app/src/protyle/render/av/col.ts
@@ -654,23 +654,16 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen
filter = {
column: colId,
operator: getDefaultOperatorByType(type),
- value: genCellValue(type, "")
+ value: genCellValue(type, ""),
+ type,
};
avData.view.filters.push(filter);
- transaction(protyle, [{
- action: "setAttrViewFilters",
- avID,
- data: [filter]
- }], [{
- action: "setAttrViewFilters",
- avID,
- data: []
- }]);
}
setFilter({
filter,
protyle,
data: avData,
+ blockElement: blockElement,
target: blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`),
});
});
diff --git a/app/src/protyle/render/av/filter.ts b/app/src/protyle/render/av/filter.ts
index 795dbfc17..5e508a9cc 100644
--- a/app/src/protyle/render/av/filter.ts
+++ b/app/src/protyle/render/av/filter.ts
@@ -7,6 +7,8 @@ import {objEquals} from "../../../util/functions";
import {genCellValue} from "./cell";
import * as dayjs from "dayjs";
import {unicode2Emoji} from "../../../emoji";
+import {openMenuPanel} from "./openMenuPanel";
+import {fetchSyncPost} from "../../../util/fetch";
export const getDefaultOperatorByType = (type: TAVCol) => {
if (["select", "number"].includes(type)) {
@@ -50,11 +52,12 @@ const toggleEmpty = (element: HTMLElement, operator: string, type: TAVCol) => {
}
};
-export const setFilter = (options: {
+export const setFilter = async (options: {
filter: IAVFilter,
protyle: IProtyle,
data: IAV,
target: HTMLElement,
+ blockElement: Element
}) => {
let rectTarget = options.target.getBoundingClientRect();
if (rectTarget.height === 0) {
@@ -66,8 +69,8 @@ export const setFilter = (options: {
let hasMatch = false;
let cellValue: IAVCellValue;
if (textElements.length > 0) {
- if (["date", "updated", "created"].includes(colData.type)) {
- cellValue = genCellValue(colData.type, {
+ if (["date", "updated", "created"].includes(filterType)) {
+ cellValue = genCellValue(filterType, {
isNotEmpty2: textElements[1].value !== "",
isNotEmpty: textElements[0].value !== "",
content: new Date(textElements[0].value + " 00:00").getTime(),
@@ -75,9 +78,9 @@ export const setFilter = (options: {
hasEndDate: operator === "Is between"
});
} else {
- cellValue = genCellValue(colData.type, textElements[0].value);
+ cellValue = genCellValue(filterType, textElements[0].value);
}
- } else {
+ } else if (filterType === "select" || filterType === "mSelect") {
const mSelect: {
color: string,
content: string
@@ -94,14 +97,15 @@ export const setFilter = (options: {
if (mSelect.length === 0) {
mSelect.push({color: "", content: ""});
}
- cellValue = genCellValue(colData.type, mSelect);
+ cellValue = genCellValue(filterType, mSelect);
+ } else {
+ cellValue = genCellValue(filterType, undefined);
}
const newFilter: IAVFilter = {
column: options.filter.column,
value: cellValue,
operator
};
-
let isSame = false;
options.data.view.filters.find((filter, index) => {
if (filter.column === options.filter.column) {
@@ -142,7 +146,41 @@ export const setFilter = (options: {
return true;
}
});
- switch (colData.type) {
+ let filterType = colData.type;
+ if (filterType === "rollup") {
+ if (!colData.rollup.relationKeyID || !colData.rollup.keyID) {
+ openMenuPanel({
+ protyle: options.protyle,
+ blockElement: options.blockElement,
+ type: "edit",
+ colId: colData.id
+ });
+ return;
+ }
+ let targetAVId = ""
+ options.data.view.columns.find((column) => {
+ if (column.id === colData.rollup.relationKeyID) {
+ targetAVId = column.relation.avID
+ return true;
+ }
+ });
+ const response = await fetchSyncPost("/api/av/getAttributeView", {id: targetAVId});
+ response.data.av.keyValues.find((item: { key: { id: string, name: string, type: TAVCol } }) => {
+ if (item.key.id === colData.rollup.keyID) {
+ filterType = item.key.type;
+ return true;
+ }
+ });
+ options.data.view.filters.find(item => {
+ if (item.column === colData.id && item.type) {
+ item.operator = getDefaultOperatorByType(filterType);
+ item.value = genCellValue(filterType, "");
+ delete item.type
+ return true;
+ }
+ })
+ }
+ switch (filterType) {
case "checkbox":
selectHTML = `
`;
@@ -215,7 +253,7 @@ export const setFilter = (options: {
iconHTML: "",
label: ``
});
- if (colData.type === "select" || colData.type === "mSelect") {
+ if (filterType === "select" || filterType === "mSelect") {
colData.options?.forEach((option) => {
let icon = "iconUncheck";
options.filter.value?.mSelect.find((optionItem) => {
@@ -240,29 +278,29 @@ export const setFilter = (options: {
}
});
});
- } else if (["text", "url", "block", "email", "phone", "template", "relation"].includes(colData.type)) {
+ } else if (["text", "url", "block", "email", "phone", "template", "relation"].includes(filterType)) {
let value = "";
if (options.filter.value) {
- if (colData.type === "relation") {
+ if (filterType === "relation") {
value = options.filter.value.relation.contents[0] || "";
} else {
- value = options.filter.value[colData.type as "text"].content || "";
+ value = options.filter.value[filterType as "text"].content || "";
}
}
menu.addItem({
iconHTML: "",
label: ``
});
- } else if (colData.type === "number") {
+ } else if (filterType === "number") {
menu.addItem({
iconHTML: "",
label: ``
});
- } else if (["date", "updated", "created"].includes(colData.type)) {
- const dateValue = options.filter.value ? options.filter.value[colData.type as "date"] : null;
+ } else if (["date", "updated", "created"].includes(filterType)) {
+ const dateValue = options.filter.value ? options.filter.value[filterType as "date"] : null;
menu.addItem({
iconHTML: "",
- label: ``
+ label: ``
});
menu.addItem({
iconHTML: "",
@@ -297,7 +335,7 @@ export const setFilter = (options: {
});
const selectElement = (window.siyuan.menus.menu.element.querySelector(".b3-select") as HTMLSelectElement);
selectElement.addEventListener("change", () => {
- toggleEmpty(selectElement, selectElement.value, colData.type);
+ toggleEmpty(selectElement, selectElement.value, filterType);
});
const textElements: NodeListOf = window.siyuan.menus.menu.element.querySelectorAll(".b3-text-field");
textElements.forEach(item => {
@@ -312,7 +350,7 @@ export const setFilter = (options: {
}
});
});
- toggleEmpty(selectElement, selectElement.value, colData.type);
+ toggleEmpty(selectElement, selectElement.value, filterType);
menu.open({x: rectTarget.left, y: rectTarget.bottom});
if (textElements.length > 0) {
textElements[0].select();
@@ -326,6 +364,7 @@ export const addFilter = (options: {
tabRect: DOMRect,
avId: string,
protyle: IProtyle
+ blockElement: Element
}) => {
const menu = new Menu("av-add-filter");
options.data.view.columns.forEach((column) => {
@@ -341,22 +380,13 @@ export const addFilter = (options: {
label: column.name,
iconHTML: column.icon ? unicode2Emoji(column.icon, "b3-menu__icon", true) : ``,
click: () => {
- const oldFilters = Object.assign([], options.data.view.filters);
const cellValue = genCellValue(column.type, "");
options.data.view.filters.push({
column: column.id,
operator: getDefaultOperatorByType(column.type),
value: cellValue,
+ type: column.type
});
- transaction(options.protyle, [{
- action: "setAttrViewFilters",
- avID: options.data.id,
- data: options.data.view.filters
- }], [{
- action: "setAttrViewFilters",
- avID: options.data.id,
- data: oldFilters
- }]);
options.menuElement.innerHTML = getFiltersHTML(options.data.view);
setPosition(options.menuElement, options.tabRect.right - options.menuElement.clientWidth, options.tabRect.bottom, options.tabRect.height);
const filterElement = options.menuElement.querySelector(`[data-id="${column.id}"] .b3-chip`) as HTMLElement;
@@ -368,7 +398,8 @@ export const addFilter = (options: {
},
protyle: options.protyle,
data: options.data,
- target: filterElement
+ target: filterElement,
+ blockElement: options.blockElement
});
}
});
@@ -430,7 +461,7 @@ export const getFiltersHTML = (data: IAVTable) => {
filterValue = ` ≤ ${filter.value.number.content}`;
}
} else if (filter.value?.text?.content || filter.value?.block?.content || filter.value?.url?.content ||
- filter.value?.phone?.content || filter.value?.email?.content || filter.value?.relation?.contents.length>0) {
+ filter.value?.phone?.content || filter.value?.email?.content || filter.value?.relation?.contents.length > 0) {
const content = filter.value?.text?.content || filter.value?.block?.content ||
filter.value?.url?.content || filter.value?.phone?.content || filter.value?.email?.content ||
filter.value?.relation?.contents[0];
diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts
index 517672430..10324e8f0 100644
--- a/app/src/protyle/render/av/openMenuPanel.ts
+++ b/app/src/protyle/render/av/openMenuPanel.ts
@@ -517,7 +517,8 @@ export const openMenuPanel = (options: {
menuElement,
tabRect,
avId: avID,
- protyle: options.protyle
+ protyle: options.protyle,
+ blockElement: options.blockElement
});
event.preventDefault();
event.stopPropagation();
@@ -552,7 +553,8 @@ export const openMenuPanel = (options: {
filter: item,
protyle: options.protyle,
data,
- target
+ target,
+ blockElement: options.blockElement
});
return true;
}
diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts
index d391e1f6c..1ab99bb2a 100644
--- a/app/src/types/index.d.ts
+++ b/app/src/types/index.d.ts
@@ -1063,7 +1063,8 @@ interface IAVTable extends IAVView {
interface IAVFilter {
column: string,
operator: TAVFilterOperator,
- value: IAVCellValue
+ value: IAVCellValue,
+ type?: TAVCol // 仅用于标识新增时的类型,用于区分 rollup
}
interface IAVSort {