mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-21 09:00:12 +01:00
This commit is contained in:
parent
1278c30e9d
commit
526c830535
4 changed files with 105 additions and 26 deletions
|
|
@ -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:hover .b3-menu__action {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
&__item:not([data-type="nobg"]):hover {
|
&__item:not([data-type="nobg"]):hover {
|
||||||
background-color: var(--b3-list-hover);
|
background-color: var(--b3-list-hover);
|
||||||
|
|
||||||
.b3-menu__action {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>`;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
18
app/src/types/index.d.ts
vendored
18
app/src/types/index.d.ts
vendored
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue