diff --git a/package.json b/package.json index a1a7ba0a6..095ca49ed 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "vue-i18n": "8.25.0", "vue-shortkey": "3.1.7", "vue-smooth-dnd": "0.8.1", + "vuedraggable": "^2.24.3", "vuex": "3.6.2", "workbox-precaching": "6.1.5" }, diff --git a/src/components/tasks/add-task.vue b/src/components/tasks/add-task.vue index 64f71c91f..d92854628 100644 --- a/src/components/tasks/add-task.vue +++ b/src/components/tasks/add-task.vue @@ -66,6 +66,12 @@ export default { this.labelService = new LabelService() this.labelTaskService = new LabelTaskService() }, + props: { + defaultPosition: { + type: Number, + required: false, + }, + }, methods: { addTask() { if (this.newTaskTitle === '') { @@ -74,7 +80,7 @@ export default { } this.errorMessage = '' - this.createNewTask(this.newTaskTitle, 0, this.$store.state.auth.settings.defaultListId) + this.createNewTask(this.newTaskTitle, 0, this.$store.state.auth.settings.defaultListId, this.defaultPosition) .then(task => { this.newTaskTitle = '' this.$emit('taskAdded', task) diff --git a/src/components/tasks/mixins/createTask.js b/src/components/tasks/mixins/createTask.js index 989636a6e..968516666 100644 --- a/src/components/tasks/mixins/createTask.js +++ b/src/components/tasks/mixins/createTask.js @@ -22,7 +22,7 @@ export default { labels: state => state.labels.labels, }), methods: { - createNewTask(newTaskTitle, bucketId = 0, lId = 0) { + createNewTask(newTaskTitle, bucketId = 0, lId = 0, position = 0) { const parsedTask = parseTaskText(newTaskTitle) const assignees = [] @@ -57,6 +57,7 @@ export default { priority: parsedTask.priority, assignees: assignees, bucketId: bucketId, + position: position, }) return this.taskService.create(task) .then(task => { diff --git a/src/components/tasks/mixins/taskList.js b/src/components/tasks/mixins/taskList.js index 2a2576915..64c425b66 100644 --- a/src/components/tasks/mixins/taskList.js +++ b/src/components/tasks/mixins/taskList.js @@ -1,5 +1,6 @@ import TaskCollectionService from '../../../services/taskCollection' import cloneDeep from 'lodash/cloneDeep' +import {calculateTaskPosition} from '../../../helpers/calculateTaskPosition' /** * This mixin provides a base set of methods and properties to get tasks on a list. @@ -20,7 +21,7 @@ export default { showTaskFilter: false, params: { - sort_by: ['done', 'id'], + sort_by: ['position', 'id'], order_by: ['asc', 'desc'], filter_by: ['done'], filter_value: ['false'], @@ -187,5 +188,23 @@ export default { }, } }, + saveTaskPosition(e) { + console.log(e.oldIndex, e.newIndex) + console.log('elem', this.tasks[e.newIndex].title) + + const task = this.tasks[e.newIndex] + const taskBefore = this.tasks[e.newIndex - 1] ?? null + const taskAfter = this.tasks[e.newIndex + 1] ?? null + + task.position = calculateTaskPosition(taskBefore !== null ? taskBefore.position : null, taskAfter !== null ? taskAfter.position : null) + + this.$store.dispatch('tasks/update', task) + .then(r => { + this.$set(this.tasks, e.newIndex, r) + }) + .catch(e => { + this.error(e) + }) + }, }, } \ No newline at end of file diff --git a/src/views/list/views/List.vue b/src/views/list/views/List.vue index 722c67041..47d75b7e4 100644 --- a/src/views/list/views/List.vue +++ b/src/views/list/views/List.vue @@ -21,7 +21,7 @@ v-model="searchTerm" /> - +
@@ -63,16 +63,15 @@ - {{ $t('list.list.empty') }} {{ $t('list.list.newTaskCta') }} -
@@ -81,23 +80,25 @@ class="tasks mt-0" v-if="tasks && tasks.length > 0" > - -
+ - -
-
+
+ +
+ +
- +
@@ -163,14 +164,17 @@ import EditTask from '../../../components/tasks/edit-task' import AddTask from '../../../components/tasks/add-task' import SingleTaskInList from '../../../components/tasks/partials/singleTaskInList' import taskList from '../../../components/tasks/mixins/taskList' -import { saveListView } from '@/helpers/saveListView' +import {saveListView} from '@/helpers/saveListView' import Rights from '../../../models/rights.json' -import { mapState } from 'vuex' import FilterPopup from '@/components/list/partials/filter-popup.vue' -import { HAS_TASKS } from '@/store/mutation-types' +import {HAS_TASKS} from '@/store/mutation-types' import Nothing from '@/components/misc/nothing.vue' import createTask from '@/components/tasks/mixins/createTask' +import {mapState} from 'vuex' +import draggable from 'vuedraggable' +import {calculateTaskPosition} from '../../../helpers/calculateTaskPosition' + export default { name: 'List', data() { @@ -191,6 +195,7 @@ export default { SingleTaskInList, EditTask, AddTask, + draggable, }, created() { this.taskService = new TaskService() @@ -199,10 +204,21 @@ export default { // We use local storage and not vuex here to make it persistent across reloads. saveListView(this.$route.params.listId, this.$route.name) }, - computed: mapState({ - canWrite: state => state.currentList.maxRight > Rights.READ, - list: state => state.currentList, - }), + computed: { + firstNewPosition() { + if (this.tasks.length === 0) { + return 0 + } + + const p = calculateTaskPosition(null, this.tasks[0].position) + console.log('newp', p) + return p + }, + ...mapState({ + canWrite: state => state.currentList.maxRight > Rights.READ, + list: state => state.currentList, + }), + }, mounted() { this.$nextTick(() => (this.ctaVisible = true)) }, diff --git a/yarn.lock b/yarn.lock index e790f84e6..88f4d02cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7245,6 +7245,11 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +sortablejs@1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.10.2.tgz#6e40364d913f98b85a14f6678f92b5c1221f5290" + integrity sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A== + source-map-js@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" @@ -8169,6 +8174,13 @@ vue@2.6.14: resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235" integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ== +vuedraggable@^2.24.3: + version "2.24.3" + resolved "https://registry.yarnpkg.com/vuedraggable/-/vuedraggable-2.24.3.tgz#43c93849b746a24ce503e123d5b259c701ba0d19" + integrity sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g== + dependencies: + sortablejs "1.10.2" + vuex@3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"