This commit is contained in:
Vanessa 2023-07-07 23:04:16 +08:00
parent 1bff1ef7cb
commit a410900dc5
2 changed files with 156 additions and 10 deletions

View file

@ -173,6 +173,20 @@
overflow: hidden; overflow: hidden;
} }
&__item {
transition: margin .2s cubic-bezier(0, 0, .2, 1) 0ms;
&.dragover__bottom {
background-color: var(--b3-theme-primary-lightest);
box-shadow: 0 -2px 0 var(--b3-theme-primary-lighter) inset;
}
&.dragover__top {
background-color: var(--b3-theme-primary-lightest);
box-shadow: 0 2px 0 var(--b3-theme-primary-lighter) inset;
}
}
&__item:hover .b3-menu__action { &__item:hover .b3-menu__action {
opacity: 1; opacity: 1;
} }

View file

@ -4,7 +4,7 @@ import {addCol} from "./addCol";
import {getColIconByType} from "./col"; import {getColIconByType} from "./col";
import {setPosition} from "../../../util/setPosition"; import {setPosition} from "../../../util/setPosition";
import {Menu} from "../../../plugin/Menu"; import {Menu} from "../../../plugin/Menu";
import {hasClosestByClassName} from "../../util/hasClosest"; import {hasClosestByAttribute, hasClosestByClassName} from "../../util/hasClosest";
export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type: "properties" | "config" | "sorts" | "filters" = "config") => { export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type: "properties" | "config" | "sorts" | "filters" = "config") => {
let avPanelElement = document.querySelector(".av__panel"); let avPanelElement = document.querySelector(".av__panel");
@ -37,6 +37,138 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height); setPosition(menuElement, tabRect.right - menuElement.clientWidth, tabRect.bottom, tabRect.height);
bindSortsEvent(protyle, menuElement, data); bindSortsEvent(protyle, menuElement, data);
avPanelElement.addEventListener("dragstart", (event) => {
window.siyuan.dragElement = event.target as HTMLElement;
window.siyuan.dragElement.style.opacity = ".1";
return;
});
avPanelElement.addEventListener("drop", (event) => {
window.siyuan.dragElement.style.opacity = "";
const sourceElement = window.siyuan.dragElement;
window.siyuan.dragElement = undefined;
if (protyle.disabled) {
event.preventDefault();
event.stopPropagation();
return;
}
const target = event.target as HTMLElement;
const targetElement = hasClosestByAttribute(target, "data-id", null);
if (!targetElement ||
(!targetElement.classList.contains("dragover__top") && !targetElement.classList.contains("dragover__bottom"))) {
return;
}
let type = "columns";
if (targetElement.querySelector('[data-type="removeSort"]')) {
type = "sorts";
} else if (targetElement.querySelector('[data-type="removeFilter"]')) {
type = "filters";
}
const sourceId = sourceElement.dataset.id;
const targetId = targetElement.dataset.id;
const isTop = targetElement.classList.contains("dragover__top")
if (type !== "columns") {
const changeData = (type === "sorts" ? data.sorts : data.filters) as IAVFilter[]
const oldData = Object.assign([], changeData);
let targetFilter: IAVFilter
changeData.find((filter, index: number) => {
if (filter.column === sourceId) {
targetFilter = changeData.splice(index, 1)[0];
return true;
}
})
changeData.find((filter, index: number) => {
if (filter.column === targetId) {
if (isTop) {
changeData.splice(index, 0, targetFilter);
} else {
changeData.splice(index + 1, 0, targetFilter);
}
return true;
}
})
transaction(protyle, [{
action: "setAttrView",
id: avId,
data: {
[type]: changeData
}
}], [{
action: "setAttrView",
id: avId,
data: {
[type]: oldData
}
}]);
menuElement.innerHTML = (type === "sorts" ? getSortsHTML(data) : getFiltersHTML(data));
if (type === "sorts") {
bindSortsEvent(protyle, menuElement, data);
}
return;
}
transaction(protyle, [{
action: "sortAttrViewCol",
parentID: avId,
previousID: (targetElement.classList.contains("dragover__top") ? targetElement.previousElementSibling?.getAttribute("data-id") : targetElement.getAttribute("data-id")) || "",
id: sourceId,
}], [{
action: "sortAttrViewCol",
parentID: avId,
previousID: sourceElement.previousElementSibling?.getAttribute("data-id") || "",
id: sourceId,
}]);
let column: IAVColumn
data.columns.find((item, index: number) => {
if (item.id === sourceId) {
column = data.columns.splice(index, 1)[0];
return true;
}
})
data.columns.find((item, index: number) => {
if (item.id === targetId) {
if (isTop) {
data.columns.splice(index, 0, column);
} else {
data.columns.splice(index + 1, 0, column);
}
return true;
}
})
menuElement.innerHTML = getPropertiesHTML(data)
});
let dragoverElement: HTMLElement
avPanelElement.addEventListener("dragover", (event: DragEvent) => {
const target = event.target as HTMLElement;
const targetElement = hasClosestByAttribute(target, "data-id", null);
if (!targetElement || targetElement.isSameNode(window.siyuan.dragElement)) {
return;
}
event.preventDefault();
if (dragoverElement && targetElement.isSameNode(dragoverElement)) {
const nodeRect = targetElement.getBoundingClientRect();
if (event.clientY > nodeRect.top + nodeRect.height / 2) {
targetElement.classList.add("dragover__bottom");
} else {
targetElement.classList.add("dragover__top");
}
return;
}
dragoverElement = targetElement;
});
avPanelElement.addEventListener("dragleave", (event) => {
const target = event.target as HTMLElement;
const targetElement = hasClosestByAttribute(target, "data-id", null);
if (targetElement) {
targetElement.classList.remove("dragover__top", "dragover__bottom");
}
});
avPanelElement.addEventListener("dragend", (event) => {
if (window.siyuan.dragElement) {
window.siyuan.dragElement.style.opacity = ""
window.siyuan.dragElement = undefined;
}
});
avPanelElement.addEventListener("click", (event) => { avPanelElement.addEventListener("click", (event) => {
event.preventDefault(); event.preventDefault();
let target = event.target as HTMLElement; let target = event.target as HTMLElement;
@ -249,7 +381,7 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
event.stopPropagation(); event.stopPropagation();
break; break;
} else if (type === "hideCol") { } else if (type === "hideCol") {
const colId = target.getAttribute("data-id"); const colId = target.parentElement.getAttribute("data-id");
transaction(protyle, [{ transaction(protyle, [{
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: colId, id: colId,
@ -267,7 +399,7 @@ export const openMenuPanel = (protyle: IProtyle, blockElement: HTMLElement, type
event.stopPropagation(); event.stopPropagation();
break; break;
} else if (type === "showCol") { } else if (type === "showCol") {
const colId = target.getAttribute("data-id"); const colId = target.parentElement.getAttribute("data-id");
transaction(protyle, [{ transaction(protyle, [{
action: "setAttrViewColHidden", action: "setAttrViewColHidden",
id: colId, id: colId,
@ -388,7 +520,7 @@ const getSortsHTML = (data: IAV) => {
return sortHTML; return sortHTML;
}; };
data.sorts.forEach((item: IAVSort) => { data.sorts.forEach((item: IAVSort) => {
html += `<button class="b3-menu__item" data-id="${item.column}"> html += `<button draggable="true" class="b3-menu__item" data-id="${item.column}">
<svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg> <svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg>
<select class="b3-select" style="width: 106px;margin: 4px 0"> <select class="b3-select" style="width: 106px;margin: 4px 0">
${genSortItem(item.column)} ${genSortItem(item.column)}
@ -597,7 +729,7 @@ const getFiltersHTML = (data: IAV) => {
return filterHTML; return filterHTML;
}; };
data.filters.forEach((item: IAVFilter) => { data.filters.forEach((item: IAVFilter) => {
html += `<button class="b3-menu__item" data-type="nobg" data-id="${item.column}"> html += `<button class="b3-menu__item" draggable="true" data-type="nobg" data-id="${item.column}">
<svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg> <svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg>
<div class="fn__flex-1">${genFilterItem(item)}</div> <div class="fn__flex-1">${genFilterItem(item)}</div>
<svg class="b3-menu__action" data-type="removeFilter"><use xlink:href="#iconTrashcan"></use></svg> <svg class="b3-menu__action" data-type="removeFilter"><use xlink:href="#iconTrashcan"></use></svg>
@ -627,7 +759,7 @@ const getPropertiesHTML = (data: IAV) => {
let hideHTML = ""; let hideHTML = "";
data.columns.forEach((item: IAVColumn) => { data.columns.forEach((item: IAVColumn) => {
if (item.hidden) { if (item.hidden) {
hideHTML += `<button class="b3-menu__item" data-type="nobg"> hideHTML += `<button class="b3-menu__item" draggable="true" data-type="nobg" data-id="${item.id}">
<svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg> <svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg>
<div class="fn__flex-1"> <div class="fn__flex-1">
<span class="b3-chip"> <span class="b3-chip">
@ -635,11 +767,11 @@ const getPropertiesHTML = (data: IAV) => {
<span class="fn__ellipsis">${item.name}</span> <span class="fn__ellipsis">${item.name}</span>
</span> </span>
</div> </div>
<svg class="b3-menu__action" data-type="showCol" data-id="${item.id}"><use xlink:href="#iconEyeoff"></use></svg> <svg class="b3-menu__action" data-type="showCol"><use xlink:href="#iconEyeoff"></use></svg>
<svg class="b3-menu__action"><use xlink:href="#iconEdit"></use></svg> <svg class="b3-menu__action"><use xlink:href="#iconEdit"></use></svg>
</button>`; </button>`;
} else { } else {
showHTML += `<button class="b3-menu__item" data-type="nobg"> showHTML += `<button class="b3-menu__item" draggable="true" data-type="nobg" data-id="${item.id}">
<svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg> <svg class="b3-menu__icon"><use xlink:href="#iconDrag"></use></svg>
<div class="fn__flex-1"> <div class="fn__flex-1">
<span class="b3-chip"> <span class="b3-chip">
@ -647,7 +779,7 @@ const getPropertiesHTML = (data: IAV) => {
<span class="fn__ellipsis">${item.name}</span> <span class="fn__ellipsis">${item.name}</span>
</span> </span>
</div> </div>
<svg class="b3-menu__action${item.type === "block" ? " fn__none" : ""}" data-type="hideCol" data-id="${item.id}"><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${item.type === "block" ? " fn__none" : ""}"><use xlink:href="#iconEdit"></use></svg> <svg class="b3-menu__action${item.type === "block" ? " fn__none" : ""}"><use xlink:href="#iconEdit"></use></svg>
</button>`; </button>`;
} }