diff --git a/app/src/protyle/render/av/action.ts b/app/src/protyle/render/av/action.ts
index 099cdd6ef..749585444 100644
--- a/app/src/protyle/render/av/action.ts
+++ b/app/src/protyle/render/av/action.ts
@@ -92,6 +92,14 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
return true;
}
+ const filtersElement = hasClosestByAttribute(event.target, "data-type", "av-filter");
+ if (filtersElement) {
+ openMenuPanel(protyle, blockElement, "filters");
+ event.preventDefault();
+ event.stopPropagation();
+ return true;
+ }
+
const cellHeaderElement = hasClosestByClassName(event.target, "av__cellheader");
if (cellHeaderElement) {
showHeaderCellMenu(protyle, blockElement, cellHeaderElement.parentElement);
diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts
index cdad52242..d82e214d8 100644
--- a/app/src/protyle/render/av/openMenuPanel.ts
+++ b/app/src/protyle/render/av/openMenuPanel.ts
@@ -5,7 +5,7 @@ import {getColIconByType} from "./col";
import {setPosition} from "../../../util/setPosition";
import {Menu} from "../../../plugin/Menu";
-export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type: "properties" | "config" | "sorts" = "config") => {
+export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type: "properties" | "config" | "sorts" | "filters" = "config") => {
let avPanelElement = document.querySelector(".av__panel");
if (avPanelElement) {
avPanelElement.remove();
@@ -22,6 +22,8 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
html = getPropertiesHTML(data);
} else if (type === "sorts") {
html = getSortsHTML(data);
+ } else if (type === "filters") {
+ html = getFiltersHTML(data);
}
document.body.insertAdjacentHTML("beforeend", `
@@ -110,6 +112,62 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height);
event.stopPropagation();
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;
+ } else if (type === "removeFilters") {
+ transaction(protyle, [{
+ action: "setAttrView",
+ id: avId,
+ data: {
+ Filters: []
+ }
+ }], [{
+ action: "setAttrView",
+ id: avId,
+ data: {
+ 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;
+ } else if (type === "addFilter") {
+ addFilter({data, rect: target.getBoundingClientRect(), menuElement, tabRect, avId, protyle});
+ event.stopPropagation();
+ break;
+ } else if (type === "removeFilter") {
+ const oldFilters = Object.assign([], data.filters);
+ data.filters.find((item: IAVFilter, index: number) => {
+ if (item.column === target.parentElement.dataset.id) {
+ data.filters.splice(index, 1);
+ return true;
+ }
+ });
+ transaction(protyle, [{
+ action: "setAttrView",
+ id: avId,
+ data: {
+ Filters: data.filters
+ }
+ }], [{
+ action: "setAttrView",
+ id: avId,
+ data: {
+ Filters: 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 === "newCol") {
avPanelElement.remove();
const addMenu = addCol(protyle, blockElement);
@@ -218,36 +276,58 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
});
};
-const getConfigHTML = (data: IAV) => {
- return `
-
-
-
-
-`;
+const addSort = (options: {
+ data: IAV,
+ rect: DOMRect,
+ menuElement: HTMLElement,
+ tabRect: DOMRect,
+ avId: string,
+ protyle: IProtyle
+}) => {
+ const menu = new Menu("av-add-sort");
+ options.data.columns.forEach((column) => {
+ let hasSort = false;
+ options.data.sorts.find((sort) => {
+ if (sort.column === column.id) {
+ hasSort = true;
+ return true;
+ }
+ });
+ if (!hasSort) {
+ menu.addItem({
+ label: column.name,
+ icon: getColIconByType(column.type),
+ click: () => {
+ const oldSorts = Object.assign([], options.data.sorts);
+ options.data.sorts.push({
+ column: column.id,
+ order: "ASC",
+ });
+ transaction(options.protyle, [{
+ action: "setAttrView",
+ id: options.avId,
+ data: {
+ sorts: options.data.sorts
+ }
+ }], [{
+ action: "setAttrView",
+ id: options.avId,
+ data: {
+ sorts: oldSorts
+ }
+ }]);
+ options.menuElement.innerHTML = getSortsHTML(options.data);
+ bindSortsEvent(options.protyle, options.menuElement, options.data);
+ setPosition(options.menuElement, options.tabRect.right - options.menuElement.clientWidth, options.tabRect.bottom, options.tabRect.height);
+ }
+ });
+ }
+ });
+ menu.open({
+ x: options.rect.left,
+ y: options.rect.bottom,
+ h: options.rect.height,
+ });
};
const bindSortsEvent = (protyle: IProtyle, menuElement: HTMLElement, data: IAV) => {
@@ -325,6 +405,63 @@ ${html}
`;
};
+const addFilter = (options: {
+ data: IAV,
+ rect: DOMRect,
+ menuElement: HTMLElement,
+ tabRect: DOMRect,
+ avId: string,
+ protyle: IProtyle
+}) => {
+
+}
+
+const bindFiltersEvent = (protyle: IProtyle, menuElement: HTMLElement, data: IAV) => {
+
+}
+
+const getFiltersHTML = (data: IAV) => {
+ let html = "";
+ const genFilterItem = (id: string) => {
+ let filterHTML = "";
+ data.columns.forEach((item) => {
+ filterHTML += `
`;
+ });
+ return filterHTML;
+ };
+ data.filters.forEach((item: IAVFilter) => {
+ html += ``;
+ });
+ return `
+
+${html}
+
+`;
+};
+
const getPropertiesHTML = (data: IAV) => {
let showHTML = "";
let hideHTML = "";
@@ -384,56 +521,34 @@ ${hideHTML}
`;
};
-const addSort = (options: {
- data: IAV,
- rect: DOMRect,
- menuElement: HTMLElement,
- tabRect: DOMRect,
- avId: string,
- protyle: IProtyle
-}) => {
- const menu = new Menu("av-add-sort");
- options.data.columns.forEach((column) => {
- let hasSort = false;
- options.data.sorts.find((sort) => {
- if (sort.column === column.id) {
- hasSort = true;
- return true;
- }
- });
- if (!hasSort) {
- menu.addItem({
- label: column.name,
- icon: getColIconByType(column.type),
- click: () => {
- const oldSorts = Object.assign([], options.data.sorts);
- options.data.sorts.push({
- column: column.id,
- order: "ASC",
- });
- transaction(options.protyle, [{
- action: "setAttrView",
- id: options.avId,
- data: {
- sorts: options.data.sorts
- }
- }], [{
- action: "setAttrView",
- id: options.avId,
- data: {
- sorts: oldSorts
- }
- }]);
- options.menuElement.innerHTML = getSortsHTML(options.data);
- bindSortsEvent(options.protyle, options.menuElement, options.data);
- setPosition(options.menuElement, options.tabRect.right - options.menuElement.clientWidth, options.tabRect.bottom, options.tabRect.height);
- }
- });
- }
- });
- menu.open({
- x: options.rect.left,
- y: options.rect.bottom,
- h: options.rect.height,
- });
+const getConfigHTML = (data: IAV) => {
+ return `
+
+
+
+
+`;
};
diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts
index 71a9080c2..bfcfc6d91 100644
--- a/app/src/types/index.d.ts
+++ b/app/src/types/index.d.ts
@@ -826,7 +826,7 @@ interface IBazaarItem {
interface IAV {
columns: IAVColumn[],
- filters: [],
+ filters: IAVFilter[],
sorts: IAVSort[],
name: string,
type: "table"
@@ -834,6 +834,12 @@ interface IAV {
id: string
}
+interface IAVFilter {
+ column: string,
+ operator: "=" | "!=" | ">" | ">=" | "<" | "<=" | "Contains" | "Does not contains" | "Is empty" | "Is not empty" | "Starts with" | "Ends with" | "Is between" | "Is relative to today"
+ value: string
+}
+
interface IAVSort {
column: string,
order: "ASC" | "DESC"