mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-22 17:40:13 +01:00
This commit is contained in:
parent
8b064e44bd
commit
794a3cd476
4 changed files with 70 additions and 43 deletions
|
|
@ -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}"]`),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -430,7 +461,7 @@ export const getFiltersHTML = (data: IAVTable) => {
|
||||||
filterValue = ` ≤ ${filter.value.number.content}`;
|
filterValue = ` ≤ ${filter.value.number.content}`;
|
||||||
}
|
}
|
||||||
} else if (filter.value?.text?.content || filter.value?.block?.content || filter.value?.url?.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 ||
|
const content = filter.value?.text?.content || filter.value?.block?.content ||
|
||||||
filter.value?.url?.content || filter.value?.phone?.content || filter.value?.email?.content ||
|
filter.value?.url?.content || filter.value?.phone?.content || filter.value?.email?.content ||
|
||||||
filter.value?.relation?.contents[0];
|
filter.value?.relation?.contents[0];
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3
app/src/types/index.d.ts
vendored
3
app/src/types/index.d.ts
vendored
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue