Fix tasks moving infinitely in gantt chart (#493)

Fixes vikunja/frontend#489

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#493
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
This commit is contained in:
konrad 2021-04-25 16:01:17 +00:00
parent 4d998d891e
commit 85e55d1300
4 changed files with 76 additions and 72 deletions

View File

@ -85,7 +85,7 @@ export default {
if (typeof this.$route.query.code !== 'undefined' || location.hash.startsWith('#token=')) { if (typeof this.$route.query.code !== 'undefined' || location.hash.startsWith('#token=')) {
if (location.hash.startsWith('#token=')) { if (location.hash.startsWith('#token=')) {
this.migratorAuthCode = location.hash.substring(7) this.migratorAuthCode = location.hash.substring(7)
console.log(location.hash.substring(7)) console.debug(location.hash.substring(7))
} else { } else {
this.migratorAuthCode = this.$route.query.code this.migratorAuthCode = this.$route.query.code
} }

View File

@ -59,7 +59,8 @@
</div> </div>
<div :style="{ width: fullWidth + 'px' }" class="tasks"> <div :style="{ width: fullWidth + 'px' }" class="tasks">
<div <div
:key="t.id" v-for="(t, k) in theTasks"
:key="t ? t.id : 0"
:style="{ :style="{
background: background:
'repeating-linear-gradient(90deg, #ededed, #ededed 1px, ' + 'repeating-linear-gradient(90deg, #ededed, #ededed 1px, ' +
@ -70,13 +71,11 @@
'px)', 'px)',
}" }"
class="row" class="row"
v-for="(t, k) in theTasks"
> >
<VueDragResize <VueDragResize
:class="{ :class="{
done: t.done, done: t ? t.done : false,
'is-current-edit': 'is-current-edit': taskToEdit !== null && taskToEdit.id === t.id,
taskToEdit !== null && taskToEdit.id === t.id,
'has-light-text': !colorIsDark(t.getHexColor()), 'has-light-text': !colorIsDark(t.getHexColor()),
'has-dark-text': colorIsDark(t.getHexColor()), 'has-dark-text': colorIsDark(t.getHexColor()),
}" }"
@ -367,83 +366,89 @@ export default {
}) })
}, },
addGantAttributes(t) { addGantAttributes(t) {
if (typeof t.durationDays !== 'undefined' && typeof t.offsetDays !== 'undefined') {
return t
}
t.endDate === null ? this.endDate : t.endDate t.endDate === null ? this.endDate : t.endDate
t.durationDays = t.durationDays = Math.floor((t.endDate - t.startDate) / 1000 / 60 / 60 / 24)
Math.floor((t.endDate - t.startDate) / 1000 / 60 / 60 / 24) + 1 t.offsetDays = Math.floor((t.startDate - this.startDate) / 1000 / 60 / 60 / 24)
t.offsetDays =
Math.floor(
(t.startDate - this.startDate) / 1000 / 60 / 60 / 24
) + 1
return t return t
}, },
setTaskDragged(t) { setTaskDragged(t) {
this.taskDragged = t this.taskDragged = t
}, },
resizeTask(newRect) { resizeTask(newRect) {
// Timeout to definitly catch if the user clicked on taskedit if (this.isTaskEdit) {
setTimeout(() => { return
if (this.isTaskEdit) { }
return
const didntHaveDates = this.taskDragged.startDate === null ? true : false
let startDate = new Date(this.startDate)
startDate.setDate(
startDate.getDate() + newRect.left / this.dayWidth
)
startDate.setUTCHours(0)
startDate.setUTCMinutes(0)
startDate.setUTCSeconds(0)
startDate.setUTCMilliseconds(0)
this.taskDragged.startDate = startDate
let endDate = new Date(startDate)
endDate.setDate(
startDate.getDate() + newRect.width / this.dayWidth
)
this.taskDragged.startDate = startDate
this.taskDragged.endDate = endDate
// We take the task from the overall tasks array because the one in it has bad data after it was updated once.
// FIXME: This is a workaround. We should use a better mechanism to get the task or, even better,
// prevent it from containing outdated Data in the first place.
for (const tt in this.theTasks) {
if (this.theTasks[tt].id === this.taskDragged.id) {
this.$set(this, 'taskDragged', this.theTasks[tt])
break
} }
}
let didntHaveDates = const ganttData = {
this.taskDragged.startDate === null ? true : false endDate: this.taskDragged.endDate,
durationDays: this.taskDragged.durationDays,
offsetDays: this.taskDragged.offsetDays,
}
let startDate = new Date(this.startDate) this.taskService
startDate.setDate( .update(this.taskDragged)
startDate.getDate() + newRect.left / this.dayWidth .then(r => {
) r.endDate = ganttData.endDate
startDate.setUTCHours(0) r.durationDays = ganttData.durationDays
startDate.setUTCMinutes(0) r.offsetDays = ganttData.offsetDays
startDate.setUTCSeconds(0)
startDate.setUTCMilliseconds(0)
this.taskDragged.startDate = startDate
let endDate = new Date(startDate)
endDate.setDate(
startDate.getDate() + newRect.width / this.dayWidth
)
this.taskDragged.startDate = startDate
this.taskDragged.endDate = endDate
// We take the task from the overall tasks array because the one in it has bad data after it was updated once. // If the task didn't have dates before, we'll update the list
// FIXME: This is a workaround. We should use a better mechanism to get the task or, even better, if (didntHaveDates) {
// prevent it from containing outdated Data in the first place. for (const t in this.tasksWithoutDates) {
for (const tt in this.theTasks) { if (this.tasksWithoutDates[t].id === r.id) {
if (this.theTasks[tt].id === this.taskDragged.id) { this.tasksWithoutDates.splice(t, 1)
this.$set(this, 'taskDragged', this.theTasks[tt]) break
break
}
}
this.taskService
.update(this.taskDragged)
.then((r) => {
// If the task didn't have dates before, we'll update the list
if (didntHaveDates) {
for (const t in this.tasksWithoutDates) {
if (this.tasksWithoutDates[t].id === r.id) {
this.tasksWithoutDates.splice(t, 1)
break
}
}
this.theTasks.push(this.addGantAttributes(r))
} else {
for (const tt in this.theTasks) {
if (this.theTasks[tt].id === r.id) {
this.$set(
this.theTasks,
tt,
this.addGantAttributes(r)
)
break
}
} }
} }
}) this.theTasks.push(this.addGantAttributes(r))
.catch((e) => { } else {
this.error(e, this) for (const tt in this.theTasks) {
}) if (this.theTasks[tt].id === r.id) {
}, 100) this.$set(
this.theTasks,
tt,
this.addGantAttributes(r)
)
break
}
}
}
})
.catch((e) => {
this.error(e, this)
})
}, },
editTask(task) { editTask(task) {
this.taskToEdit = task this.taskToEdit = task

View File

@ -72,6 +72,7 @@ $gantt-vertical-border-color: $grey-100;
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
cursor: grab; cursor: grab;
position: relative; position: relative;
height: 31px !important;
-webkit-touch-callout: none; // iOS Safari -webkit-touch-callout: none; // iOS Safari
-webkit-user-select: none; // Safari -webkit-user-select: none; // Safari

View File

@ -505,8 +505,6 @@ export default {
this.listViewName = `list.${parts[1]}` this.listViewName = `list.${parts[1]}`
} }
console.log(this.task)
this.loadTask() this.loadTask()
}, },
computed: { computed: {