Vanessa 2023-07-18 01:38:59 +08:00
parent 317ecdb618
commit a45de887b5
4 changed files with 153 additions and 108 deletions

View file

@ -6,6 +6,66 @@ import {getDefaultOperatorByType, setFilter} from "./filter";
import {genCellValue} from "./cell"; import {genCellValue} from "./cell";
import {openMenuPanel} from "./openMenuPanel"; 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: { export const getEditHTML = (options: {
protyle: IProtyle, protyle: IProtyle,
colId: string, colId: string,
@ -50,20 +110,24 @@ export const getEditHTML = (options: {
} }
return `${html} return `${html}
<button class="b3-menu__separator"></button> <button class="b3-menu__separator"></button>
<button class="b3-menu__item"> <button class="b3-menu__item" data-type="${colData.hidden ? "showCol" : "hideCol"}">
<svg class="b3-menu__icon" style=""><use xlink:href="#icon${colData.hidden ? "Eye" : "Eyeoff"}"></use></svg> <svg class="b3-menu__icon" style=""><use xlink:href="#icon${colData.hidden ? "Eye" : "Eyeoff"}"></use></svg>
<span class="b3-menu__label">${colData.hidden ? window.siyuan.languages.showCol : window.siyuan.languages.hideCol}</span> <span class="b3-menu__label">${colData.hidden ? window.siyuan.languages.showCol : window.siyuan.languages.hideCol}</span>
</button> </button>
<button class="b3-menu__item"> <button class="b3-menu__item" data-type="duplicateCol">
<svg class="b3-menu__icon" style=""><use xlink:href="#iconCopy"></use></svg> <svg class="b3-menu__icon" style=""><use xlink:href="#iconCopy"></use></svg>
<span class="b3-menu__label">${window.siyuan.languages.duplicate}</span> <span class="b3-menu__label">${window.siyuan.languages.duplicate}</span>
</button> </button>
<button class="b3-menu__item"> <button class="b3-menu__item" data-type="removeCol">
<svg class="b3-menu__icon" style=""><use xlink:href="#iconTrashcan"></use></svg> <svg class="b3-menu__icon" style=""><use xlink:href="#iconTrashcan"></use></svg>
<span class="b3-menu__label">${window.siyuan.languages.delete}</span> <span class="b3-menu__label">${window.siyuan.languages.delete}</span>
</button>`; </button>`;
}; };
export const bindEditEvent = (options: { protyle: IProtyle, data: IAV, menuElement: HTMLElement }) => {
// TODO
}
export const getColIconByType = (type: TAVCol) => { export const getColIconByType = (type: TAVCol) => {
switch (type) { switch (type) {
case "text": case "text":
@ -110,18 +174,6 @@ export const updateHeader = (rowElement: HTMLElement) => {
avHeadElement.style.position = "sticky"; 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) => { export const showColMenu = (protyle: IProtyle, blockElement: HTMLElement, cellElement: HTMLElement) => {
const type = cellElement.getAttribute("data-dtype") as TAVCol; const type = cellElement.getAttribute("data-dtype") as TAVCol;
const colId = cellElement.getAttribute("data-col-id"); const colId = cellElement.getAttribute("data-col-id");
@ -261,64 +313,7 @@ export const showColMenu = (protyle: IProtyle, blockElement: HTMLElement, cellEl
icon: "iconCopy", icon: "iconCopy",
label: window.siyuan.languages.duplicate, label: window.siyuan.languages.duplicate,
click() { click() {
const id = Lute.NewNodeID(); duplicateCol(protyle, type, avID, colId, (window.siyuan.menus.menu.element.querySelector(".b3-text-field") as HTMLInputElement).value);
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,
}]);
}
} }
}); });
menu.addItem({ menu.addItem({
@ -336,7 +331,6 @@ export const showColMenu = (protyle: IProtyle, blockElement: HTMLElement, cellEl
type: type, type: type,
id: colId id: colId
}]); }]);
removeCol(cellElement);
} }
}); });
menu.addSeparator(); menu.addSeparator();

View file

