Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/tasks.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaimund Schlüßler <raimund.schluessler@mailbox.org>2020-01-23 23:25:08 +0300
committerRaimund Schlüßler <raimund.schluessler@mailbox.org>2020-02-05 00:49:18 +0300
commit3ae623cf08c90b76ef969a3c140eb6fd3a611144 (patch)
treec53e85d451166590178531f8d7b82bf52975ad9e /src/components
parent2ab7e6bd3b091413b9fff797a51ddb213d8d1bf9 (diff)
Allow dropping tasks on collections and calendars
Signed-off-by: Raimund Schlüßler <raimund.schluessler@mailbox.org>
Diffstat (limited to 'src/components')
-rw-r--r--src/components/AppNavigation/List.vue93
-rw-r--r--src/components/AppNavigation/ListItemCalendar.vue91
-rw-r--r--src/components/TaskBody.vue14
-rw-r--r--src/components/TaskDragContainer.vue7
4 files changed, 190 insertions, 15 deletions
diff --git a/src/components/AppNavigation/List.vue b/src/components/AppNavigation/List.vue
index 26b3c836..a1ad5b67 100644
--- a/src/components/AppNavigation/List.vue
+++ b/src/components/AppNavigation/List.vue
@@ -31,7 +31,12 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
:to="{ name: 'collections', params: { collectionId: collection.id } }"
:title="collection.displayName"
class="collection reactive"
- @add="dropTaskOnCollection(...arguments, collection)">
+ draggable="false"
+ @dragstart.native="dragStart"
+ @drop.native="dropTaskOnCollection(...arguments, collection)"
+ @dragover.native="dragOver"
+ @dragenter.native="dragEnter(...arguments, collection)"
+ @dragleave.native="dragLeave">
<AppNavigationCounter slot="counter">
{{ collectionCount(collection.id) | counterFormatter }}
</AppNavigationCounter>
@@ -140,11 +145,87 @@ export default {
'setPercentComplete',
'setDate',
]),
- dropTaskOnCollection: function($event, collection) {
- let task
- const taskAttribute = $event.item.attributes['task-id']
- if (taskAttribute) {
- task = this.getTask(taskAttribute.value)
+
+ /**
+ * Handle the drag start
+ *
+ * @param {Object} e The event object
+ * @returns {Boolean}
+ */
+ dragStart(e) {
+ e.stopPropagation()
+ e.preventDefault()
+ return false
+ },
+ /**
+ * Handle the drag over
+ *
+ * @param {Object} e The event object
+ * @returns {Boolean}
+ */
+ dragOver(e) {
+ if (e.preventDefault) {
+ e.preventDefault()
+ }
+ return false
+ },
+ /**
+ * Set the appropriate class on hovering
+ *
+ * @param {Object} e The event object
+ * @param {Object} collection The collection on which the task was dropped
+ */
+ dragEnter(e, collection) {
+ // Check if dropping here is allowed
+ if (!['starred', 'completed', 'today', 'week'].includes(collection.id)) {
+ return
+ }
+ // Get the correct element, in case we hover a child.
+ if (e.target.closest) {
+ const target = e.target.closest('li.collection')
+ if (target) {
+ const collections = document.querySelectorAll('li.collection')
+ collections.forEach((f) => { f.classList.remove('dnd-hover') })
+ target.classList.add('dnd-hover')
+ }
+ }
+ },
+ /**
+ * Remove the hovering class after leaving
+ *
+ * @param {Object} e The event object
+ */
+ dragLeave(e) {
+ // Don't do anything if we leave towards a child element.
+ if (e.target.contains(e.relatedTarget)) {
+ return
+ }
+ // Get the correct element, in case we leave directly from a child.
+ if (e.target.closest) {
+ const target = e.target.closest('li.collection')
+ if (!target || target.contains(e.relatedTarget)) {
+ return
+ }
+ target.classList.remove('dnd-hover')
+ }
+ },
+ /**
+ * Drop a task on a collection
+ *
+ * @param {Object} e The event object
+ * @param {Object} collection The collection
+ */
+ dropTaskOnCollection(e, collection) {
+ // Remove all hover classes
+ const collections = document.querySelectorAll('li.collection')
+ collections.forEach((f) => { f.classList.remove('dnd-hover') })
+ // Check if dropping here is allowed
+ if (!['starred', 'completed', 'today', 'week'].includes(collection.id)) {
+ return
+ }
+ const taskUri = e.dataTransfer.getData('text/plain')
+ if (taskUri) {
+ const task = this.getTask(taskUri)
switch (collection.id) {
case 'starred':
this.setPriority({ task: task, priority: 1 })
diff --git a/src/components/AppNavigation/ListItemCalendar.vue b/src/components/AppNavigation/ListItemCalendar.vue
index cc31bfc6..05dc7c21 100644
--- a/src/components/AppNavigation/ListItemCalendar.vue
+++ b/src/components/AppNavigation/ListItemCalendar.vue
@@ -28,7 +28,12 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
:title="calendar.displayName"
:class="{edit: editing, deleted: !!deleteTimeout}"
class="list reactive"
- @add="dropTaskOnCalendar(...arguments, calendar)">
+ draggable="false"
+ @dragstart.native="dragStart"
+ @drop.native="dropTask"
+ @dragover.native="dragOver"
+ @dragenter.native="dragEnter"
+ @dragleave.native="dragLeave">
<AppNavigationIconBullet slot="icon" :color="calendar.color" />
<template v-if="!deleteTimeout" slot="counter">
@@ -235,13 +240,83 @@ export default {
'deleteCalendar',
'moveTask',
]),
- dropTaskOnCalendar: function($event, calendar) {
- let task
- const taskAttribute = $event.item.attributes['task-id']
- if (taskAttribute) {
- task = this.getTask(taskAttribute.value)
- if (calendar !== task.calendar) {
- this.moveTask({ task: task, calendar: calendar, parent: undefined })
+
+ /**
+ * Handle the drag start
+ *
+ * @param {Object} e The event object
+ * @returns {Boolean}
+ */
+ dragStart(e) {
+ e.stopPropagation()
+ e.preventDefault()
+ return false
+ },
+ /**
+ * Handle the drag over
+ *
+ * @param {Object} e The event object
+ * @returns {Boolean}
+ */
+ dragOver(e) {
+ if (e.preventDefault) {
+ e.preventDefault()
+ }
+ return false
+ },
+ /**
+ * Set the appropriate class on hovering
+ *
+ * @param {Object} e The event object
+ */
+ dragEnter(e) {
+ // Check if dropping here is allowed
+ if (this.calendar.readOnly) {
+ return
+ }
+ // Get the correct element, in case we hover a child.
+ if (e.target.closest) {
+ const target = e.target.closest('li.list')
+ if (target) {
+ const calendars = document.querySelectorAll('li.list')
+ calendars.forEach((f) => { f.classList.remove('dnd-hover') })
+ target.classList.add('dnd-hover')
+ }
+ }
+ },
+ /**
+ * Remove the hovering class after leaving
+ *
+ * @param {Object} e The event object
+ */
+ dragLeave(e) {
+ // Don't do anything if we leave towards a child element.
+ if (e.target.contains(e.relatedTarget)) {
+ return
+ }
+ // Get the correct element, in case we leave directly from a child.
+ if (e.target.closest) {
+ const target = e.target.closest('li.list')
+ if (!target || target.contains(e.relatedTarget)) {
+ return
+ }
+ target.classList.remove('dnd-hover')
+ }
+ },
+ /**
+ * Drop a task on a calendar
+ *
+ * @param {Object} e The event object
+ */
+ dropTask(e) {
+ // Remove all hover classes
+ const calendars = document.querySelectorAll('li.list')
+ calendars.forEach((f) => { f.classList.remove('dnd-hover') })
+ const taskUri = e.dataTransfer.getData('text/plain')
+ if (taskUri) {
+ const task = this.getTask(taskUri)
+ if (this.calendar !== task.calendar) {
+ this.moveTask({ task: task, calendar: this.calendar, parent: undefined })
}
}
},
diff --git a/src/components/TaskBody.vue b/src/components/TaskBody.vue
index 41101ba5..82e03bda 100644
--- a/src/components/TaskBody.vue
+++ b/src/components/TaskBody.vue
@@ -25,7 +25,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
:task-id="task.uri"
:class="{done: task.completed, readOnly: task.calendar.readOnly}"
:data-priority="[task.priority]"
- class="task-item">
+ class="task-item"
+ @dragstart="dragStart($event)">
<div :task-id="task.uri"
:class="{active: isTaskOpen()}"
class="task-body reactive"
@@ -308,6 +309,17 @@ export default {
overdue: overdue,
/**
+ * Set task uri in the data transfer object
+ * so we can get it when dropped on an
+ * app-navigation-item
+ *
+ * @param {Object} e The drag event
+ */
+ dragStart(e) {
+ e.dataTransfer.setData('text/plain', this.task.uri)
+ },
+
+ /**
* Checks if one of the tasks sub(sub-...)tasks matches the search query
*
* @param {Task} task The task to search in
diff --git a/src/components/TaskDragContainer.vue b/src/components/TaskDragContainer.vue
index 56ab0c38..5b15994a 100644
--- a/src/components/TaskDragContainer.vue
+++ b/src/components/TaskDragContainer.vue
@@ -22,6 +22,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
<template>
<draggable tag="ol"
:list="['']"
+ :set-data="setDragData"
v-bind="{group: 'tasks', swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3, disabled: disabled, filter: '.readOnly'}"
@add="onAdd">
<slot />
@@ -56,6 +57,12 @@ export default {
'setDate',
]),
+ setDragData: (dataTransfer) => {
+ // We do nothing here, this just prevents
+ // vue.draggable from setting data on the
+ // dataTransfer object.
+ },
+
/**
* Called when a task is dropped.
*