Move buttons to separate component (#380)

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/380
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
This commit is contained in:
konrad 2021-01-17 17:57:57 +00:00
parent f3e0b79b26
commit 2aceca54ca
61 changed files with 2315 additions and 1825 deletions

View file

@ -2,12 +2,13 @@
<div class="gantt-chart box">
<div class="filter-container">
<div class="items">
<button @click.prevent.stop="showTaskFilter = !showTaskFilter" class="button">
<span class="icon is-small">
<icon icon="filter"/>
</span>
<x-button
@click.prevent.stop="showTaskFilter = !showTaskFilter"
type="secondary"
icon="filter"
>
Filters
</button>
</x-button>
</div>
<filter-popup
@change="loadTasks"
@ -18,21 +19,37 @@
<div class="dates">
<template v-for="(y, yk) in days">
<div :key="yk + 'year'" class="months">
<div :key="mk + 'month'" class="month" v-for="(m, mk) in days[yk]">
{{ new Date((new Date(yk)).setMonth(mk)).toLocaleString('en-us', {month: 'long'}) }},
{{ (new Date(yk)).getFullYear() }}
<div
:key="mk + 'month'"
class="month"
v-for="(m, mk) in days[yk]"
>
{{
new Date(
new Date(yk).setMonth(mk)
).toLocaleString('en-us', {month: 'long'})
}},
{{ new Date(yk).getFullYear() }}
<div class="days">
<div
:class="{'today': d.toDateString() === now.toDateString()}"
:class="{
today:
d.toDateString() === now.toDateString(),
}"
:key="dk + 'day'"
:style="{'width': dayWidth + 'px'}"
:style="{ width: dayWidth + 'px' }"
class="day"
v-for="(d, dk) in days[yk][mk]">
v-for="(d, dk) in days[yk][mk]"
>
<span class="theday" v-if="dayWidth > 25">
{{ d.getDate() }}
</span>
<span class="weekday" v-if="dayWidth > 25">
{{ d.toLocaleString('en-us', {weekday: 'short'}) }}
{{
d.toLocaleString('en-us', {
weekday: 'short',
})
}}
</span>
</div>
</div>
@ -40,19 +57,29 @@
</div>
</template>
</div>
<div :style="{'width': fullWidth + 'px'}" class="tasks">
<div :style="{ width: fullWidth + 'px' }" class="tasks">
<div
:key="t.id"
:style="{background: 'repeating-linear-gradient(90deg, #ededed, #ededed 1px, ' + (k % 2 === 0 ? '#fafafa 1px, #fafafa ' : '#fff 1px, #fff ') + dayWidth + 'px)'}"
:style="{
background:
'repeating-linear-gradient(90deg, #ededed, #ededed 1px, ' +
(k % 2 === 0
? '#fafafa 1px, #fafafa '
: '#fff 1px, #fff ') +
dayWidth +
'px)',
}"
class="row"
v-for="(t, k) in theTasks">
v-for="(t, k) in theTasks"
>
<VueDragResize
:class="{
'done': t.done,
'is-current-edit': taskToEdit !== null && taskToEdit.id === t.id,
'has-light-text': !colorIsDark(t.hexColor),
'has-dark-text': colorIsDark(t.hexColor)
}"
done: t.done,
'is-current-edit':
taskToEdit !== null && taskToEdit.id === t.id,
'has-light-text': !colorIsDark(t.hexColor),
'has-dark-text': colorIsDark(t.hexColor),
}"
:gridX="dayWidth"
:h="31"
:isActive="canWrite"
@ -61,7 +88,10 @@
:parentW="fullWidth"
:snapToGrid="true"
:sticks="['mr', 'ml']"
:style="{'border-color': t.hexColor, 'background-color': t.hexColor}"
:style="{
'border-color': t.hexColor,
'background-color': t.hexColor,
}"
:w="t.durationDays * dayWidth"
:x="t.offsetDays * dayWidth - 6"
:y="0"
@ -71,11 +101,16 @@
axis="x"
class="task"
>
<span :class="{
'has-high-priority': t.priority >= priorities.HIGH,
'has-not-so-high-priority': t.priority === priorities.HIGH,
'has-super-high-priority': t.priority === priorities.DO_NOW
}">{{ t.title }}</span>
<span
:class="{
'has-high-priority': t.priority >= priorities.HIGH,
'has-not-so-high-priority':
t.priority === priorities.HIGH,
'has-super-high-priority':
t.priority === priorities.DO_NOW,
}"
>{{ t.title }}</span
>
<priority-label :priority="t.priority"/>
<!-- using the key here forces vue to use the updated version model and not the response returned by the api -->
<a @click="editTask(theTasks[k])" class="edit-toggle">
@ -86,9 +121,18 @@
<template v-if="showTaskswithoutDates">
<div
:key="t.id"
:style="{background: 'repeating-linear-gradient(90deg, #ededed, #ededed 1px, ' + (k % 2 === 0 ? '#fafafa 1px, #fafafa ' : '#fff 1px, #fff ') + dayWidth + 'px)'}"
:style="{
background:
'repeating-linear-gradient(90deg, #ededed, #ededed 1px, ' +
(k % 2 === 0
? '#fafafa 1px, #fafafa '
: '#fff 1px, #fff ') +
dayWidth +
'px)',
}"
class="row"
v-for="(t, k) in tasksWithoutDates">
v-for="(t, k) in tasksWithoutDates"
>
<VueDragResize
:gridX="dayWidth"
:h="31"
@ -112,7 +156,11 @@
</div>
</template>
</div>
<form @submit.prevent="addNewTask()" class="add-new-task" v-if="canWrite">
<form
@submit.prevent="addNewTask()"
class="add-new-task"
v-if="canWrite"
>
<transition name="width">
<input
@blur="hideCrateNewTask"
@ -124,31 +172,20 @@
v-model="newTaskTitle"
/>
</transition>
<button @click="showCreateNewTask" class="button is-primary has-no-shadow">
<span class="icon is-small">
<icon icon="plus"/>
</span>
<x-button @click="showCreateNewTask" :shadow="false" icon="plus">
Add a new task
</button>
</x-button>
</form>
<transition name="fade">
<div class="card taskedit" v-if="isTaskEdit">
<header class="card-header">
<p class="card-header-title">
Edit Task
</p>
<a @click="() => {isTaskEdit = false; taskToEdit = null}" class="card-header-icon">
<span class="icon">
<icon icon="times"/>
</span>
</a>
</header>
<div class="card-content">
<div class="content">
<edit-task :task="taskToEdit"/>
</div>
</div>
</div>
<card
v-if="isTaskEdit"
class="taskedit"
title="Edit Task"
@close="() => {isTaskEdit = false;taskToEdit = null}"
:has-close="true"
>
<edit-task :task="taskToEdit"/>
</card>
</transition>
</div>
</template>
@ -184,10 +221,10 @@ export default {
default: false,
},
dateFrom: {
default: new Date((new Date()).setDate((new Date()).getDate() - 15)),
default: new Date(new Date().setDate(new Date().getDate() - 15)),
},
dateTo: {
default: new Date((new Date()).setDate((new Date()).getDate() + 30)),
default: new Date(new Date().setDate(new Date().getDate() + 30)),
},
// The width of a day in pixels, used to calculate all sorts of things.
dayWidth: {
@ -226,9 +263,9 @@ export default {
}
},
watch: {
'dateFrom': 'buildTheGanttChart',
'dateTo': 'buildTheGanttChart',
'listId': 'parseTasks',
dateFrom: 'buildTheGanttChart',
dateTo: 'buildTheGanttChart',
listId: 'parseTasks',
},
created() {
this.now = new Date()
@ -240,7 +277,7 @@ export default {
this.buildTheGanttChart()
},
computed: mapState({
canWrite: state => state.currentList.maxRight > Rights.READ,
canWrite: (state) => state.currentList.maxRight > Rights.READ,
}),
methods: {
buildTheGanttChart() {
@ -252,17 +289,26 @@ export default {
this.startDate = new Date(this.dateFrom)
this.endDate = new Date(this.dateTo)
this.dayOffsetUntilToday = Math.floor((this.now - this.startDate) / 1000 / 60 / 60 / 24) + 1
this.dayOffsetUntilToday =
Math.floor((this.now - this.startDate) / 1000 / 60 / 60 / 24) +
1
},
prepareGanttDays() {
// Layout: years => [months => [days]]
let years = {}
for (let d = this.startDate; d <= this.endDate; d.setDate(d.getDate() + 1)) {
for (
let d = this.startDate;
d <= this.endDate;
d.setDate(d.getDate() + 1)
) {
let date = new Date(d)
if (years[date.getFullYear() + ''] === undefined) {
years[date.getFullYear() + ''] = {}
}
if (years[date.getFullYear() + ''][date.getMonth() + ''] === undefined) {
if (
years[date.getFullYear() + ''][date.getMonth() + ''] ===
undefined
) {
years[date.getFullYear() + ''][date.getMonth() + ''] = []
}
years[date.getFullYear() + ''][date.getMonth() + ''].push(date)
@ -279,79 +325,86 @@ export default {
this.$set(this, 'tasksWithoutDates', [])
const getAllTasks = (page = 1) => {
return this.taskCollectionService.getAll({listId: this.listId}, this.params, page)
.then(tasks => {
return this.taskCollectionService
.getAll({listId: this.listId}, this.params, page)
.then((tasks) => {
if (page < this.taskCollectionService.totalPages) {
return getAllTasks(page + 1)
.then(nextTasks => {
return tasks.concat(nextTasks)
})
return getAllTasks(page + 1).then((nextTasks) => {
return tasks.concat(nextTasks)
})
} else {
return tasks
}
})
.catch(e => {
.catch((e) => {
return Promise.reject(e)
})
}
getAllTasks()
.then(tasks => {
.then((tasks) => {
this.theTasks = tasks
.filter(t => {
.filter((t) => {
if (t.startDate === null && !t.done) {
this.tasksWithoutDates.push(t)
}
return t.startDate >= this.startDate && t.endDate <= this.endDate
return (
t.startDate >= this.startDate &&
t.endDate <= this.endDate
)
})
.map(t => {
.map((t) => {
return this.addGantAttributes(t)
})
.sort(function (a, b) {
if (a.startDate < b.startDate)
return -1
if (a.startDate > b.startDate)
return 1
if (a.startDate < b.startDate) return -1
if (a.startDate > b.startDate) return 1
return 0
})
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
},
addGantAttributes(t) {
t.endDate === null ? this.endDate : t.endDate
t.durationDays = Math.floor((t.endDate - t.startDate) / 1000 / 60 / 60 / 24) + 1
t.offsetDays = Math.floor((t.startDate - this.startDate) / 1000 / 60 / 60 / 24) + 1
t.durationDays =
Math.floor((t.endDate - t.startDate) / 1000 / 60 / 60 / 24) + 1
t.offsetDays =
Math.floor(
(t.startDate - this.startDate) / 1000 / 60 / 60 / 24
) + 1
return t
},
setTaskDragged(t) {
this.taskDragged = t
},
resizeTask(newRect) {
// Timeout to definitly catch if the user clicked on taskedit
setTimeout(() => {
if (this.isTaskEdit) {
return
}
let didntHaveDates = this.taskDragged.startDate === null ? true : false
let didntHaveDates =
this.taskDragged.startDate === null ? true : false
let startDate = new Date(this.startDate)
startDate.setDate(startDate.getDate() + newRect.left / this.dayWidth)
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)
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.
@ -362,8 +415,9 @@ export default {
}
}
this.taskService.update(this.taskDragged)
.then(r => {
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) {
@ -376,13 +430,17 @@ export default {
} else {
for (const tt in this.theTasks) {
if (this.theTasks[tt].id === r.id) {
this.$set(this.theTasks, tt, this.addGantAttributes(r))
this.$set(
this.theTasks,
tt,
this.addGantAttributes(r)
)
break
}
}
}
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
}, 100)
@ -402,21 +460,25 @@ export default {
},
hideCrateNewTask() {
if (this.newTaskTitle === '') {
this.$nextTick(() => this.newTaskFieldActive = false)
this.$nextTick(() => (this.newTaskFieldActive = false))
}
},
addNewTask() {
if (!this.newTaskFieldActive) {
return
}
let task = new TaskModel({title: this.newTaskTitle, listId: this.listId})
this.taskService.create(task)
.then(r => {
let task = new TaskModel({
title: this.newTaskTitle,
listId: this.listId,
})
this.taskService
.create(task)
.then((r) => {
this.tasksWithoutDates.push(this.addGantAttributes(r))
this.newTaskTitle = ''
this.hideCrateNewTask()
})
.catch(e => {
.catch((e) => {
this.error(e, this)
})
},