@setoelkahfi / svara / commits / c50f570

feature: added ability to drag and drop files/folders

Refactored drop function Bug: Moving root directory throws an error

mellbacon committed May 24, 2023 at 14:35 UTC c50f570ae7d463da9c1328ca8a1fa8223c0bb16a
2 files changed +34 -19
src/lib/FileTree/FileTreeList.svelte
+33 -18
@@ -10,6 +10,7 @@
10 import Directory from "../../util/icons/Directory.svelte";
11 import {filetree} from "../FileTree.svelte";
12 import ContextMenu from "../utility/ContextMenu.svelte";
13 + import { moveFile } from "../File";
14
15 export let root = false;
16 export let isroot = false;
@@ -61,39 +62,53 @@
62 }
63
64 function dragstart(e) {
64 - let data = {element: `filetree-node-${id}`, id:id, type: "parent"};
65 + let data = {element: `filetree-node-${id}`, id:id, type: "directory"};
66 e.dataTransfer.setData("text/plain", JSON.stringify(data));
67 }
68
68 - function drop(e) {
69 + async function drop(e) {
70 let data = JSON.parse(e.dataTransfer.getData("text/plain"))
71 let el = document.getElementById(data.element);
72 let from = el.parentElement;
72 - let to = e.target.parentElement.parentElement;
73 -
74 - let fromid = from.getAttribute("data-id");
75 - let toid = to.getAttribute("data-id");
76 -
73 + let to = dropTarget.parentElement.parentElement;
74 + if (dropTarget.hasAttribute("data-nodetype")) {
75 + if (dropTarget.nextElementSibling) {
76 + to = dropTarget.nextElementSibling;
77 + }
78 + else {
79 + to = dropTarget;
80 + }
81 + }
82 +
83 + const fromid = from.getAttribute("data-id");
84 + const toid = to.getAttribute("data-id");
85 const element = findNode(parseInt(data.id));
86 const fromlist = findNode(parseInt(fromid));
87 const tolist = findNode(parseInt(toid));
88 +
89 + if (fromlist.path === tolist.path) return;
90
81 - fromlist.children.splice(fromlist.children.indexOf(element), 1);
82 - tolist.children = [...tolist.children, element];
83 -
84 - from.removeChild(el);
85 - to.appendChild(el);
91 + await moveFile(fromlist.path, tolist.path, element.path, data.type);
92
87 - filetree.set($filetree);
88 -
89 - e.target.parentElement.classList.remove("hover");
93 + e.target.classList.remove("hover");
94 }
95
96 + let dropTarget = null;
97 function dragenter(e) {
93 - e.target.parentElement.classList.add("hover");
98 + switch (e.target.nodeName) {
99 + case "svg": case "SPAN":
100 + dropTarget = e.target.parentElement;
101 + break;
102 + case "path":
103 + dropTarget = e.target.parentElement.parentElement;
104 + break;
105 + default:
106 + dropTarget = e.target;
107 + }
108 + e.target.classList.add("hover");
109 }
110 function dragleave(e) {
96 - e.target.parentElement.classList.remove("hover");
111 + e.target.classList.remove("hover");
112 }
113
114 const toggleExpansion = (event) => {
@@ -136,7 +151,7 @@
151 {:else}
152 <li id={`filetree-node-${id}`} bind:this={ref} class="treenode" class:root={isroot} on:dragenter|stopPropagation={dragenter} on:dragleave|stopPropagation={dragleave} on:dragend|stopPropagation={dragleave} title={path}>
153 <!-- svelte-ignore a11y-click-events-have-key-events -->
139 - <div bind:this={refLabel} class:selected class="tree-label" on:click={toggleExpansion} draggable={true} on:dragstart={dragstart} on:mouseup={(e) => {
154 + <div bind:this={refLabel} data-id={id} class:selected class="tree-label" data-nodetype="directory" on:click={toggleExpansion} on:dragover|preventDefault on:drop|stopPropagation={drop} draggable={true} on:dragstart={dragstart} on:mouseup={(e) => {
155 if (e.button === 2) {
156 contextmenu = true;
157 }
src/lib/FileTree/FileTreeNode.svelte
+1 -1
@@ -42,7 +42,7 @@
42 ]
43
44 function dragstart(e) {
45 - let data = {element: `filetree-node-${id}`, id:id, type: "node"};
45 + let data = {element: `filetree-node-${id}`, id:id, type: "file"};
46 e.dataTransfer.setData("text/plain", JSON.stringify(data));
47 }
48