Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Add Ghost Element for Drag & Drop move #1754

Merged
merged 6 commits into from
Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions changelog/unreleased/enhancement-add-drag-drop-ghost
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Enhancement: Add Ghost Element for Drag & Drop

We've added a custom ghost element for the drag&drop functionality in the OcTableFiles to
better visualize the action to the user.

https://github.com/owncloud/web/issues/5788
https://github.com/owncloud/owncloud-design-system/pull/1754
57 changes: 57 additions & 0 deletions src/components/molecules/OcTable/GhostElement/GhostElement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<template>
<div id="ghost-element" class="ghost-element">
<oc-icon :name="firstPreviewIcon" size="large" />
<span class="badge">{{ itemCount }}</span>
</div>
</template>

<script>
/**
* Please head to the OcTableFiles component (https://owncloud.design/#/oC%20Components/OcTableFiles) for a demo of the Ghost Element.
*/
export default {
lookacat marked this conversation as resolved.
Show resolved Hide resolved
name: "GhostElement",
props: {
previewItems: {
type: Array,
required: true,
},
},
computed: {
firstPreviewIcon() {
const icon = this.previewItems[0].icon
return icon ? icon : "file"
},
itemCount() {
return this.previewItems.length
},
},
}
</script>

<style lang="scss">
.ghost-element {
background-color: transparent;
padding-top: 4px;
padding-left: 5px;
z-index: var(--oc-z-index-modal);
position: absolute;
.badge {
position: absolute;
top: -2px;
right: -8px;
padding: 4px;
line-height: 10px;
-webkit-border-radius: 30px;
-moz-border-radius: 30px;
border-radius: 30px;
min-width: 10px;
height: 10px;
text-align: center;

font-size: 12px;
background: red;
color: white;
}
}
</style>
42 changes: 39 additions & 3 deletions src/components/molecules/OcTable/OcTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@
$emit(constants.EVENT_TROW_CONTEXTMENU, $refs[`row-${trIndex}`][0], $event, item)
"
@hook:mounted="$emit(constants.EVENT_TROW_MOUNTED, item, $refs[`row-${trIndex}`][0])"
@dragstart.native="dragStart(item)"
@dragstart.native="dragStart(item, $event)"
@drop.native="dropRowEvent(item.id, $event)"
@dragenter.native.prevent="dropRowStyling(item.id, false, $event)"
@dragleave.native.prevent="dropRowStyling(item.id, true, $event)"
@mouseleave="dropRowStyling(item.id, true, $event)"
@dragover.native.prevent
@dragover.native="dragOver($event)"
>
<oc-td
v-for="(field, tdIndex) in fields"
Expand Down Expand Up @@ -79,6 +79,7 @@
</table>
</template>
<script>
import Vue from "vue"
import OcThead from "../../atoms/_OcTableHeader/_OcTableHeader.vue"
import OcTbody from "../../atoms/_OcTableBody/_OcTableBody.vue"
import OcTr from "../../atoms/_OcTableRow/_OcTableRow"
Expand All @@ -87,6 +88,7 @@ import OcTd from "../../atoms/_OcTableCellData/_OcTableCellData.vue"
import OcButton from "../../atoms/OcButton/OcButton.vue"
import SortMixin from "../../../mixins/sort"
import { getSizeClass } from "../../../utils/sizeClasses"
import GhostElement from "./GhostElement/GhostElement.vue"

import {
EVENT_THEAD_CLICKED,
Expand Down Expand Up @@ -214,6 +216,11 @@ export default {
required: false,
default: false,
},
selection: {
type: Array,
required: false,
default: () => [],
},
},
data() {
return {
Expand All @@ -223,6 +230,7 @@ export default {
EVENT_TROW_MOUNTED,
EVENT_TROW_CONTEXTMENU,
},
ghostElement: null,
}
},
computed: {
Expand All @@ -248,14 +256,42 @@ export default {
},
},
methods: {
dragStart(file) {
dragOver(event) {
event.preventDefault()
},
setGhostElement(file, event) {
const selection = [...this.selection]
selection.splice(
selection.findIndex(function (i) {
return i.id === file.id
}),
1
)
const GhostElementComponent = Vue.extend(GhostElement)
const ghostInstances = new GhostElementComponent({
propsData: {
previewItems: [file, ...selection],
},
})
ghostInstances.$mount()
this.ghostElement = document.body.appendChild(ghostInstances.$el)
this.ghostElement.ariaHidden = "true"
this.ghostElement.style.left = "-99999px"
this.ghostElement.style.top = "-99999px"
event.dataTransfer.setDragImage(this.ghostElement, 0, 0)
event.dataTransfer.dropEffect = "move"
event.dataTransfer.effectAllowed = "move"
},
dragStart(file, event) {
if (!this.dragDrop) return
this.setGhostElement(file, event)
this.$emit(EVENT_FILE_DRAGGED, file)
},
dropRowEvent(id, event) {
if (!this.dragDrop) return
const hasFilePayload = (event.dataTransfer.types || []).some(e => e === "Files")
if (hasFilePayload) return
this.ghostElement.remove()
const dropTarget = event.target
const dropTargetTr = dropTarget.closest("tr")
const dropFileId = dropTargetTr.dataset.fileId
Expand Down
1 change: 1 addition & 0 deletions src/components/templates/OcTableFiles/OcTableFiles.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:header-position="headerPosition"
:drag-drop="dragDrop"
:hover="hover"
:selection="selection"
@highlight="fileClicked"
@rowMounted="rowMounted"
@contextmenuClicked="showContextMenu"
Expand Down