diff --git a/app/src/assets/scss/business/_av.scss b/app/src/assets/scss/business/_av.scss index 59d250c9b..88dd955e3 100644 --- a/app/src/assets/scss/business/_av.scss +++ b/app/src/assets/scss/business/_av.scss @@ -3,7 +3,7 @@ box-sizing: border-box; font-size: 14px; - &:hover .av__row--footer { + &:hover .av__row--footer > .av__calc--show { opacity: 1; } @@ -76,6 +76,7 @@ .av__cell { padding: 0; + transition: background 20ms ease-in 0s; &:hover { background-color: var(--b3-list-icon-hover); @@ -92,15 +93,21 @@ display: flex; border-top: 1px solid var(--b3-theme-surface-lighter); color: var(--b3-theme-on-surface); - opacity: 0; + + &:hover > .av__calc, + &.av__row--show > .av__calc { + opacity: 1; + } & > .av__calc { + transition: opacity 150ms linear, background 20ms ease-in 0s; display: flex; align-items: center; padding: 5px 5px 5px 7px; border-right: 1px; flex-direction: row-reverse; box-sizing: border-box; + opacity: 0; svg { height: 10px; @@ -119,6 +126,7 @@ padding: 5px 5px 5px 7px; display: flex; align-items: center; + transition: background 20ms ease-in 0s; svg { height: 12px; @@ -191,7 +199,7 @@ width: 5px; height: 100%; right: -2.5px; - transition: background 200ms ease-out 0s; + transition: background 20ms ease-in 0s; z-index: 1; &:hover { diff --git a/app/src/protyle/render/av/action.ts b/app/src/protyle/render/av/action.ts index 588bf3146..6f3db3df3 100644 --- a/app/src/protyle/render/av/action.ts +++ b/app/src/protyle/render/av/action.ts @@ -3,7 +3,7 @@ import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName} from "../ import {transaction} from "../../wysiwyg/transaction"; import {openEditorTab} from "../../../menus/util"; import {copySubMenu} from "../../../menus/commonMenuItem"; -import {popTextCell} from "./cell"; +import {openCalcMenu, popTextCell} from "./cell"; import {getColIconByType, showColMenu, updateHeader} from "./col"; import {emitOpenMenu} from "../../../plugin/EventBus"; import {addCol} from "./addCol"; @@ -115,6 +115,14 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle event.stopPropagation(); return true; } + + const calcElement = hasClosestByClassName(event.target, "av__calc"); + if (calcElement) { + openCalcMenu(protyle, calcElement); + event.preventDefault(); + event.stopPropagation(); + return true; + } return false; }; diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index fde158587..7aa026240 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -1,6 +1,7 @@ import {transaction} from "../../wysiwyg/transaction"; import {hasClosestBlock, hasClosestByClassName} from "../../util/hasClosest"; import {openMenuPanel} from "./openMenuPanel"; +import {Menu} from "../../../plugin/Menu"; export const genCellValue = (colType: TAVCol, value: string | { content: string, @@ -51,6 +52,185 @@ export const genCellValue = (colType: TAVCol, value: string | { } }; +const calcItem = (options: { + menu: Menu, + protyle: IProtyle, + label: string, + operator: string, + oldOperator: string, + colId: string, + avId: string +}) => { + options.menu.addItem({ + iconHTML: "", + label: options.label, + click() { + transaction(options.protyle, [{ + action: "setAttrViewColCalc", + avID: options.avId, + id: options.colId, + data: { + operator: options.operator + } + }], [{ + action: "setAttrViewColCalc", + avID: options.avId, + id: options.colId, + data: { + operator: options.oldOperator + } + }]); + } + }); +} +export const openCalcMenu = (protyle: IProtyle, calcElement: HTMLElement) => { + const blockElement = hasClosestBlock(calcElement); + if (!blockElement) { + return; + } + calcElement.parentElement.classList.add("av__row--show"); + const menu = new Menu("av-calc", () => { + calcElement.parentElement.classList.remove("av__row--show"); + }); + if (menu.isOpen) { + return; + } + const type = calcElement.dataset.dtype as TAVCol; + const colId = calcElement.dataset.id; + const avId = blockElement.dataset.avId; + const oldOperator = calcElement.dataset.operator; + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "", + label: window.siyuan.languages.calcOperatorNone + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Count all", + label: window.siyuan.languages.calcOperatorCountAll + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Count values", + label: window.siyuan.languages.calcOperatorCountValues + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Count unique values", + label: window.siyuan.languages.calcOperatorCountUniqueValues + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Count empty", + label: window.siyuan.languages.calcOperatorCountEmpty + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Count not empty", + label: window.siyuan.languages.calcOperatorCountNotEmpty + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Percent empty", + label: window.siyuan.languages.calcOperatorPercentEmpty + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Percent not empty", + label: window.siyuan.languages.calcOperatorPercentNotEmpty + }); + if (type === "number") { + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Sum", + label: window.siyuan.languages.calcOperatorSum + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Average", + label: window.siyuan.languages.calcOperatorAverage + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Median", + label: window.siyuan.languages.calcOperatorMedian + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Min", + label: window.siyuan.languages.calcOperatorMin + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Max", + label: window.siyuan.languages.calcOperatorMax + }); + calcItem({ + menu, + protyle, + colId, + avId, + oldOperator, + operator: "Range", + label: window.siyuan.languages.calcOperatorRange + }); + } + const calcRect = calcElement.getBoundingClientRect(); + menu.open({x: calcRect.left, y: calcRect.bottom, h: calcRect.height}); +} + export const popTextCell = (protyle: IProtyle, cellElement: HTMLElement) => { const type = cellElement.parentElement.parentElement.firstElementChild.querySelector(`[data-col-id="${cellElement.getAttribute("data-col-id")}"]`).getAttribute("data-dtype") as TAVCol; const cellRect = cellElement.getBoundingClientRect(); diff --git a/app/src/protyle/render/av/render.ts b/app/src/protyle/render/av/render.ts index f3e69f229..c402bb422 100644 --- a/app/src/protyle/render/av/render.ts +++ b/app/src/protyle/render/av/render.ts @@ -22,7 +22,7 @@ export const avRender = (element: Element, cb?: () => void) => { const data = response.data.view as IAVTable; // header let tableHTML = '