Vanessa 2023-12-31 00:09:47 +08:00
parent 8b064e44bd
commit 794a3cd476
4 changed files with 70 additions and 43 deletions

View file

@ -654,23 +654,16 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen
filter = { filter = {
column: colId, column: colId,
operator: getDefaultOperatorByType(type), operator: getDefaultOperatorByType(type),
value: genCellValue(type, "") value: genCellValue(type, ""),
type,
}; };
avData.view.filters.push(filter); avData.view.filters.push(filter);
transaction(protyle, [{
action: "setAttrViewFilters",
avID,
data: [filter]
}], [{
action: "setAttrViewFilters",
avID,
data: []
}]);
} }
setFilter({ setFilter({
filter, filter,
protyle, protyle,
data: avData, data: avData,
blockElement: blockElement,
target: blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`), target: blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`),
}); });
}); });

View file

@ -7,6 +7,8 @@ import {objEquals} from "../../../util/functions";
import {genCellValue} from "./cell"; import {genCellValue} from "./cell";
import * as dayjs from "dayjs"; import * as dayjs from "dayjs";
import {unicode2Emoji} from "../../../emoji"; import {unicode2Emoji} from "../../../emoji";
import {openMenuPanel} from "./openMenuPanel";
import {fetchSyncPost} from "../../../util/fetch";
export const getDefaultOperatorByType = (type: TAVCol) => { export const getDefaultOperatorByType = (type: TAVCol) => {
if (["select", "number"].includes(type)) { 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, filter: IAVFilter,
protyle: IProtyle, protyle: IProtyle,
data: IAV, data: IAV,
target: HTMLElement, target: HTMLElement,
blockElement: Element
}) => { }) => {
let rectTarget = options.target.getBoundingClientRect(); let rectTarget = options.target.getBoundingClientRect();
if (rectTarget.height === 0) { if (rectTarget.height === 0) {
@ -66,8 +69,8 @@ export const setFilter = (options: {
let hasMatch = false; let hasMatch = false;
let cellValue: IAVCellValue; let cellValue: IAVCellValue;
if (textElements.length > 0) { if (textElements.length > 0) {
if (["date", "updated", "created"].includes(colData.type)) { if (["date", "updated", "created"].includes(filterType)) {
cellValue = genCellValue(colData.type, { cellValue = genCellValue(filterType, {
isNotEmpty2: textElements[1].value !== "", isNotEmpty2: textElements[1].value !== "",
isNotEmpty: textElements[0].value !== "", isNotEmpty: textElements[0].value !== "",
content: new Date(textElements[0].value + " 00:00").getTime(), content: new Date(textElements[0].value + " 00:00").getTime(),
@ -75,9 +78,9 @@ export const setFilter = (options: {
hasEndDate: operator === "Is between" hasEndDate: operator === "Is between"
}); });
} else { } else {
cellValue = genCellValue(colData.type, textElements[0].value); cellValue = genCellValue(filterType, textElements[0].value);
} }
} else { } else if (filterType === "select" || filterType === "mSelect") {
const mSelect: { const mSelect: {
color: string, color: string,
content: string content: string
@ -94,14 +97,15 @@ export const setFilter = (options: {
if (mSelect.length === 0) { if (mSelect.length === 0) {
mSelect.push({color: "", content: ""}); mSelect.push({color: "", content: ""});
} }
cellValue = genCellValue(colData.type, mSelect); cellValue = genCellValue(filterType, mSelect);
} else {
cellValue = genCellValue(filterType, undefined);
} }
const newFilter: IAVFilter = { const newFilter: IAVFilter = {
column: options.filter.column, column: options.filter.column,
value: cellValue, value: cellValue,
operator operator
}; };
let isSame = false; let isSame = false;
options.data.view.filters.find((filter, index) => { options.data.view.filters.find((filter, index) => {
if (filter.column === options.filter.column) { if (filter.column === options.filter.column) {
@ -142,7 +146,41 @@ export const setFilter = (options: {
return true; 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": case "checkbox":
selectHTML = `<option ${"Is true" === options.filter.operator ? "selected" : ""} value="Is true">${window.siyuan.languages.checked}</option> selectHTML = `<option ${"Is true" === options.filter.operator ? "selected" : ""} value="Is true">${window.siyuan.languages.checked}</option>
<option ${"Is false" === options.filter.operator ? "selected" : ""} value="Is false">${window.siyuan.languages.unchecked}</option>`; <option ${"Is false" === options.filter.operator ? "selected" : ""} value="Is false">${window.siyuan.languages.unchecked}</option>`;
@ -215,7 +253,7 @@ export const setFilter = (options: {
iconHTML: "", iconHTML: "",
label: `<select style="margin: 4px 0" class="b3-select fn__size200">${selectHTML}</select>` label: `<select style="margin: 4px 0" class="b3-select fn__size200">${selectHTML}</select>`
}); });
if (colData.type === "select" || colData.type === "mSelect") { if (filterType === "select" || filterType === "mSelect") {
colData.options?.forEach((option) => { colData.options?.forEach((option) => {
let icon = "iconUncheck"; let icon = "iconUncheck";
options.filter.value?.mSelect.find((optionItem) => { 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 = ""; let value = "";
if (options.filter.value) { if (options.filter.value) {
if (colData.type === "relation") { if (filterType === "relation") {
value = options.filter.value.relation.contents[0] || ""; value = options.filter.value.relation.contents[0] || "";
} else { } else {
value = options.filter.value[colData.type as "text"].content || ""; value = options.filter.value[filterType as "text"].content || "";
} }
} }
menu.addItem({ menu.addItem({
iconHTML: "", iconHTML: "",
label: `<input style="margin: 4px 0" value="${value}" class="b3-text-field fn__size200">` label: `<input style="margin: 4px 0" value="${value}" class="b3-text-field fn__size200">`
}); });
} else if (colData.type === "number") { } else if (filterType === "number") {
menu.addItem({ menu.addItem({
iconHTML: "", iconHTML: "",
label: `<input style="margin: 4px 0" value="${options.filter.value?.number.isNotEmpty ? options.filter.value.number.content : ""}" class="b3-text-field fn__size200">` label: `<input style="margin: 4px 0" value="${options.filter.value?.number.isNotEmpty ? options.filter.value.number.content : ""}" class="b3-text-field fn__size200">`
}); });
} else if (["date", "updated", "created"].includes(colData.type)) { } else if (["date", "updated", "created"].includes(filterType)) {
const dateValue = options.filter.value ? options.filter.value[colData.type as "date"] : null; const dateValue = options.filter.value ? options.filter.value[filterType as "date"] : null;
menu.addItem({ menu.addItem({
iconHTML: "", iconHTML: "",
label: `<input style="margin: 4px 0" value="${(dateValue.isNotEmpty || colData.type !== "date") ? dayjs(dateValue.content).format("YYYY-MM-DD") : ""}" type="date" max="9999-12-31" class="b3-text-field fn__size200">` label: `<input style="margin: 4px 0" value="${(dateValue.isNotEmpty || filterType !== "date") ? dayjs(dateValue.content).format("YYYY-MM-DD") : ""}" type="date" max="9999-12-31" class="b3-text-field fn__size200">`
}); });
menu.addItem({ menu.addItem({
iconHTML: "", iconHTML: "",
@ -297,7 +335,7 @@ export const setFilter = (options: {
}); });
const selectElement = (window.siyuan.menus.menu.element.querySelector(".b3-select") as HTMLSelectElement); const selectElement = (window.siyuan.menus.menu.element.querySelector(".b3-select") as HTMLSelectElement);
selectElement.addEventListener("change", () => { selectElement.addEventListener("change", () => {
toggleEmpty(selectElement, selectElement.value, colData.type); toggleEmpty(selectElement, selectElement.value, filterType);
}); });
const textElements: NodeListOf<HTMLInputElement> = window.siyuan.menus.menu.element.querySelectorAll(".b3-text-field"); const textElements: NodeListOf<HTMLInputElement> = window.siyuan.menus.menu.element.querySelectorAll(".b3-text-field");
textElements.forEach(item => { 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}); menu.open({x: rectTarget.left, y: rectTarget.bottom});
if (textElements.length > 0) { if (textElements.length > 0) {
textElements[0].select(); textElements[0].select();
@ -326,6 +364,7 @@ export const addFilter = (options: {
tabRect: DOMRect, tabRect: DOMRect,
avId: string, avId: string,
protyle: IProtyle protyle: IProtyle
blockElement: Element
}) => { }) => {
const menu = new Menu("av-add-filter"); const menu = new Menu("av-add-filter");
options.data.view.columns.forEach((column) => { options.data.view.columns.forEach((column) => {
@ -341,22 +380,13 @@ export const addFilter = (options: {
label: column.name, label: column.name,
iconHTML: column.icon ? unicode2Emoji(column.icon, "b3-menu__icon", true) : `<svg class="b3-menu__icon"><use xlink:href="#${getColIconByType(column.type)}"></use></svg>`, iconHTML: column.icon ? unicode2Emoji(column.icon, "b3-menu__icon", true) : `<svg class="b3-menu__icon"><use xlink:href="#${getColIconByType(column.type)}"></use></svg>`,
click: () => { click: () => {
const oldFilters = Object.assign([], options.data.view.filters);
const cellValue = genCellValue(column.type, ""); const cellValue = genCellValue(column.type, "");
options.data.view.filters.push({ options.data.view.filters.push({
column: column.id, column: column.id,
operator: getDefaultOperatorByType(column.type), operator: getDefaultOperatorByType(column.type),
value: cellValue, 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); options.menuElement.innerHTML = getFiltersHTML(options.data.view);
setPosition(options.menuElement, options.tabRect.right - options.menuElement.clientWidth, options.tabRect.bottom, options.tabRect.height); 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; const filterElement = options.menuElement.querySelector(`[data-id="${column.id}"] .b3-chip`) as HTMLElement;
@ -368,7 +398,8 @@ export const addFilter = (options: {
}, },
protyle: options.protyle, protyle: options.protyle,
data: options.data, data: options.data,
target: filterElement target: filterElement,
blockElement: options.blockElement
}); });
} }
}); });

View file

@ -517,7 +517,8 @@ export const openMenuPanel = (options: {
menuElement, menuElement,
tabRect, tabRect,
avId: avID, avId: avID,
protyle: options.protyle protyle: options.protyle,
blockElement: options.blockElement
}); });
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
@ -552,7 +553,8 @@ export const openMenuPanel = (options: {
filter: item, filter: item,
protyle: options.protyle, protyle: options.protyle,
data, data,
target target,
blockElement: options.blockElement
}); });
return true; return true;
} }

View file

@ -1063,7 +1063,8 @@ interface IAVTable extends IAVView {
interface IAVFilter { interface IAVFilter {
column: string, column: string,
operator: TAVFilterOperator, operator: TAVFilterOperator,
value: IAVCellValue value: IAVCellValue,
type?: TAVCol // 仅用于标识新增时的类型,用于区分 rollup
} }
interface IAVSort { interface IAVSort {