@ -1,7 +1,7 @@
import {transaction} from "../../wysiwyg/transaction"; import {transaction} from "../../wysiwyg/transaction";
import {fetchPost} from "../../../util/fetch"; import {fetchPost} from "../../../util/fetch";
import {addCol} from "./addCol"; import {addCol} from "./addCol";
import {getColIconByType, getEditHTML} from "./col"; import {bindEditEvent, duplicateCol, getColIconByType, getEditHTML} from "./col";
import {setPosition} from "../../../util/setPosition"; import {setPosition} from "../../../util/setPosition";
import {hasClosestByAttribute} from "../../util/hasClosest"; import {hasClosestByAttribute} from "../../util/hasClosest";
import {bindSelectEvent, getSelectHTML, addColOptionOrCell, setColOption, removeCellOption} from "./select"; import {bindSelectEvent, getSelectHTML, addColOptionOrCell, setColOption, removeCellOption} from "./select";
@ -21,8 +21,8 @@ export const openMenuPanel = (options: {
return; return;
} }
window.siyuan.menus.menu.remove(); window.siyuan.menus.menu.remove();
const avId = options.blockElement.getAttribute("data-av-id"); const avID = options.blockElement.getAttribute("data-av-id");
fetchPost("/api/av/renderAttributeView", {id: avId}, (response) => { fetchPost("/api/av/renderAttributeView", {id: avID}, (response) => {
const data = response.data as IAV; const data = response.data as IAV;
let html; let html;
if (options.type === "config") { if (options.type === "config") {
@ -56,6 +56,8 @@ export const openMenuPanel = (options: {
setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height);
if (options.type === "sorts") { if (options.type === "sorts") {
bindSortsEvent(options.protyle, menuElement, data); bindSortsEvent(options.protyle, menuElement, data);
} else if (options.type === "edit") {
bindEditEvent({protyle: options.protyle, data, menuElement})
} }
} }
avPanelElement.addEventListener("dragstart", (event) => { avPanelElement.addEventListener("dragstart", (event) => {
@ -125,6 +127,7 @@ export const openMenuPanel = (options: {
data, data,
colId colId
}); });
bindEditEvent({protyle: options.protyle, data, menuElement})
} }
return; return;
} }
@ -153,11 +156,11 @@ export const openMenuPanel = (options: {
transaction(options.protyle, [{ transaction(options.protyle, [{
action: "setAttrViewSorts", action: "setAttrViewSorts",
avID: avId, avID,
data: changeData data: changeData
}], [{ }], [{
action: "setAttrViewSorts", action: "setAttrViewSorts",
avID: avId, avID,
data: oldData data: oldData
}]); }]);
menuElement.innerHTML = getSortsHTML(data.view.columns, data.view.sorts); menuElement.innerHTML = getSortsHTML(data.view.columns, data.view.sorts);
@ -187,11 +190,11 @@ export const openMenuPanel = (options: {
transaction(options.protyle, [{ transaction(options.protyle, [{
action: "setAttrViewFilters", action: "setAttrViewFilters",
avID: avId, avID,
data: changeData data: changeData
}], [{ }], [{
action: "setAttrViewFilters", action: "setAttrViewFilters",
avID: avId, avID,
data: oldData data: oldData
}]); }]);
menuElement.innerHTML = getFiltersHTML(data.view); menuElement.innerHTML = getFiltersHTML(data.view);
@ -199,12 +202,12 @@ export const openMenuPanel = (options: {
} }
transaction(options.protyle, [{ transaction(options.protyle, [{
action: "sortAttrViewCol", action: "sortAttrViewCol",
avID: avId, avID,
previousID: (targetElement.classList.contains("dragover__top") ? targetElement.previousElementSibling?.getAttribute("data-id") : targetElement.getAttribute("data-id")) || "", previousID: (targetElement.classList.contains("dragover__top") ? targetElement.previousElementSibling?.getAttribute("data-id") : targetElement.getAttribute("data-id")) || "",
id: sourceId, id: sourceId,
}], [{ }], [{
action: "sortAttrViewCol", action: "sortAttrViewCol",
avID: avId, avID,
previousID: sourceElement.previousElementSibling?.getAttribute("data-id") || "", previousID: sourceElement.previousElementSibling?.getAttribute("data-id") || "",
id: sourceId, id: sourceId,
}]); }]);
@ -288,11 +291,11 @@ export const openMenuPanel = (options: {
} else if (type === "removeSorts") { } else if (type === "removeSorts") {
transaction(options.protyle, [{ transaction(options.protyle, [{
action: "setAttrViewSorts", action: "setAttrViewSorts",
avID: avId, avID,
data: [] data: []
}], [{ }], [{
action: "setAttrViewSorts", action: "setAttrViewSorts",
avID: avId, avID,
data: data.view.sorts data: data.view.sorts
}]); }]);
data.view.sorts = []; data.view.sorts = [];
@ -307,7 +310,7 @@ export const openMenuPanel = (options: {
rect: target.getBoundingClientRect(), rect: target.getBoundingClientRect(),
menuElement, menuElement,
tabRect, tabRect,
avId, avId: avID,
protyle: options.protyle protyle: options.protyle
}); });
event.stopPropagation(); event.stopPropagation();
@ -322,11 +325,11 @@ export const openMenuPanel = (options: {
}); });
transaction(options.protyle, [{ transaction(options.protyle, [{
action: "setAttrViewSorts", action: "setAttrViewSorts",
avID: avId, avID,
data: data.view.sorts data: data.view.sorts
}], [{ }], [{
action: "setAttrViewSorts", action: "setAttrViewSorts",
avID: avId, avID,
data: oldSorts data: oldSorts
}]); }]);
menuElement.innerHTML = getSortsHTML(data.view.columns, data.view.sorts); menuElement.innerHTML = getSortsHTML(data.view.columns, data.view.sorts);
@ -342,11 +345,11 @@ export const openMenuPanel = (options: {
} else if (type === "removeFilters") { } else if (type === "removeFilters") {
transaction(options.protyle, [{ transaction(options.protyle, [{
action: "setAttrViewFilters", action: "setAttrViewFilters",
avID: avId, avID,
data: [] data: []
}], [{ }], [{
action: "setAttrViewFilters", action: "setAttrViewFilters",
avID: avId, avID,
data: data.view.filters data: data.view.filters
}]); }]);
data.view.filters = []; data.view.filters = [];
@ -360,7 +363,7 @@ export const openMenuPanel = (options: {
rect: target.getBoundingClientRect(), rect: target.getBoundingClientRect(),
menuElement, menuElement,
tabRect, tabRect,
avId, avId: avID,
protyle: options.protyle protyle: options.protyle
}); });
event.stopPropagation(); event.stopPropagation();
@ -376,11 +379,11 @@ export const openMenuPanel = (options: {
}); });
transaction(options.protyle, [{ transaction(options.protyle, [{
action: "setAttrViewFilters", action: "setAttrViewFilters",
avID: avId, avID,
data: data.view.filters data: data.view.filters
}], [{ }], [{
action: "setAttrViewFilters", action: "setAttrViewFilters",
avID: avId, avID,
data: oldFilters data: oldFilters
}]); }]);
menuElement.innerHTML = getFiltersHTML(data.view); menuElement.innerHTML = getFiltersHTML(data.view);
@ -420,13 +423,13 @@ export const openMenuPanel = (options: {
doOperations.push({ doOperations.push({
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: item.id, id: item.id,
avID: avId, avID,
data: false data: false
}); });
undoOperations.push({ undoOperations.push({
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: item.id, id: item.id,
avID: avId, avID,
data: true data: true
}); });
item.hidden = false; item.hidden = false;
@ -447,13 +450,13 @@ export const openMenuPanel = (options: {
doOperations.push({ doOperations.push({
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: item.id, id: item.id,
avID: avId, avID,
data: true data: true
}); });
undoOperations.push({ undoOperations.push({
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: item.id, id: item.id,
avID: avId, avID,
data: false data: false
}); });
item.hidden = true; item.hidden = true;
@ -472,44 +475,89 @@ export const openMenuPanel = (options: {
data, data,
colId: target.parentElement.dataset.id colId: target.parentElement.dataset.id
}); });
bindEditEvent({protyle: options.protyle, data, menuElement});
event.stopPropagation(); event.stopPropagation();
break; break;
} else if (type === "hideCol") { } 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, [{ transaction(options.protyle, [{
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: colId, id: colId,
avID: avId, avID,
data: true data: true
}], [{ }], [{
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: colId, id: colId,
avID: avId, avID,
data: false data: false
}]); }]);
data.view.columns.find((item: IAVColumn) => item.id === colId).hidden = true; data.view.columns.find((item: IAVColumn) => item.id === colId).hidden = true;
if (isEdit) {
menuElement.innerHTML = getEditHTML({
protyle: options.protyle,
data,
colId
});
bindEditEvent({protyle: options.protyle, data, menuElement});
} else {
menuElement.innerHTML = getPropertiesHTML(data.view); menuElement.innerHTML = getPropertiesHTML(data.view);
}
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 === "showCol") { } 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, [{ transaction(options.protyle, [{
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: colId, id: colId,
avID: avId, avID,
data: false data: false
}], [{ }], [{
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: colId, id: colId,
avID: avId, avID,
data: true data: true
}]); }]);
data.view.columns.find((item: IAVColumn) => item.id === colId).hidden = false; data.view.columns.find((item: IAVColumn) => item.id === colId).hidden = false;
if (isEdit) {
menuElement.innerHTML = getEditHTML({
protyle: options.protyle,
data,
colId
});
bindEditEvent({protyle: options.protyle, data, menuElement});
} else {
menuElement.innerHTML = getPropertiesHTML(data.view); menuElement.innerHTML = getPropertiesHTML(data.view);
}
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 === "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") { } else if (type === "setColOption") {
setColOption(options.protyle, data, target, options.cellElements); setColOption(options.protyle, data, target, options.cellElements);
event.stopPropagation(); event.stopPropagation();
@ -556,7 +604,7 @@ const getPropertiesHTML = (data: IAVTable) => {
</span> </span>
</div> </div>
<svg class="b3-menu__action${item.type === "block" ? " fn__none" : ""}" data-type="hideCol"><use xlink:href="#iconEye"></use></svg> <svg class="b3-menu__action${item.type === "block" ? " fn__none" : ""}" data-type="hideCol"><use xlink:href="#iconEye"></use></svg>
<svg class="b3-menu__action" data-type="editCol"><use xlink:href="#iconEdit"></use></svg> <svg class="b3-menu__action${item.type === "block" ? " fn__none" : ""}" data-type="editCol"><use xlink:href="#iconEdit"></use></svg>
</button>`; </button>`;
} }
}); });

