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"