The issue at hand
I have been working on developing an Open-Source Vue Application that features a Gantt Chart for visualizing tasks along a timeline. Users are able to customize the date range, with the default setting to display the current and upcoming month.
However, every September, there seems to be a recurring problem with the chart malfunctioning. Instead of displaying all months as intended, it skips the next month:
https://i.sstatic.net/xiCyS.png
This is how the correct output should look: https://i.sstatic.net/9uOEM.png
An ongoing discussion regarding this issue can be found here.
The challenge
Despite my best efforts, I have been unable to replicate this error. Even after utilizing Browserstack to mimic the exact browser and operating system configurations used by my users, the chart functions perfectly across all devices and browsers I've tested. The inability to reproduce the issue has hindered my ability to debug and resolve it.
This suggests that the problem may only impact specific users and not a significant portion of them.
The code snippet
The following code pertains to the creation of the data structure encompassing years, months, and days:
// Layout: years => [months => [days]]
let years = {}
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
) {
years[date.getFullYear() + ''][date.getMonth() + ''] = []
}
years[date.getFullYear() + ''][date.getMonth() + ''].push(date)
this.fullWidth += this.dayWidth
}
this.$set(this, 'days', years) // I know, that variable name doesn't make any sense
This data is then presented to the user in the following manner:
<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 class="days">
<div
:class="{ today: d.toDateString() === now.toDateString() }"
:key="dk + 'day'"
:style="{ width: dayWidth + 'px' }"
class="day"
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'}) }}
</span>
</div>
</div>
</div>
</div>
</template>
You can access the complete component code here.