stable

Clone or download

Read-only

Rewrite drag and drop library

Part of story #14310 stop being bothered by the hidden add-in-place editor when I drag and drop some cards TL;DR How to test: When drag-and-dropping solo cards or children cards: - I can no longer cause "Ranked with itself" issues. - I can no longer drop cards below the "+" or "Add child" button. - No other functional change. How did we end up here ? ------------------------ During taskboard developpment, we stumbled upon issues with the drag-and-drop library: - Cards could be dropped below the "+" button, which is bad UX (the "+" button should always be at the bottom of the dropzone) - Cards could be dropped in comparison to themselves and would trigger a "Ranked with itself" error in the backend. Those issues are **impossible** to solve with the existing drag and drop library, as there is no way to ignore some of the children of a dropzone, but not others. The library *expects* all children to be "draggables". We cannot have a "+" button to add cards inside the dropzone AND have the library ignore it. Why not modify / fork the existing lib ? ---------------------------------------- - The existing drag and drop library, dragula, is unmaintained (see [0]). At the time of this commit, it has not seen a push since one year (Dec 2018). The last release is even older (see [1]) and is three years old (Sep 2016). - Being unmaintained, this library will not accept pull requests and does not update its (admittedly few) dependencies. - Being unmaintained, it does not update its dev dependencies either, which means tests depend on old electron, phantomJS. We are not familiar with its test framework (Tap). - Its coding style is not the easiest to understand (usage of many closures, ES5, abbreviated variables, etc.). - Even IF it was maintained, there is no guarantee that the features we want would be accepted. For all of the above reasons, we chose NOT to fork dragula. Why not find another lib ? -------------------------- During *all* of our spikes and tries using existing drag and drop libraries, one (or several) of our requirements were not met. All <framework-name>-drag-and-drop libraries try to do too much. Drag and drop wrappers bound to frameworks like Vue.js or AngularJS update the framework model all by themselves, which leaves us hanging when we want to apply changes ourselves. For example they will change the list of children, when what we really want is to dispatch an action which will change that list itself. They are also much more complicated, as you now need to pass both Elements and "Data" types, or you must use built-in Components which restrict what your DOM looks like, etc. Other libraries that are not tied to a particular framework come with strong assumptions, like "all children of a dropzone are draggables". This leaves our initial problem unresolved. We have investigated using a low-level library named interact.js (see [2]) that **does not** update the DOM by itself, which is what we want. After a while it became clear that we did not actually need any of its features. In addition it was poorly typed and the API was hard to understand and use. Why write our own library ? --------------------------- Given all of the above information, it became clear that, even in 2020, drag and drop is not easy. The best choice was to write our own library. We would have low-level control over everything and could update or not update the DOM as we wish. Functional changes with dragula ------------------------------- Draggable elements **must** have an attribute `draggable="true"`. There is no equivalent to "gu-mirror". The "drag mirror" is generated by the browser itself. The mouse cursor during drag is adapted by the browser to give feedback. It is different when a drop is possible and when it is not. There is **no way to cancel** from a script. I have searched and tried, believe me. That means we **cannot** bind the ESC key to "cancel()". However, I don't believe it is a problem: - Chromium-based browsers bind the ESC key on "cancel" by themselves. - For users on Firefox and other browsers, they can drop on any non-valid position to cancel. If they did drop to a legitimate dropzone by accident, they can simply drag and drop again to where they wanted. Users with touch screens cannot press ESC at the same time, so this sort of behaviour should not really surprise people. What is this ? -------------- This is an implementation of the HTML5 drag-and-drop specification (see [3]). While this API has flaws, it is still much easier than going even lower-level with PointerEvents. It has no dependencies and **reduces** Taskboard's minified size to 260 KiB. With the previous lib, taskboard had 7 more package dependencies and a size of 264 KiB. It is entirely written in TypeScript and SCSS (2 CSS classes). It is named "Drekkenov" after Archein von Drekkenov [4] who is a character in "The Dungeon of Naheulbeuk" [5]. I wrote it, I get to name it ;) [0]: https://github.com/bevacqua/dragula [1]: https://github.com/bevacqua/dragula/commit/a13d7db9e698fa9bc866855a5556ca5fb61f2bc2 [2]: https://interactjs.io/ [3]: https://www.w3.org/html/wg/spec/dnd.html [4]: https://en.wikipedia.org/wiki/Le_donjon_de_Naheulbeuk [5]: http://www.penofchaos.com/warham/donjon.htm Change-Id: I8f66c310fb5b0534376bd56473499102e5d67bbc

Modified Files

Name
M plugins/taskboard/scripts/package-lock.json +0 −47 Go to diff View file
M plugins/taskboard/scripts/package.json +0 −2 Go to diff View file
M plugins/taskboard/scripts/taskboard/src/components/TaskBoard/Body/Swimlane/Card/ChildCard.test.ts +2 −2 Go to diff View file
M plugins/taskboard/scripts/taskboard/src/components/TaskBoard/Body/Swimlane/Card/ChildCard.vue +1 −1 Go to diff View file
M plugins/taskboard/scripts/taskboard/src/components/TaskBoard/Body/Swimlane/Cell/SoloSwimlaneCell.test.ts +2 −2 Go to diff View file
M plugins/taskboard/scripts/taskboard/src/components/TaskBoard/Body/Swimlane/Cell/SoloSwimlaneCell.vue +1 −1 Go to diff View file
M plugins/taskboard/scripts/taskboard/src/components/TaskBoard/TaskBoard.test.ts +11 −59 Go to diff View file
M plugins/taskboard/scripts/taskboard/src/components/TaskBoard/TaskBoard.vue +79 −82 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/DocumentEventsHandler.ts +46 −0 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/DragGhost.ts +129 −0 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/DrekkenovState.ts +69 −0 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/OngoingDrag.ts +52 −0 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/constants.ts +23 −0 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/dom-manipulation.ts +88 −0 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/drekkenov.scss +26 −0 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/drekkenov.ts +52 −0 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/event-handler-factory.ts +212 −0 Go to diff View file
A plugins/taskboard/scripts/taskboard/src/helpers/drag-and-drop/types.ts +91 −0 Go to diff View file
M plugins/taskboard/scripts/taskboard/src/helpers/drag-drop.test.ts +2 −2 Go to diff View file
M plugins/taskboard/scripts/taskboard/src/helpers/drag-drop.ts +5 −1 Go to diff View file
M plugins/taskboard/themes/_taskboard.scss +1 −1 Go to diff View file
M plugins/taskboard/themes/includes/_body.scss +2 −2 Go to diff View file
M plugins/taskboard/themes/includes/_card-edit.scss +2 −2 Go to diff View file
M plugins/taskboard/themes/includes/_card-read.scss +1 −17 Go to diff View file
M tsconfig.json +2 −1 Go to diff View file