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; width: 300px;
max-height: 70vh; 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 { .block__icon {
line-height: 20px; line-height: 20px;
padding: 0 4px; padding: 0 4px;
@ -161,12 +173,12 @@
overflow: hidden; overflow: hidden;
} }
&__item:not([data-type="nobg"]):hover { &__item:hover .b3-menu__action {
background-color: var(--b3-list-hover);
.b3-menu__action {
opacity: 1; opacity: 1;
} }
&__item:not([data-type="nobg"]):hover {
background-color: var(--b3-list-hover);
} }
} }
} }

View file

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

View file

@ -114,7 +114,6 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
break; break;
} else if (type === "goFilters") { } else if (type === "goFilters") {
menuElement.innerHTML = getFiltersHTML(data); menuElement.innerHTML = getFiltersHTML(data);
bindFiltersEvent(protyle, menuElement, data);
setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height);
event.stopPropagation(); event.stopPropagation();
break; break;
@ -123,18 +122,17 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
action: "setAttrView", action: "setAttrView",
id: avId, id: avId,
data: { data: {
Filters: [] filters: []
} }
}], [{ }], [{
action: "setAttrView", action: "setAttrView",
id: avId, id: avId,
data: { data: {
Filters: data.filters filters: data.filters
} }
}]); }]);
data.filters = []; data.filters = [];
menuElement.innerHTML = getFiltersHTML(data); menuElement.innerHTML = getFiltersHTML(data);
bindFiltersEvent(protyle, menuElement, data);
setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height);
event.stopPropagation(); event.stopPropagation();
break; break;
@ -154,20 +152,23 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
action: "setAttrView", action: "setAttrView",
id: avId, id: avId,
data: { data: {
Filters: data.filters filter: data.filters
} }
}], [{ }], [{
action: "setAttrView", action: "setAttrView",
id: avId, id: avId,
data: { data: {
Filters: oldFilters filter: oldFilters
} }
}]); }]);
menuElement.innerHTML = getFiltersHTML(data); menuElement.innerHTML = getFiltersHTML(data);
bindFiltersEvent(protyle, menuElement, data);
setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height);
event.stopPropagation(); event.stopPropagation();
break; break;
} else if (type === "setFilter") {
setFilter(protyle, data, target);
event.stopPropagation();
break;
} else if (type === "newCol") { } else if (type === "newCol") {
avPanelElement.remove(); avPanelElement.remove();
const addMenu = addCol(protyle, blockElement); const addMenu = addCol(protyle, blockElement);
@ -405,6 +406,59 @@ ${html}
</button>`; </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: { const addFilter = (options: {
data: IAV, data: IAV,
rect: DOMRect, rect: DOMRect,
@ -450,7 +504,6 @@ const addFilter = (options: {
} }
}]); }]);
options.menuElement.innerHTML = getFiltersHTML(options.data); 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); 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) => { const getFiltersHTML = (data: IAV) => {
let html = ""; let html = "";
const genFilterItem = (id: string) => { const genFilterItem = (filter: IAVFilter) => {
let filterHTML = ""; let filterHTML = "";
data.columns.forEach((item) => { data.columns.find((item) => {
filterHTML += `<option value="${item.id}" ${item.id === id ? "selected" : ""}>${item.name}</option>`; 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; return filterHTML;
}; };
data.filters.forEach((item: IAVFilter) => { 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> <svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg>
<select class="b3-select" style="flex: 1;margin: 4px 0"> <div class="fn__flex-1">${genFilterItem(item)}</div>
${genFilterItem(item.column)}
</select>
<svg class="b3-menu__action" data-type="removeFilter"><use xlink:href="#iconTrashcan"></use></svg> <svg class="b3-menu__action" data-type="removeFilter"><use xlink:href="#iconTrashcan"></use></svg>
</button>`; </button>`;
}); });

View file

@ -39,7 +39,21 @@ type TEventBus = "ws-main" |
"open-menu-av" | "open-menu-content" | "open-menu-breadcrumbmore" | "open-menu-av" | "open-menu-content" | "open-menu-breadcrumbmore" |
"loaded-protyle" "loaded-protyle"
type TAVCol = "text" | "date" | "number" | "relation" | "rollup" | "select" | "block" | "mSelect" 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" declare module "blueimp-md5"
interface Window { interface Window {
@ -836,7 +850,7 @@ interface IAV {
interface IAVFilter { interface IAVFilter {
column: string, 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 value: IAVCellValue
} }