Vanessa 2023-07-06 21:52:34 +08:00
parent 1278c30e9d
commit 526c830535
4 changed files with 105 additions and 26 deletions

View file

@ -149,6 +149,18 @@
width: 300px;
max-height: 70vh;
.b3-chip {
max-width: 220px;
margin: 1px 0;
padding: 6px 12px 6px 14px;
float: left;
svg {
width: 12px;
flex-shrink: 0;
}
}
.block__icon {
line-height: 20px;
padding: 0 4px;
@ -161,12 +173,12 @@
overflow: hidden;
}
&__item:hover .b3-menu__action {
opacity: 1;
}
&__item:not([data-type="nobg"]):hover {
background-color: var(--b3-list-hover);
.b3-menu__action {
opacity: 1;
}
}
}
}

View file

@ -18,7 +18,7 @@
align-items: center;
box-sizing: border-box;
padding: 8px 12px;
border-radius: var(--b3-border-radius-b);
border-radius: 20px;
transition: var(--b3-transition);
text-decoration: none;

View file

@ -114,7 +114,6 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
break;
} else if (type === "goFilters") {
menuElement.innerHTML = getFiltersHTML(data);
bindFiltersEvent(protyle, menuElement, data);
setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height);
event.stopPropagation();
break;
@ -123,18 +122,17 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
action: "setAttrView",
id: avId,
data: {
Filters: []
filters: []
}
}], [{
action: "setAttrView",
id: avId,
data: {
Filters: data.filters
filters: data.filters
}
}]);
data.filters = [];
menuElement.innerHTML = getFiltersHTML(data);
bindFiltersEvent(protyle, menuElement, data);
setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height);
event.stopPropagation();
break;
@ -154,20 +152,23 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
action: "setAttrView",
id: avId,
data: {
Filters: data.filters
filter: data.filters
}
}], [{
action: "setAttrView",
id: avId,
data: {
Filters: oldFilters
filter: oldFilters
}
}]);
menuElement.innerHTML = getFiltersHTML(data);
bindFiltersEvent(protyle, menuElement, data);
setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height);
event.stopPropagation();
break;
} else if (type === "setFilter") {
setFilter(protyle, data, target);
event.stopPropagation();
break;
} else if (type === "newCol") {
avPanelElement.remove();
const addMenu = addCol(protyle, blockElement);
@ -405,6 +406,59 @@ ${html}
</button>`;
};
const setFilter = (protyle: IProtyle, data: IAV, target: HTMLElement) => {
const menu = new Menu(undefined, () => {
const colId = target.parentElement.parentElement.getAttribute("data-id");
const oldFilters = JSON.parse(JSON.stringify(data.filters));
data.filters.find((filter) => {
if (filter.column === colId) {
filter.value = {
content: (window.siyuan.menus.menu.element.querySelector(".b3-text-field") as HTMLInputElement).value
};
filter.operator = (window.siyuan.menus.menu.element.querySelector(".b3-select") as HTMLSelectElement).value as TAVFilterOperator;
return true;
}
});
transaction(protyle, [{
action: "setAttrView",
id: data.id,
data: {
filters: data.filters
}
}], [{
action: "setAttrView",
id: data.id,
data: {
filters: oldFilters
}
}]);
});
let selectHTML = "";
switch (target.getAttribute("data-coltype")) {
case "text":
selectHTML = `<option value="=">=</option>
<option value="!=">!=</option>
<option value="Contains">Contains</option>
<option value="Does not contains">Does not contains</option>
<option value="Starts with">Starts with</option>
<option value="Ends with">Ends with</option>
<option value="Is empty">Is empty</option>
<option value="Is not empty">Is not empty</option>
`;
break;
}
menu.addItem({
iconHTML: "",
label: `<select class="b3-select fn__size200">${selectHTML}</select>`
})
menu.addItem({
iconHTML: "",
label: `<input class="b3-text-field fn__size200">`
})
const rectTarget = target.getBoundingClientRect();
menu.open({x: rectTarget.left, y: rectTarget.bottom})
}
const addFilter = (options: {
data: IAV,
rect: DOMRect,
@ -450,7 +504,6 @@ const addFilter = (options: {
}
}]);
options.menuElement.innerHTML = getFiltersHTML(options.data);
bindFiltersEvent(options.protyle, options.menuElement, options.data);
setPosition(options.menuElement, options.tabRect.right - options.menuElement.clientWidth, options.tabRect.bottom, options.tabRect.height);
}
});
@ -463,25 +516,25 @@ const addFilter = (options: {
});
}
const bindFiltersEvent = (protyle: IProtyle, menuElement: HTMLElement, data: IAV) => {
}
const getFiltersHTML = (data: IAV) => {
let html = "";
const genFilterItem = (id: string) => {
const genFilterItem = (filter: IAVFilter) => {
let filterHTML = "";
data.columns.forEach((item) => {
filterHTML += `<option value="${item.id}" ${item.id === id ? "selected" : ""}>${item.name}</option>`;
data.columns.find((item) => {
if (item.id === filter.column) {
filterHTML += `<span data-type="setFilter" data-coltype="${item.type}" class="b3-chip${filter.value?.content ? " b3-chip--primary" : ""}">
<svg><use xlink:href="#${getColIconByType(item.type)}"></use></svg>
<span class="fn__ellipsis">${item.name}${filter.value?.content ? ":" + filter.value?.content : ""}</span>
</span>`;
return true
}
});
return filterHTML;
};
data.filters.forEach((item: IAVFilter) => {
html += `<button class="b3-menu__item" data-id="${item.column}">
html += `<button class="b3-menu__item" data-type="nobg" data-id="${item.column}">
<svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg>
<select class="b3-select" style="flex: 1;margin: 4px 0">
${genFilterItem(item.column)}
</select>
<div class="fn__flex-1">${genFilterItem(item)}</div>
<svg class="b3-menu__action" data-type="removeFilter"><use xlink:href="#iconTrashcan"></use></svg>
</button>`;
});

View file

@ -39,7 +39,21 @@ type TEventBus = "ws-main" |
"open-menu-av" | "open-menu-content" | "open-menu-breadcrumbmore" |
"loaded-protyle"
type TAVCol = "text" | "date" | "number" | "relation" | "rollup" | "select" | "block" | "mSelect"
type TAVFilterOperator =
"="
| "!="
| ">"
| ">="
| "<"
| "<="
| "Contains"
| "Does not contains"
| "Is empty"
| "Is not empty"
| "Starts with"
| "Ends with"
| "Is between"
| "Is relative to today"
declare module "blueimp-md5"
interface Window {
@ -836,7 +850,7 @@ interface IAV {
interface IAVFilter {
column: string,
operator: "=" | "!=" | ">" | ">=" | "<" | "<=" | "Contains" | "Does not contains" | "Is empty" | "Is not empty" | "Starts with" | "Ends with" | "Is between" | "Is relative to today"
operator: TAVFilterOperator,
value: IAVCellValue
}