'Svelte Gantt Chart - Separate via months

I'm trying to have a gantt chart with all 12 months in it. I'm doing this by setting the from & to values to currentDate.clone().endOf('year') & currentDate.clone().endOf('year'). But the gantt chart stopping appearing when setting these values, if I print out the dates they are valid & weirdly if I change the values to startOf('week') & endOf('week)` it renders the chart fine. Is this possible to do?

Package I'm using: https://github.com/ANovokmet/svelte-gantt

Edit: My code is based on this index.js file: https://github.com/ANovokmet/svelte-gantt/blob/gh-pages/index.js

It might be simpler to ask, how can I modify it to show months instead of hours/days?

function time(input) {
  return moment(input, "MMMM DD YYYY");
}

const currentStart = time(responseData.currentDate);
const currentEnd = time(responseData.currentDate);

gantt.$set({
   fitWidth: false,
   columnUnit: 'month',
   rowPadding: 6,
   rowHeight: 52,
   columnOffset: 28.8,
   magnetOffset: 15,
   from: currentStart.clone().startOf('year'),
   to: currentStart.clone().endOf('year'),
   minWidth: 800,
   headers: [{ unit: 'month', format: 'MMMM YYYY' }, { unit: 'day', format: 'ddd DD' }]
});


Solution 1:[1]

TL;DR: Svelte Gantt Year + Months example

(note: svelte-gantt behavior is a bit finicky in the REPL, you might have to resize the width of the render panel to display the default 10 rows/tasks).

Important Update

I have noticed that there is an issue in the months' column headers, with January and May being repeated, February being skipped, and ultimately a one-month offset from May onwards (causing December to disappear as well). This is because of the way svelte-gantt handles month duration internally: all months are set to 30 days (!!). You can see this in this source file at line 118. The author even commented that this was incorrect...

Knowing this, you might want to reconsider using this module for an accurate representation of a yearly/monthly Gantt diagram, unless you fork the project and implement a correct handling of variable month durations yourself!

How I got there

I used the svelte-gantt large dataset demo source as a starting point, removing the GanttOptions import and component (irrelevant for this question). What I was left with was a Gantt diagram for a single day, hourly columns, and 100 generated rows & tasks (which I shortened to 10). The key info there was obviously the options object passed to the SvelteGantt constructor as props:

let options = {
    dateAdapter: new MomentSvelteGanttDateAdapter(moment),
    rows: data.rows,
    tasks: data.tasks,
    timeRanges,
    columnOffset: 15,
    magnetOffset: 15,
    rowHeight: 52,
    rowPadding: 6,
    headers: [{ unit: 'day', format: 'MMMM Do' }, { unit: 'hour', format: 'H:mm' }],
    fitWidth: true,
    minWidth: 800,
    from: currentStart,
    to: currentEnd,
    tableHeaders: [{ title: 'Label', property: 'label', width: 140, type: 'tree' }],
    tableWidth: 240,
    ganttTableModules: [SvelteGanttTable]
}

The changes needed to get from a single day diagram with hourly columns to a single year diagram with monthly columns were quite straightforward.

I removed the timeRanges option (which was used to set lunch & dinner time ranges in the daily diagram but were no longer useful in the yearly diagram - although you might want to use them again for bank holidays, or summer vacation periods for instance), and the associated data.

Then I added the columnUnit option, setting it to 'month', and changed the columnOffset option, setting it to 1, in order to have 1 column per month.

Finally I adjusted the headers option to display the year in the top line, and the abbreviated months in the second line (column headers): headers: [{ unit: 'year', format: 'YYYY' }, { unit: 'month', format: 'MMM' }].

The final, modified options object:

let options = {
    dateAdapter: new MomentSvelteGanttDateAdapter(moment),
    rows: data.rows,
    tasks: data.tasks,
    columnUnit: 'month',
    columnOffset: 1,
    magnetOffset: 15,
    rowHeight: 52,
    rowPadding: 6,
    headers: [{ unit: 'year', format: 'YYYY' }, { unit: 'month', format: 'MMM' }],
    fitWidth: true,
    minWidth: 800,
    from: currentStart,
    to: currentEnd,
    tableHeaders: [{ title: 'Label', property: 'label', width: 140, type: 'tree' }],
    tableWidth: 240,
    ganttTableModules: [SvelteGanttTable]
}

I then modified the currentStart and currentEnd values to reflect the new range of the diagram (a full year) by setting them to the beginning and the end of the current year, repectively:

const currentStart = moment().clone().startOf('year');
const currentEnd = moment().clone().endOf('year');

Finally, I had to modify the task generation process in order to randomly generate tasks that were meaningful enough for the new scale/range of the diagram:

// start of task (random day (1-20) + month (1-12))
const rand_d = (Math.random() * 20) | 0 + 1
const rand_m = (Math.random() * 12) | 0 + 1
const from = moment(`${rand_d} ${rand_m}`, 'D M')
// duration of task (random, 5 to 60 days)
const rand_l = (Math.random() * 55) | 0 + 5
const to = from.clone().add(rand_l, 'days')
tasks.push({
    type: 'task',
    id: ids[i],
    resourceId: i,
    label: 'Task #' + ids[i],
    from,
    to,
    classes: colors[(Math.random() * colors.length) | 0],
    generation
});

As a final cleanup, since by now I was no longer using the time() utility function, relying entirely on moment instead, I also removed the import { time } from '../utils'; statement.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1