feat: replace our home-grown gantt implementation with ganttastic #2180

Merged
konrad merged 78 commits from feature/ganttastic into main 2022-10-27 16:03:27 +00:00
3 changed files with 121 additions and 2 deletions
Showing only changes of commit 2b0df8c237 - Show all commits

View File

@ -23,6 +23,7 @@
"@fortawesome/free-solid-svg-icons": "6.2.0",
"@fortawesome/vue-fontawesome": "3.0.1",
"@github/hotkey": "2.0.1",
"@infectoone/vue-ganttastic": "^2.0.4",
"@kyvg/vue3-notification": "2.4.1",
"@sentry/tracing": "7.17.0",
"@sentry/vue": "7.17.0",

View File

@ -0,0 +1,118 @@
<template>
<g-gantt-chart
konrad marked this conversation as resolved Outdated

Use loading component. This way it's easier for us to refactor the is-loading styles from bulma later.

Use loading component. This way it's easier for us to refactor the `is-loading` styles from bulma later.

Done.

Done.
:chart-start="dateFromFormatted"
:chart-end="dateToFormatted"
precision="day"
bar-start="startDate"
bar-end="endDate"
:grid="true"
@dragend-bar="updateTask"
>
<g-gantt-row
v-for="bar in ganttBars"
konrad marked this conversation as resolved Outdated

Is it possible to use here simply inherit as value?

Is it possible to use here simply `inherit` as value?

Seems to work, yes.

Seems to work, yes.

Not necessary with lates release. Removed.

Not necessary with lates release. Removed.
label=""
:bars="bar"
/>
</g-gantt-chart>
</template>
<script setup lang="ts">
import {computed, ref} from 'vue'
import TaskCollectionService from '@/services/taskCollection'
import {format} from 'date-fns'
import {colorIsDark} from '@/helpers/color/colorIsDark'
import TaskService from '@/services/task'
const dateFormat = 'yyyy-LL-dd kk:mm'
const props = defineProps({
listId: {
type: Number,
required: true,
},
dateFrom: {
default: () => new Date(new Date().setDate(new Date().getDate() - 15)),
},
dateTo: {
default: () => new Date(new Date().setDate(new Date().getDate() + 30)),
},
})
const dateFromFormatted = computed(() => format(props.dateFrom, dateFormat))
const dateToFormatted = computed(() => format(props.dateTo, dateFormat))
const tasks = ref([])
const ganttBars = ref([])
// We need a "real" ref object for the gantt bars to instantly update the tasks when they are dragged on the chart.
// A computed won't work directly.
function mapGanttBars() {
const defaultStartDate = '2022-07-19 12:00'
const defaultEndDate = '2022-07-25 12:00'
tasks.value.forEach(t => ganttBars.value.push([{
startDate: t.startDate ? format(t.startDate, dateFormat) : defaultStartDate,
endDate: t.endDate ? format(t.endDate, dateFormat) : defaultEndDate,
ganttBarConfig: {
id: t.id,
label: t.title,
hasHandles: true,
style: {
color: colorIsDark(t.getHexColor()) ? 'black' : 'white',
konrad marked this conversation as resolved Outdated

Picky: Use @/models...

Picky: Use `@/models...`

Done.

Done.
backgroundColor: t.getHexColor(),
},
},
}]))
konrad marked this conversation as resolved Outdated

picky: use DATE_FORMAT to make clear it's a 'config const'

picky: use `DATE_FORMAT` to make clear it's a 'config const'

But also: shouldn't this depend on the user setting / language?

But also: shouldn't this depend on the user setting / language?

shouldn't this depend on the user setting / language?

It's only used to pass the date in the correct format to the gantt chart libaray so it will always be the same. Not sure why they only take strings as input instead of Date objects but that's how it is.

> shouldn't this depend on the user setting / language? It's only used to pass the date in the correct format to the gantt chart libaray so it will always be the same. Not sure why they only take strings as input instead of `Date` objects but that's how it is.
}
async function loadTasks() {
tasks.value = new Map()
const params = {
sort_by: ['start_date', 'done', 'id'],
order_by: ['asc', 'asc', 'desc'],
filter_by: ['done'], // TODO: only load tasks in the current date range
filter_comparator: ['equals'],
filter_value: ['false'],
filter_concat: 'and',
}
const taskCollectionService = new TaskCollectionService()
const getAllTasks = async (page = 1) => {
const tasks = await taskCollectionService.getAll({listId: props.listId}, params, page)
if (page < taskCollectionService.totalPages) {
const nextTasks = await getAllTasks(page + 1)
return tasks.concat(nextTasks)
}
return tasks
}
konrad marked this conversation as resolved Outdated

picky: If you use a default value there is no need to define required

picky: If you use a default value there is no need to define `required`

Done.

Done.
const loadedTasks = await getAllTasks()
loadedTasks
.forEach(t => {
tasks.value.set(t.id, t)
})
mapGanttBars()
}
loadTasks()
async function updateTask(e) {
const task = tasks.value.get(e.bar.ganttBarConfig.id)
task.startDate = e.bar.startDate
task.endDate = e.bar.endDate
dpschen marked this conversation as resolved Outdated

User TaskModel['id']

User `TaskModel['id']`

Done (I think you did that one?)

Done (I think you did that one?)
const taskService = new TaskService()
await taskService.update(task)
// TODO: Loading animation
konrad marked this conversation as resolved Outdated

define types

define types

Done.

Done.
}
</script>
<style>
.g-gantt-row-label {
display: none !important;
}
</style>

View File

@ -49,7 +49,7 @@
<template #default>
<div class="gantt-chart-container">
<card :padding="false" class="has-overflow">
<gantt-chart
:date-from="dateFrom"
:date-to="dateTo"
@ -72,7 +72,7 @@ import {useI18n} from 'vue-i18n'
import {useAuthStore} from '@/stores/auth'
import ListWrapper from './ListWrapper.vue'
import GanttChart from '@/components/tasks/gantt-component.vue'
import GanttChart from '@/components/tasks/gantt-chart.vue'
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
const props = defineProps({
konrad marked this conversation as resolved Outdated

Should this update?

Should this update?

No, doesn't even need to be ref.

No, doesn't even need to be ref.