From 016f58e1a0e7009d4e357ae83560e5d21e6b86b3 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Sat, 20 Jan 2024 12:21:40 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/10142 --- app/src/assets/scss/business/_custom.scss | 4 ++ app/src/protyle/render/av/blockAttr.ts | 75 ++++++++++++++++++++++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/app/src/assets/scss/business/_custom.scss b/app/src/assets/scss/business/_custom.scss index ce656577e..950f4806b 100644 --- a/app/src/assets/scss/business/_custom.scss +++ b/app/src/assets/scss/business/_custom.scss @@ -79,4 +79,8 @@ .av__cellassetimg { max-height: 24px; } + + .dragover__top.av__row { + box-shadow: 0 -2px 0 var(--b3-theme-primary-lighter), inset 0 2px 0 var(--b3-theme-primary-lighter) !important; + } } diff --git a/app/src/protyle/render/av/blockAttr.ts b/app/src/protyle/render/av/blockAttr.ts index 8d6855003..e20a8162e 100644 --- a/app/src/protyle/render/av/blockAttr.ts +++ b/app/src/protyle/render/av/blockAttr.ts @@ -3,8 +3,9 @@ import {addCol, getColIconByType} from "./col"; import {escapeAttr} from "../../../util/escape"; import * as dayjs from "dayjs"; import {popTextCell} from "./cell"; -import {hasClosestBlock} from "../../util/hasClosest"; +import {hasClosestBlock, hasClosestByClassName} from "../../util/hasClosest"; import {unicode2Emoji} from "../../../emoji"; +import {transaction} from "../../wysiwyg/transaction"; const genAVRollupHTML = (value: IAVCellValue) => { let html = ""; @@ -135,6 +136,7 @@ export const renderAVAttribute = (element: HTMLElement, id: string, protyle: IPr type: TAVCol, name: string, icon: string, + id: string, options?: { name: string, color: string @@ -160,7 +162,7 @@ export const renderAVAttribute = (element: HTMLElement, id: string, protyle: IPr `; table.keyValues?.forEach(item => { - html += `
+ html += `
"; }); if (element.innerHTML === "") { + let dragBlockElement: HTMLElement; + element.addEventListener("dragstart", (event: DragEvent) => { + const target = event.target as HTMLElement; + window.siyuan.dragElement = target.parentElement; + window.siyuan.dragElement.style.opacity = ".1"; + dragBlockElement = hasClosestBlock(window.siyuan.dragElement) as HTMLElement; + + const ghostElement = document.createElement("div"); + ghostElement.className = "block__icons" + ghostElement.innerHTML = target.nextElementSibling.outerHTML; + ghostElement.setAttribute("style", "width: 160px;position:fixed;opacity:.1;"); + document.body.append(ghostElement); + event.dataTransfer.setDragImage(ghostElement, 0, 0); + setTimeout(() => { + ghostElement.remove(); + }); + }); + element.addEventListener("drop", (event) => { + window.siyuan.dragElement.style.opacity = ""; + const id = window.siyuan.dragElement.dataset.colId; + window.siyuan.dragElement = null; + const targetElement = element.querySelector(".dragover__bottom, .dragover__top") as HTMLElement + if (!targetElement) { + return; + } + const previousID = targetElement.classList.contains("dragover__bottom") ? targetElement.dataset.colId : targetElement.previousElementSibling?.getAttribute("data-col-id"); + targetElement.classList.remove("dragover__bottom", "dragover__top"); + if (dragBlockElement) { + transaction(protyle, [{ + action: "sortAttrViewCol", + avID: dragBlockElement.dataset.avId, + previousID, + id + }]); + } + }); + element.addEventListener("dragover", (event: DragEvent) => { + const target = event.target as HTMLElement; + let targetElement = hasClosestByClassName(target, "av__row"); + if (!targetElement) { + targetElement = hasClosestByClassName(document.elementFromPoint(event.clientX, event.clientY - 1), "av__row"); + } + if (!targetElement || targetElement.isSameNode(window.siyuan.dragElement) || !dragBlockElement) { + return; + } + const targetBlockElement = hasClosestBlock(targetElement); + if (!targetBlockElement || !targetBlockElement.isSameNode(dragBlockElement)) { + return; + } + event.preventDefault(); + const nodeRect = targetElement.getBoundingClientRect(); + targetElement.classList.remove("dragover__bottom", "dragover__top"); + if (event.clientY > nodeRect.top + nodeRect.height / 2) { + targetElement.classList.add("dragover__bottom"); + } else { + targetElement.classList.add("dragover__top"); + } + }); + element.addEventListener("dragleave", () => { + element.querySelectorAll(".dragover__bottom, .dragover__top").forEach((item: HTMLElement) => { + item.classList.remove("dragover__bottom", "dragover__top"); + }); + }); + element.addEventListener("dragend", () => { + if (window.siyuan.dragElement) { + window.siyuan.dragElement.style.opacity = ""; + window.siyuan.dragElement = undefined; + } + }); element.addEventListener("click", (event) => { let target = event.target as HTMLElement; while (target && !element.isSameNode(target)) {