v7.3.0
SupportExamplesFree Trial

What's new in Gantt v6.0.0+

Gantt v6.0.0

Calendar editor widget

The release introduces the calendar editor - a special widget visualizing and allowing to edit a calendar's data. Click Edit project calendar button to see the widget in action:

const gantt = new Gantt({ appendTo : targetElement, flex : '1 0 100%', // Project contains all the data and is responsible for correct scheduling project : { calendar : 1, calendars : [{ id : 1, name : 'Project Calendar', unspecifiedTimeIsWorking : true, intervals : [ { recurrentStartDate : 'on Sat', recurrentEndDate : 'on Mon', isWorking : false }, { name : 'Day-off', startDate : '2023-12-13', endDate : '2023-12-14', isWorking : false } ] }], tasks : [{ id : 1, name : 'Write docs', expanded : true, children : [ { id : 2, name : 'Proof-read docs', startDate : '2023-12-12', duration : 3 }, { id : 3, name : 'Release docs', startDate : '2023-12-19', duration : 5 } ] }], resources : [ { id : 1, name : 'Albert' }, { id : 2, name : 'Bill' } ], assignments : [ { event : 2, resource : 1 }, { event : 3, resource : 2 } ] }, startDate : new Date(2023, 11, 11), endDate : new Date(2023, 11, 31), height : 250, tbar : [{ type : 'button', icon : 'fa fa-calendar', text : 'Edit Project Calendar', async onAction() { // wait till project finished its calculations await gantt.project.commitAsync(); // gantt might be destroyed during the commit if (gantt.isDestroyed) { return; } let editor = this.calendarEditor; // create calendar editor if (!editor) { this.calendarEditor = editor = new CalendarEditor({ owner : gantt, // don't show it right away autoShow : false, modal : true }); } // edit project calendar editor.calendar = gantt.project.calendar; editor.activeDate = gantt.visibleDateRange.startDate; editor.show(); } }], columns : [ { field : 'name', text : 'Name' } ] });

The widget used is a CalendarEditor. It extends the standard Popup, any corresponding configs works for it too:

const editor = new CalendarEditor({
    // display the editor right now
    autoShow  : true,
    calendar  : calendarToEdit,
    // use it as a modal dialog
    modal     : true,
    // clicking outside the editor closes it
    autoClose : true
});

And additionally the class has some extra APIs specific to its purposes:

  • calendar - a config to load a calendar for editing.
  • activeDate - a date to display on the widget's "General" tab date picker.

For more details please check the API docs and this new guide.

CalendarField support for the calendar editor

CalendarField has been changed to support the new calendar editor. The field has a new trigger to open the editor for the selected calendar.

const project = new ProjectModel({ startDate : '2020-01-02', events : [ { id : 1, name : 'Write docs', startDate : '2020-01-02', endDate : '2020-01-05' } ], calendars : [ { id : 'general', name : '24 hour calendar', intervals : [ { recurrentStartDate : 'on Sat', recurrentEndDate : 'on Mon', isWorking : false } ], expanded : true, children : [ { id : 'business', name : 'Business hours (8am - 5pm)', intervals : [ { recurrentStartDate : 'every weekday at 12:00', recurrentEndDate : 'every weekday at 13:00', isWorking : false }, { recurrentStartDate : 'every weekday at 17:00', recurrentEndDate : 'every weekday at 08:00', isWorking : false } ] }, { id : 'nightshift', name : 'Night shift (10pm - 6am)', intervals : [ { recurrentStartDate : 'every weekday at 6:00', recurrentEndDate : 'every weekday at 22:00', isWorking : false } ] } ] } ] }); const eventRecord = project.eventStore.getById(1); const calendarField = new CalendarField({ appendTo : targetElement, width : 250, store : project.calendarManagerStore, // edit "Write docs" event calendar value : eventRecord.calendar, calendarConsumerRecord : eventRecord });

There is a new calendarConsumerRecord config on the field that must be provided to use the calendar editor. The config should be set to the record "owning" the edited calendar. So it could be either a resource, a task or a project:

new CalendarField({
    value                  : task1.calendar,
    calendarConsumerRecord : task1
})

The field has got a new calendarEditor config to customize the calendar editor widget:

new CalendarField({
    value                  : task1.calendar,
    calendarConsumerRecord : task1,
    calendarEditor         : {
        // display editor centered
        centered : true
    }
})

The config can also be set to false to opt out both the new editor and its trigger displaying:

new CalendarField({
    value          : task1.calendar,
    // disable new calendar editor
    calendarEditor : false
})

Please check the new behavior in the "advanced" demo where the field allows editing the project calendar.

Project statusDate field

We've added a new field for the ProjectModel - statusDate.

This date is used as a reference point for various reports and data calculations. For example, the ProgressLine feature will use this field, if it's not provided for the feature explicitly. In the same way, the PlannedPercentDoneColumn will also refer to it.

Planned percent done column

In this release we introduce a PlannedPercentDoneColumn column, which shows the "planned percent done" values.

To calculate it, task needs to have at least 1 baseline set and the reference "status" date should be provided either to the column, or to the project.

The calculation is performed with the getPlannedPercentDone method of TaskModel, as follows:

  • If the baseline's end date is before the status date, result value is 100%
  • If the baseline's start date is after the status date, result value is 0%
  • Now the status date is in between the baseline's start and end date, result value is: (status date - baseline start date) / (baseline end date - baseline start date). Here the "minus" operation effectively calculates the duration between the two moments on timeaxis. Duration calculation takes into account the task's calendar.

See the new Planned percent done demo for a showcase.

Gantt v6.0.2

Started tasks scheduling

This release introduces a new config affecting started tasks (tasks having percentDone value greater than zero) scheduling. Such tasks can now be treated as manually scheduled to preserve their dates. The rationale behind this is starting a task implies its start date gets established and thus should not be calculated dynamically.

The behavior is controlled by new startedTaskScheduling project field supporting two values:

  • Manual - enables this new behavior when started tasks preserve their current positions
  • Auto - (default) old behavior when tasks are scheduled regardless of whether they are started or not

So to switch to the new behavior please provide Manual to the project field:

new ProjectModel({
    startedTaskScheduling : 'Manual',
    ...
})

Or one can simply include the field value in a dataset:

{
    "project" : {
        "startedTaskScheduling" : "Manual",
        ...
    },

    "tasks" : {
        "rows: [ ... ]
    },

    ...
}

ResourceHistogram and ResourceUtilization views API changes

ResourceHistogram and ResourceUtilization views have got two new hooks providing better control over the rendered DOM elements.

The first hook is getBarDOMConfig. It's a function which is meant to return a bar DOM configuration object - the object that configures the bar RECT element.

new ResourceHistogram({
    // Let's add left & right margins to bars
    getBarDOMConfig(series, domConfig) {
        // margin size is 10% of the bar width
        const xMargin = 0.1 * domConfig.width;
        // adjust the bar x-coordinate
        domConfig.x += xMargin;
        // reduce the bar width respectively
        domConfig.width -= 2 * xMargin;
        // return the edited domConfig
        return domConfig;
    },
    ...
})

Another one is getBarTextDOMConfig - a function which is meant to return a DOM configuration object for text elements:

new ResourceHistogram({
    getBarTextDOMConfig(domConfig, datum, index) {
        // Place text at the top of the "effort" bar
        // so calculate y-position in percents
        domConfig.y = `${100 * (1 - datum.effort / this.topValue)}%`;
        // also let's laid the text lines horizontally
        domConfig.style = 'writing-mode: lr';

        return domConfig;
    },
    ...
})

For more details on the functions please check their docs:

This release also deprecates getRectClass config in favor of new getBarClass config to make naming more consistent. The old config will be removed in the next major release so please change getRectClass in your code to getBarClass before that.

Gantt v6.1.0

Show Unscheduled Tasks in Gantt Chart

We have added a new feature to show unscheduled tasks in the Gantt Chart. Unscheduled tasks are those tasks that have either a startDate or both duration and endDate set to null. This feature is enabled by default. To disable it, set the showUnscheduledTasks config on the Gantt Chart to false. Unscheduled tasks are rendered as icons.

We now also allow creating dependencies for such tasks. When an unscheduled task has an incoming dependency, it will be scheduled with a duration of 1.

const gantt = new Gantt({ appendTo : targetElement, columns : [ { type : 'name', field : 'name', text : 'Name' } ], height : 400, startDate : new Date(2024, 5, 1), endDate : new Date(2024, 5, 11), project : { startDate : '2024-06-01', tasks : [ { id : 1, name : 'Tasks', expanded : true, children : [ { id : 11, name : 'Task 1', duration : 2 }, { id : 12, name : 'Task 2' }, { id : 13, name : 'Task 3', duration : 3, expanded : true, children : [ { id : 16, name : 'Task 4', duration : 5 }, { id : 14, name : 'Task 5' }, { id : 15, name : 'Task 6', duration : 2 } ] } ] } ], dependencies : [ { id : 1, fromTask : 11, toTask : 13 }, { id : 2, fromTask : 16, toTask : 15 } ] } });

Postpone the resolution of certain conflicts

It is now possible to postpone resolution of certain scheduling conflicts - either via conflict popup dialog or automatically. Task with postponed conflict will be marked with a flag, which can be visualized with the Info column.

Please refer to the documentation of allowPostponedConflicts and autoPostponedConflicts options.

Dragging multiple tasks

You can now opt in to allow dragging multiple selected task bars at once in the schedule area. Enable this with the new dragAllSelectedTasks property available on the TaskDrag feature. This property will be default true from v7.0.

const gantt = new Gantt({ appendTo : targetElement, features : { taskDrag : { dragAllSelectedTasks : true } }, columns : [ { type : 'name', field : 'name', text : 'Name' } ], height : 310, startDate : new Date(2024, 7, 25), endDate : new Date(2024, 8, 1), project : { startDate : '2024-08-26', tasks : [ { id : 100, name : 'Tasks', expanded : true, children : [ { id : 1, name : 'Task 1', duration : 2 }, { id : 2, name : 'Task 2', duration : 2 }, { id : 3, name : 'Task 3', duration : 3 }, { id : 4, name : 'Task 4', duration : 1 } ] } ] } }); gantt.selectedRecords = [gantt.taskStore.getById(1), gantt.taskStore.getById(2), gantt.taskStore.getById(4)];

Elapsed duration units support

In this release the Gantt has got Elapsed Durations support. In order to use it one should provide a task duration value in special elapsed time units. In English locale they look like regular time units prefixed with "e" letter.

Here is a list of some new supported units:

Unit Description
eminute Elapsed minute. Lasts 60 seconds.
ehour Elapsed hours. Lasts 60 minutes.
eday Elapsed day. Lasts 24 hours.
eweek Elapsed week. Lasts 7 elapsed days.
emonth Elapsed month. Lasts 30 elapsed days.
equarter Elapsed quarter. Lasts 3 elapsed months.
eyear Elapsed year. Lasts 3 elapsed quarters or 12 elapsed months.

For example one can enter a task duration as 7 edays or make a task with the following data:

new TaskModel({
    startDate    : '2024-09-10',
    endDate      : '2024-09-17',
    duration     : 7,
    durationUnit : 'ed'
});

The difference between a regular duration and an elapsed one is the Gantt schedules an elapsed duration task as 24/hours per day and 7 days/week, ignoring all nonworking time. So you could use an Elapsed Duration value for a task that needs to run continuously without a break or when planning a project on early stages having rough task dates/durations info.

Please also take into account that such tasks ignore assigned resource calendars forcing them to use the same 24/7 calendar.

Gantt v6.1.3

New keepTime modes for StartDateField and EndDateField classes

The StartDateField and EndDateField classes processing of time values differs from the standard DateField behavior. So it was decided to make separate modes for them:

  • StartDateFieldkeepTime config has got a new sod mode (default for the field). When the mode is enabled the field adjusts its value time portion to start of the working day. The adjustment is skipped when loading a record value to the field.

  • EndDateFieldkeepTime config has got a new eod mode (default for the field). When the mode is enabled the field adjusts its value time portion to end of the working day. The adjustment is skipped when loading a record value to the field.

Gantt v6.1.4

Introducing thin trial NPM packages

Starting with the 6.1.4 release, there are now trial versions of thin NPM packages available on our NPM server. These can be used to evaluate combining multiple products before purchasing a license. Please check the combining multiple products guides for the trial packages list and installation tips:

New is{{ClassName}} boolean property

Classes extending Base have got a new is{{ClassName}} boolean property indicating instances of the corresponding class or subclasses of thereof. The properties can be used for checking types without need of importing the corresponding types just to do instanceof check.

For example TaskModel class is automatically decorated with isTaskModel property returning true. And EventSegmentModel has isEventSegmentModel as true respectively. Then the following taskRenderer code can be used for checking the corresponding types:

    taskRenderer({ taskRecord }) {
        // if that's a segment
        if (taskRecord.isEventSegmentModel) {
            // ...render a segment
        }
        // that's a task
        else {
            ...
        }
    },

ProjectModel and EventSegmentModel classes has got new properties

ProjectModel class has got new segmentModelClass property allowing to override the class used for representing a segment:

// a custom class for a segment
class MySegment extends EventSegmentModel {
    static fields = [
       // a custom segment field
       { name : 'responsiblePerson' }
    ];
}

new Gantt({
    project : {
        segmentModelClass : MySegment
    }
})

EventSegmentModel class has got new segmentIndex property providing zero-based index of the segment.

Gantt v6.1.6

Suspended tasks support in msprojectimport demo

Starting with this release, msprojectimport demo represents suspended and then resumed tasks with segments field. The change should not be breaking but still if you don't want this logic please change use.segments.for.suspended config in the main/resources/META-INF/projectreader.properties file included in the demo to false:

use.segments.for.suspended=false

Gantt v6.1.7

New scrollAction config in CellEditing

The scrollAction config specifies what action should be taken if an active cell editor is scrolled out of view.

It may be set to 'cancel', 'complete' or null.

The default value is null which means the edit is preserved.

New roundedSplit config introduced in EventSegments feature

The roundedSplit config allows user, when is set to false, to split tasks using the exact clicked date. When the config value is true (default) the feature uses a rounded date.

new Gantt({
    ...
    features : {
        eventSegments : {
            // split at the exact date user clicks in UI
            roundedSplit : false
        }
    }
})

Gantt v6.1.8

rtl config of Widget

The rtl config property of Widgets is now public. By default Widgets conform to the writing direction of the element they are rendered to. But with the now public rtl property, you can force a widget, and all descendant widgets to lay out from right to left.

Duration and lag conversion hooks

This release introduces new public methods allowing to override duration units conversion easier.

Task model has got a couple of new methods:

  • convertDurationGen method that basically converts the provided duration value from one time unit to another. The method has to be a generator to embed into the rest of the Engine code.
  • canConvertDuration method that indicates whether the task can perform the requested duration conversion. The method is used when requesting a conversion in a synchronous way and since the data is loaded asynchronously there could be cases when a conversion is not possible yet. By default the method checks that the project has loaded the rates needed for conversion.

And dependency model has got new convertLagGen method responsible for converting the dependency lag. Our codebase has no code triggering lag conversion from a synchronous context. So we haven't added canConvertLag similar to mentioned canConvertDuration.

Usage example

In the old version of the Gantt made for Ext JS each calendar keeps own conversion rates. The approach was quite controversial and caused a lot of questions. So it was decided to change that in the new Gantt. But if you migrate from the old version and want to stick to that approach you can use the following code:

// Make calendars capable of converting durations.
// This will add "hoursPerDay", "daysPerWeek" and "daysPerMonth" fields to MyCalendarModel model
class MyCalendarModel extends DurationConverterMixin.derive(CalendarModel) {}

class MyDependencyModel extends DependencyModel {

    * convertLagGen(duration, fromUnit, toUnit) {
        // use the dependency calendar as lag converter
        const converter = yield this.$.calendar;

        return yield* converter.$convertDuration(duration, fromUnit, toUnit);
    }

}

class MyTaskModel extends TaskModel {

    * convertDurationGen(duration, fromUnit, toUnit) {
        // use the task calendar as duration converter
        const converter = yield this.$.effectiveCalendar;

        return yield* converter.$convertDuration(duration, fromUnit, toUnit);
    }

    // Override to check that the task calendar is ready for converting
    canConvertDuration(duration, fromUnit, toUnit) {
        // sanitize provided units ("d", "days" -> "day", "ms" -> "millisecond" etc)
        toUnit   = DateHelper.normalizeUnit(toUnit);
        fromUnit = DateHelper.normalizeUnit(fromUnit);

        const calendar = this.effectiveCalendar;

        // can convert duration if its numeric and
        return typeof duration === 'number' &&
            // the task calendar is resolved and has needed conversion rates
            calendar?.unitsInMs?.[ fromUnit ] && calendar.unitsInMs[ toUnit ];
    }
}

new Gantt({
    project : {
        // tell the project to use own customized models
        calendarModelClass   : MyCalendarModel,
        taskModelClass       : MyTaskModel,
        dependencyModelClass : MyDependencyModel,
        ...
    },
    ...
})

Gantt v6.2.0

Task highlighting

Task highlighting has been added to the Gantt API. You can programmatically highlight one or more available tasks in the timeline by calling highlightTasks.

The highlighting will be removed when the user clicks somewhere in the browser window (this behavior can be changed). You can also remove the highlighting programmatically.

If the tasks being highlighted is not in view, the closest one of them will be scrolled into view (this behavior can also be changed).

// This will highlight tasks with id 1, 2 and 3.
// And, if necessary, scroll them into view.
// And remove the highlighting on window click
gantt.highlightTasks([1,2,3]);

// This will highlight a specific task
// Without scrolling (second argument)
// And removing the highlight after 5s only (third argument)
gantt.highlightTasks(taskRecord, false, false);
setTimeout(() => gantt.unhighlightTasks(taskRecord), 5000);

Project edit feature

This release introduces new ProjectEdit feature. The feature displays the project editor - a special popup allowing user to edit a project parameters: name, start date, scheduling direction, working time setting and duration unit settings. The editor is implemented in the ProjectEditor class.

The feature is disabled by default and should be enabled like this:

new Gantt({
    features : {
        projectEdit : true
    },
    ...
})

When the feature is enabled the Gantt has a editProject method that can be used to start editing a project:

// open the project editor
gantt.editProject(gantt.project);

The method accepts a project instance to edit. The value can be omitted and then the method will start editing of the current project loaded in the Gantt. So the above code snippet can be shortened to:

// open the project editor
gantt.editProject();

Please check the new editor in the advanced demo.

New respectStoreFilters and assignmentFilterFn config on the ResourceHistogram view

ResourceHistogram class has got new configs giving more control on data filtering when collecting resource allocation:

  • respectStoreFilters boolean config that allows to specify whether exiting task and assignment store filters should be taken into account or not:
new ResourceHistogram({
    // skip filtered out tasks/assignments
    respectStoreFilters : true
    ...
});

// Filter task store to include only task w/ id === 777
// That will result the histogram displays only that task allocation
project.taskStore.filter(task => task.id === 777);

The config is false by default so the filters are not taken into account.

  • assignmentFilterFn config accepts a function that specifies whether the provided assignment allocation should be included or not. The function is recommended to be a generator to attach to the Engine transactions (which use generators internally):
new ResourceHistogram({
    // custom filtering function
    * assignmentFilterFn(assignment, allocationInfo) {
        // get the assignment task
        const task = yield assignment.$.event;

        // include only allocation of events having "type" field set to "Meeting"
        if (event) {
            // get "type" field value and bind to its changes
            // to refresh the histogram automatically
            const type = yield* allocationInfo.readField(event, 'type');

            return type === 'Meeting';
        }
    }
    ...
});

S-Curve chart

Introduced a TimelineChart feature which allows drawing charts over the timeline. By default, it is used to draw s-curves of project progress or duration. Try it in the new s-curve demo.

targetElement.innerHTML = '<p>This demo shows the timeline chart feature</p>'; const gantt = new Gantt({ appendTo : targetElement, height : 350, startDate : '2019-07-07', endDate : '2019-07-29', features : { timelineChart : true }, rowHeight : 60, project : new ProjectModel({ startDate : '2019-07-07', duration : 30, events : [ { id : 1, name : 'Project A', duration : 30, expanded : true, children : [ { id : 11, name : 'Child 1', duration : 1, leaf : true, rollup : true, cls : 'child1' }, { id : 12, name : 'Child 2', duration : 3, leaf : true, rollup : true, cls : 'child1' }, { id : 13, name : 'Child 3', duration : 0, rollup : true, leaf : true, cls : 'child1' } ] } ], dependencies : [{ id : 1, lag : 1, fromEvent : 11, toEvent : 12 }, { id : 2, lag : 1, fromEvent : 12, toEvent : 13 }] }) });

Charts feature

The new Charts feature adds a pop-up chart designer connected to the Gantt, for creating line, bar, pie, and other types of charts from selected data in the Gantt.

new Gantt({
    features : { charts : true },
    // ...
});

With the feature enabled, make a selection of cells in the grid and then activate the cell context menu and choose New Chart to open the chart designer.

Check out the Charts example to see the new feature in action.

Chart column

The new ChartColumn supports displaying a chart inside a grid column. You can provide a chart config and supply data records for the chart in the specified field on your primary grid data record:

new Gantt({
    columns : [
        {
             type: 'chart',
             chart : {
                 chartType : 'line',
                 series : [{
                     field : 'price'
                 },{
                     field : 'changePct'
                 }],
                 labels : {
                     field : 'symbol'
                 }
             }
        }
    ],
    // ...
});

Sparkline column

In addition to ChartColumn mentioned above, there is a new SparklineColumn specifically designed for sparklines (micro-charts that show general trends in a data series). This column type offers a simple API for this use-case. Data values are provided as arrays of numbers on your primary grid record. Line, bar, and pie chart types are supported.

const gantt = new Gantt({
    columns    : [
        {
            type  : 'sparkline',
            field : 'monthlySales'  // field values should be arrays of numbers
        }
    ],
    // ...
});

New respectStoreFilters and assignmentFilterFn config on the ResourceHistogram view

ResourceHistogram class has got new configs giving more control on data filtering when collecting resource allocation:

  • respectStoreFilters boolean config that allows to specify whether exiting task and assignment store filters should be taken into account or not:
new ResourceHistogram({
    // skip filtered out tasks/assignments
    respectStoreFilters : true
    ...
});

// Filter task store to include only task w/ id === 777
// That will result the histogram displays only that task allocation
project.taskStore.filter(task => task.id === 777);

The config is false by default so the filters are not taken into account.

  • assignmentFilterFn config accepts a function that specifies whether the provided assignment allocation should be included or not. The function is recommended to be a generator to attach to the Engine transactions (which use generators internally):
new ResourceHistogram({
    // custom filtering function
    * assignmentFilterFn(assignment, allocationInfo) {
        // get the assignment task
        const task = yield assignment.$.event;

        // include only allocation of events having "type" field set to "Meeting"
        if (event) {
            // get "type" field value and bind to its changes
            // to refresh the histogram automatically
            const type = yield* allocationInfo.readField(event, 'type');

            return type === 'Meeting';
        }
    }
    ...
});

Gantt v6.2.3

FixedEffort tasks effort normalization change

FixedEffort scheduling mode has been changed. By default such tasks empty effort is normalized to their duration if the tasks have no assignments. And since this release it's possible to disable that normalization.

After disabling that behavior such tasks will auto-calculate their effort when assignments are added. Please use the following code to apply that mode:

class MyTask extends TaskModel {
    // disable normalizing of empty effort to duration
    static normalizeEffortIfUnassigned = false
}

new Gantt({
    project : {
        // Let the Project know we want to use our custom MyTask model
        taskModelClass : MyTask
        ...
    },
    ...
});

Gantt v6.2.4

New recurrentDatesTimeZone field on calendar intervals

CalendarIntervalModel has got a new field specifying a timezone in which recurrentStartDate and recurrentEndDate rules are provided.

Until this release time info of the rules were always treated as specified in the local machine time zone. But that could result inconsistencies when backend provided dates in some other timezone. The new field should help in such cases.

Here is for example a dataset using the new field:

{
    "calendars" : [
        {
            "id"        : "general",
            "name"      : "General",
            "intervals" : [
                {
                    // weekends are days off starting Sat 00:00 GMT+6 and finishing Mon 00:00 GMT+6
                    "recurrentStartDate"     : "on Sat",
                    "recurrentEndDate"       : "on Mon",
                    // specify we use GMT+6 for recurrent*Date rules
                    "recurrentDatesTimeZone" : "+06:00",
                    "isWorking"              : false
                }
            ]
        }
    ],
    "resources" : [
        { "id" : "r1", "name" : "Worker #1" }
    ],
    "assignments" : [
        { "id" : "a1", "resource" : "r1", "event" : 11 }
    ],
    "events" : [
        {
            "id"           : 11,
            "name"         : "Build a skyscraper",
            // event start is specified in GMT+6 timezone
            "startDate"    : "2017-01-16T00:00+06:00",
            "duration"     : 3,
            "durationUnit" : "hour"
        }
    ]
}

Loading of the above dataset on a machine with GMT timezone will adjust the non-working interval six hours back to Fri 18:00 - Sun 18:00 and the event will start 2017-01-15T18:00 accordingly.

Gantt v6.2.5

New maxCriticalPathsCount field on the project model

ProjectModel has got new maxCriticalPathsCount parameter limiting the number of critical paths it collects. When critical tasks connectivity is high (there are many of such tasks having many critical predecessors) the tasks might produce a huge number of critical paths. Basically every critical task having N critical predecessors will result multiplying the number of paths by N times. Which could be a trouble for some datasets since collecting of all of the paths will take too much time. So this new value is the last stand limiting the number of paths to collect in order to protect from such cases.

Gantt v6.3.0

New Chart module

Bryntum products now ship with a new Chart module, which makes it easier to integrate Chart.js-based charts (see www.chartjs.org) with our products. The new module can be combined with all our products, by using the thin bundles / packages.

Try the new feature out in the new charts demo.

Using charts with your applications:

If you are using a vanilla JavaScript application, you need to import the chart thin bundle to enable support for the Charts feature:

import 'PATH_TO_DISTRIBUTION_FOLDER/build/thin/chart.module.thin.js';

For framework-based applications, the Bryntum npm repository provides the @bryntum/chart-thin package, along with chart component wrapper packages for major frameworks:

Angular:

import '@bryntum/chart-thin'
import { BryntumChart } from '@bryntum/chart-angular-thin'

React:

import '@bryntum/chart-thin'
import { BryntumChart } from '@bryntum/chart-react-thin'

Vue 3:

import '@bryntum/chart-thin'
import { BryntumChart } from '@bryntum/chart-vue-3-thin'

Streamed PDF export

The PdfExport feature now supports exporting large datasets by streaming data to the export server using a WebSocket connection. This allows for more efficient handling of large datasets during export operations, improving performance and reducing memory usage

Gantt v6.3.1

Manual FixedEffort tasks preserves its start, end and duration

By default FixedEffort tasks keep their effort intact preferring to adjust duration and assignment units. Since this release such tasks can treat manually scheduled mode as fixing their duration too. So changing of duration or effort would always mean adjusting units. Please use the following code to apply that mode:

class MyTask extends TaskModel {
    // fix start/end/duration for manual tasks
    static preserveSEDFieldsIfManual = true;
}

new Gantt({
    project : {
        // Let the Project know we want to use our custom MyTask model
        taskModelClass : MyTask
        ...
    },
    ...
});

Contents