View file

@ -3,7 +3,7 @@ import {transaction} from "../../wysiwyg/transaction";
import {hasClosestByClassName} from "../../util/hasClosest"; import {hasClosestByClassName} from "../../util/hasClosest";
import {confirmDialog} from "../../../dialog/confirmDialog"; import {confirmDialog} from "../../../dialog/confirmDialog";
import {upDownHint} from "../../../util/upDownHint"; import {upDownHint} from "../../../util/upDownHint";
import {getEditHTML} from "./col"; import {bindEditEvent, getEditHTML} from "./col";
const filterSelectHTML = (key: string, options: { name: string, color: string }[]) => { const filterSelectHTML = (key: string, options: { name: string, color: string }[]) => {
let html = ""; let html = "";
@ -140,6 +140,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement,
}); });
if (!cellElements) { if (!cellElements) {
menuElement.innerHTML = getEditHTML({protyle, data, colId}); menuElement.innerHTML = getEditHTML({protyle, data, colId});
bindEditEvent({protyle, data, menuElement})
} else { } else {
cellElements.forEach((cellElement: HTMLMediaElement) => { cellElements.forEach((cellElement: HTMLMediaElement) => {
data.view.rows.find(row => { data.view.rows.find(row => {
@ -202,6 +203,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement,
}); });
if (!cellElements) { if (!cellElements) {
menuElement.innerHTML = getEditHTML({protyle, data, colId}); menuElement.innerHTML = getEditHTML({protyle, data, colId});
bindEditEvent({protyle, data, menuElement})
} else { } else {
cellElements.forEach((cellElement: HTMLElement) => { cellElements.forEach((cellElement: HTMLElement) => {
data.view.rows.find(row => { data.view.rows.find(row => {
@ -275,6 +277,7 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement,
}); });
if (!cellElements) { if (!cellElements) {
menuElement.innerHTML = getEditHTML({protyle, data, colId}); menuElement.innerHTML = getEditHTML({protyle, data, colId});
bindEditEvent({protyle, data, menuElement})
} else { } else {
cellElements.forEach((cellElement: HTMLElement) => { cellElements.forEach((cellElement: HTMLElement) => {
data.view.rows.find(row => { data.view.rows.find(row => {

View file

@ -654,7 +654,7 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, focus: b
} else if (["addAttrViewCol", "insertAttrViewBlock", "updateAttrViewCol", "updateAttrViewColOptions", } else if (["addAttrViewCol", "insertAttrViewBlock", "updateAttrViewCol", "updateAttrViewColOptions",
"updateAttrViewColOption", "updateAttrViewCell", "sortAttrViewRow", "sortAttrViewCol", "setAttrViewColHidden", "updateAttrViewColOption", "updateAttrViewCell", "sortAttrViewRow", "sortAttrViewCol", "setAttrViewColHidden",
"setAttrViewColWrap", "setAttrViewColWidth", "removeAttrViewColOption", "setAttrViewName", "setAttrViewFilters", "setAttrViewColWrap", "setAttrViewColWidth", "removeAttrViewColOption", "setAttrViewName", "setAttrViewFilters",
"setAttrViewSorts", "setAttrViewColCalc"].includes(operation.action)) { "setAttrViewSorts", "setAttrViewColCalc", "removeAttrViewCol"].includes(operation.action)) {
refreshAV(protyle, operation); refreshAV(protyle, operation);
} }
}; };