diff --git a/app/src/protyle/render/av/col.ts b/app/src/protyle/render/av/col.ts index 8d4bc6dc8..5baee5f17 100644 --- a/app/src/protyle/render/av/col.ts +++ b/app/src/protyle/render/av/col.ts @@ -6,6 +6,66 @@ import {getDefaultOperatorByType, setFilter} from "./filter"; import {genCellValue} from "./cell"; import {openMenuPanel} from "./openMenuPanel"; +export const duplicateCol = (protyle: IProtyle, type: TAVCol, avID: string, colId: string, newValue:string) => { + const id = Lute.NewNodeID(); + const nameMatch = newValue.match(/^(.*) \((\d+)\)$/); + if (nameMatch) { + newValue = `${nameMatch[1]} (${parseInt(nameMatch[2]) + 1})`; + } else { + newValue = `${newValue} (1)`; + } + if (["select", "mSelect"].includes(type)) { + fetchPost("/api/av/renderAttributeView", {id: avID}, (response) => { + const data = response.data as IAV; + let colOptions; + data.view.columns.find((item) => { + if (item.id === colId) { + colOptions = item.options; + return true; + } + }); + transaction(protyle, [{ + action: "addAttrViewCol", + name: newValue, + avID, + type, + id + }, { + action: "sortAttrViewCol", + avID, + previousID: colId, + id + }, { + action: "updateAttrViewColOptions", + id, + avID, + data: colOptions + }], [{ + action: "removeAttrViewCol", + id, + avID, + }]); + }); + } else { + transaction(protyle, [{ + action: "addAttrViewCol", + name: newValue, + avID, + type, + id + }, { + action: "sortAttrViewCol", + avID, + previousID: colId, + id + }], [{ + action: "removeAttrViewCol", + id, + avID, + }]); + } +} + export const getEditHTML = (options: { protyle: IProtyle, colId: string, @@ -50,20 +110,24 @@ export const getEditHTML = (options: { } return `${html} - - -`; }; +export const bindEditEvent = (options: { protyle: IProtyle, data: IAV, menuElement: HTMLElement }) => { + // TODO +} + export const getColIconByType = (type: TAVCol) => { switch (type) { case "text": @@ -110,18 +174,6 @@ export const updateHeader = (rowElement: HTMLElement) => { avHeadElement.style.position = "sticky"; }; -const removeCol = (cellElement: HTMLElement) => { - const blockElement = hasClosestBlock(cellElement); - if (!blockElement) { - return false; - } - const colId = cellElement.getAttribute("data-col-id"); - blockElement.querySelectorAll(".av__row").forEach((item) => { - item.querySelector(`[data-col-id="${colId}"]`).remove(); - }); - cellElement.remove(); -}; - export const showColMenu = (protyle: IProtyle, blockElement: HTMLElement, cellElement: HTMLElement) => { const type = cellElement.getAttribute("data-dtype") as TAVCol; const colId = cellElement.getAttribute("data-col-id"); @@ -261,64 +313,7 @@ export const showColMenu = (protyle: IProtyle, blockElement: HTMLElement, cellEl icon: "iconCopy", label: window.siyuan.languages.duplicate, click() { - const id = Lute.NewNodeID(); - let newValue = (window.siyuan.menus.menu.element.querySelector(".b3-text-field") as HTMLInputElement).value; - const nameMatch = newValue.match(/^(.*) \((\d+)\)$/); - if (nameMatch) { - newValue = `${nameMatch[1]} (${parseInt(nameMatch[2]) + 1})`; - } else { - newValue = `${newValue} (1)`; - } - if (["select", "mSelect"].includes(type)) { - fetchPost("/api/av/renderAttributeView", {id: avID}, (response) => { - const data = response.data as IAV; - let colOptions; - data.view.columns.find((item) => { - if (item.id === colId) { - colOptions = item.options; - return true; - } - }); - transaction(protyle, [{ - action: "addAttrViewCol", - name: newValue, - avID, - type, - id - }, { - action: "sortAttrViewCol", - avID, - previousID: colId, - id - }, { - action: "updateAttrViewColOptions", - id, - avID, - data: colOptions - }], [{ - action: "removeAttrViewCol", - id, - avID, - }]); - }); - } else { - transaction(protyle, [{ - action: "addAttrViewCol", - name: newValue, - avID, - type, - id - }, { - action: "sortAttrViewCol", - avID, - previousID: colId, - id - }], [{ - action: "removeAttrViewCol", - id, - avID, - }]); - } + duplicateCol(protyle, type, avID, colId, (window.siyuan.menus.menu.element.querySelector(".b3-text-field") as HTMLInputElement).value); } }); menu.addItem({ @@ -336,7 +331,6 @@ export const showColMenu = (protyle: IProtyle, blockElement: HTMLElement, cellEl type: type, id: colId }]); - removeCol(cellElement); } }); menu.addSeparator(); diff --git a/app/src/protyle/render/av/openMenuPanel.ts b/app/src/protyle/render/av/openMenuPanel.ts index 4c44ca3b6..bcd20ce3f 100644 --- a/app/src/protyle/render/av/openMenuPanel.ts +++ b/app/src/protyle/render/av/openMenuPanel.ts @@ -1,7 +1,7 @@ import {transaction} from "../../wysiwyg/transaction"; import {fetchPost} from "../../../util/fetch"; import {addCol} from "./addCol"; -import {getColIconByType, getEditHTML} from "./col"; +import {bindEditEvent, duplicateCol, getColIconByType, getEditHTML} from "./col"; import {setPosition} from "../../../util/setPosition"; import {hasClosestByAttribute} from "../../util/hasClosest"; import {bindSelectEvent, getSelectHTML, addColOptionOrCell, setColOption, removeCellOption} from "./select"; @@ -21,8 +21,8 @@ export const openMenuPanel = (options: { return; } window.siyuan.menus.menu.remove(); - const avId = options.blockElement.getAttribute("data-av-id"); - fetchPost("/api/av/renderAttributeView", {id: avId}, (response) => { + const avID = options.blockElement.getAttribute("data-av-id"); + fetchPost("/api/av/renderAttributeView", {id: avID}, (response) => { const data = response.data as IAV; let html; if (options.type === "config") { @@ -56,6 +56,8 @@ export const openMenuPanel = (options: { setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); if (options.type === "sorts") { bindSortsEvent(options.protyle, menuElement, data); + } else if (options.type === "edit") { + bindEditEvent({protyle: options.protyle, data, menuElement}) } } avPanelElement.addEventListener("dragstart", (event) => { @@ -125,6 +127,7 @@ export const openMenuPanel = (options: { data, colId }); + bindEditEvent({protyle: options.protyle, data, menuElement}) } return; } @@ -153,11 +156,11 @@ export const openMenuPanel = (options: { transaction(options.protyle, [{ action: "setAttrViewSorts", - avID: avId, + avID, data: changeData }], [{ action: "setAttrViewSorts", - avID: avId, + avID, data: oldData }]); menuElement.innerHTML = getSortsHTML(data.view.columns, data.view.sorts); @@ -187,11 +190,11 @@ export const openMenuPanel = (options: { transaction(options.protyle, [{ action: "setAttrViewFilters", - avID: avId, + avID, data: changeData }], [{ action: "setAttrViewFilters", - avID: avId, + avID, data: oldData }]); menuElement.innerHTML = getFiltersHTML(data.view); @@ -199,12 +202,12 @@ export const openMenuPanel = (options: { } transaction(options.protyle, [{ action: "sortAttrViewCol", - avID: avId, + avID, previousID: (targetElement.classList.contains("dragover__top") ? targetElement.previousElementSibling?.getAttribute("data-id") : targetElement.getAttribute("data-id")) || "", id: sourceId, }], [{ action: "sortAttrViewCol", - avID: avId, + avID, previousID: sourceElement.previousElementSibling?.getAttribute("data-id") || "", id: sourceId, }]); @@ -288,11 +291,11 @@ export const openMenuPanel = (options: { } else if (type === "removeSorts") { transaction(options.protyle, [{ action: "setAttrViewSorts", - avID: avId, + avID, data: [] }], [{ action: "setAttrViewSorts", - avID: avId, + avID, data: data.view.sorts }]); data.view.sorts = []; @@ -307,7 +310,7 @@ export const openMenuPanel = (options: { rect: target.getBoundingClientRect(), menuElement, tabRect, - avId, + avId: avID, protyle: options.protyle }); event.stopPropagation(); @@ -322,11 +325,11 @@ export const openMenuPanel = (options: { }); transaction(options.protyle, [{ action: "setAttrViewSorts", - avID: avId, + avID, data: data.view.sorts }], [{ action: "setAttrViewSorts", - avID: avId, + avID, data: oldSorts }]); menuElement.innerHTML = getSortsHTML(data.view.columns, data.view.sorts); @@ -342,11 +345,11 @@ export const openMenuPanel = (options: { } else if (type === "removeFilters") { transaction(options.protyle, [{ action: "setAttrViewFilters", - avID: avId, + avID, data: [] }], [{ action: "setAttrViewFilters", - avID: avId, + avID, data: data.view.filters }]); data.view.filters = []; @@ -360,7 +363,7 @@ export const openMenuPanel = (options: { rect: target.getBoundingClientRect(), menuElement, tabRect, - avId, + avId: avID, protyle: options.protyle }); event.stopPropagation(); @@ -376,11 +379,11 @@ export const openMenuPanel = (options: { }); transaction(options.protyle, [{ action: "setAttrViewFilters", - avID: avId, + avID, data: data.view.filters }], [{ action: "setAttrViewFilters", - avID: avId, + avID, data: oldFilters }]); menuElement.innerHTML = getFiltersHTML(data.view); @@ -420,13 +423,13 @@ export const openMenuPanel = (options: { doOperations.push({ action: "setAttrViewColHidden", id: item.id, - avID: avId, + avID, data: false }); undoOperations.push({ action: "setAttrViewColHidden", id: item.id, - avID: avId, + avID, data: true }); item.hidden = false; @@ -447,13 +450,13 @@ export const openMenuPanel = (options: { doOperations.push({ action: "setAttrViewColHidden", id: item.id, - avID: avId, + avID, data: true }); undoOperations.push({ action: "setAttrViewColHidden", id: item.id, - avID: avId, + avID, data: false }); item.hidden = true; @@ -472,44 +475,89 @@ export const openMenuPanel = (options: { data, colId: target.parentElement.dataset.id }); + bindEditEvent({protyle: options.protyle, data, menuElement}); event.stopPropagation(); break; } else if (type === "hideCol") { - const colId = target.parentElement.getAttribute("data-id"); + const isEdit = menuElement.querySelector('[data-type="goProperties"]') + const colId = isEdit ? menuElement.firstElementChild.getAttribute("data-col-id") : target.parentElement.getAttribute("data-id"); transaction(options.protyle, [{ action: "setAttrViewColHidden", id: colId, - avID: avId, + avID, data: true }], [{ action: "setAttrViewColHidden", id: colId, - avID: avId, + avID, data: false }]); data.view.columns.find((item: IAVColumn) => item.id === colId).hidden = true; - menuElement.innerHTML = getPropertiesHTML(data.view); + if (isEdit) { + menuElement.innerHTML = getEditHTML({ + protyle: options.protyle, + data, + colId + }); + bindEditEvent({protyle: options.protyle, data, menuElement}); + } else { + menuElement.innerHTML = getPropertiesHTML(data.view); + } setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); event.stopPropagation(); break; } else if (type === "showCol") { - const colId = target.parentElement.getAttribute("data-id"); + const isEdit = menuElement.querySelector('[data-type="goProperties"]') + const colId = isEdit ? menuElement.firstElementChild.getAttribute("data-col-id") : target.parentElement.getAttribute("data-id"); transaction(options.protyle, [{ action: "setAttrViewColHidden", id: colId, - avID: avId, + avID, data: false }], [{ action: "setAttrViewColHidden", id: colId, - avID: avId, + avID, data: true }]); data.view.columns.find((item: IAVColumn) => item.id === colId).hidden = false; - menuElement.innerHTML = getPropertiesHTML(data.view); + if (isEdit) { + menuElement.innerHTML = getEditHTML({ + protyle: options.protyle, + data, + colId + }); + bindEditEvent({protyle: options.protyle, data, menuElement}); + } else { + menuElement.innerHTML = getPropertiesHTML(data.view); + } setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); event.stopPropagation(); break; + } else if (type === "duplicateCol") { + const colId = menuElement.firstElementChild.getAttribute("data-col-id") + const colData = data.view.columns.find((item: IAVColumn) => item.id === colId) + duplicateCol(options.protyle, colData.type, avID, colId, colData.name); + avPanelElement.remove(); + event.stopPropagation(); + break; + } else if (type === "removeCol") { + const colId = menuElement.firstElementChild.getAttribute("data-col-id") + const colData = data.view.columns.find((item: IAVColumn) => item.id === colId) + transaction(options.protyle, [{ + action: "removeAttrViewCol", + id: colId, + avID, + }], [{ + action: "addAttrViewCol", + name: colData.name, + avID, + type: colData.type, + id: colId + }]); + avPanelElement.remove(); + event.stopPropagation(); + break; } else if (type === "setColOption") { setColOption(options.protyle, data, target, options.cellElements); event.stopPropagation(); @@ -556,7 +604,7 @@ const getPropertiesHTML = (data: IAVTable) => { - + `; } }); diff --git a/app/src/protyle/render/av/select.ts b/app/src/protyle/render/av/select.ts index f7cec0779..7c0fb2a63 100644 --- a/app/src/protyle/render/av/select.ts +++ b/app/src/protyle/render/av/select.ts @@ -3,7 +3,7 @@ import {transaction} from "../../wysiwyg/transaction"; import {hasClosestByClassName} from "../../util/hasClosest"; import {confirmDialog} from "../../../dialog/confirmDialog"; import {upDownHint} from "../../../util/upDownHint"; -import {getEditHTML} from "./col"; +import {bindEditEvent, getEditHTML} from "./col"; const filterSelectHTML = (key: string, options: { name: string, color: string }[]) => { let html = ""; @@ -140,6 +140,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, }); if (!cellElements) { menuElement.innerHTML = getEditHTML({protyle, data, colId}); + bindEditEvent({protyle, data, menuElement}) } else { cellElements.forEach((cellElement: HTMLMediaElement) => { data.view.rows.find(row => { @@ -202,6 +203,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, }); if (!cellElements) { menuElement.innerHTML = getEditHTML({protyle, data, colId}); + bindEditEvent({protyle, data, menuElement}) } else { cellElements.forEach((cellElement: HTMLElement) => { data.view.rows.find(row => { @@ -275,6 +277,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement, }); if (!cellElements) { menuElement.innerHTML = getEditHTML({protyle, data, colId}); + bindEditEvent({protyle, data, menuElement}) } else { cellElements.forEach((cellElement: HTMLElement) => { data.view.rows.find(row => { diff --git a/app/src/protyle/wysiwyg/transaction.ts b/app/src/protyle/wysiwyg/transaction.ts index 23e9005a6..31a4aa004 100644 --- a/app/src/protyle/wysiwyg/transaction.ts +++ b/app/src/protyle/wysiwyg/transaction.ts @@ -654,7 +654,7 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, focus: b } else if (["addAttrViewCol", "insertAttrViewBlock", "updateAttrViewCol", "updateAttrViewColOptions", "updateAttrViewColOption", "updateAttrViewCell", "sortAttrViewRow", "sortAttrViewCol", "setAttrViewColHidden", "setAttrViewColWrap", "setAttrViewColWidth", "removeAttrViewColOption", "setAttrViewName", "setAttrViewFilters", - "setAttrViewSorts", "setAttrViewColCalc"].includes(operation.action)) { + "setAttrViewSorts", "setAttrViewColCalc", "removeAttrViewCol"].includes(operation.action)) { refreshAV(protyle, operation); } };