v7.3.0

What's new in Scheduler v6.0.0+

Scheduler v6.0.0

Multi-Event resize

The EventResize feature now allows user to simultaneously resize multiple selected events. To disable this feature set resizeSelected to false.

LockRows feature

This feature allows resources which satisfy a certain condition to be locked at the top of the scheduler.

By default the condition is that a certain named field have a truthy value. The field which decides this status defaults to 'fixed', but that is configurable using the fieldName property.

When used with fieldName, the CellMenu context menu appears with an extra option to toggle the value of that field in the contextual record. For more granular control, use the filterFn to decide which records should be locked.

This feature is disabled by default.

Lazy data loading (infinite scroll)

Stores now has support for lazy loading of data. In the Scheduler this means it is possible to continuously load resources and events (and more) when they scroll into view, instead of loading the complete datasets at once.

Activating lazy loading is either done by configuring each Scheduler store separately, or configuring the CrudManager to take care of it.

Here is an example of how to configure the stores separately (the stores communicates with the API by the use of the built-in AjaxStore functionality).

new Scheduler({
    resourceStore : {
        // This will create an AjaxStore
        readUrl  : 'backend/resources/read',
        // This will activate the lazy load functionality
        lazyLoad : true,
        // This will load the Store initially upon creation
        autoLoad : true
    },
    eventStore : {
        // This will create an AjaxStore
        readUrl  : 'backend/events/read',
        // This will activate the lazy load functionality
        lazyLoad : true
    }
});

And here is an example of how to do it using the CrudManager.

new Scheduler({
    crudManager : {
        loadUrl  : 'backend/events/read',
        // This will activate the lazy load functionality
        lazyLoad : true,
        // This will initiate the first load upon creation
        autoLoad : true,
    }
});

The backend will receive a request with startIndex and count params that refers to which resources to load. The params will also include a startDate and an endDate that refers to which events (or other type of data) to load (for the resource range). Implement these params in your data queries to only return this range of records.

It is also possible to not use AjaxStore's nor the CrudManager. In these cases you need to do more configuration. For a detailed explanation of the lazy load functionality, please read our guide. There is also a new demo that uses an express.js backend to demonstrate the functionality.

Scheduler v6.0.2

TimelineHistogram class API changes

TimelineHistogram has got two new hooks providing better control of the rendered DOM elements.

The first one is getBarDOMConfig - a function which is meant to return a bar DOM configuration object. That object will configure the bar RECT element.

new TimelineHistogram({
    // 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 new hook is getBarTextDOMConfig - a function which is meant to return a DOM configuration object for text elements:

new TimelineHistogram({
    series : {
        work : {
            type  : 'bar',
            field : 'work'
        }
    },
    // display "work" value as text
    getBarText(datum) {
        return datum.work;
    },
    // Place text at the top of the "work" bar
    getBarTextDOMConfig(domConfig, datum, index) {
        // to do that we calculate y-position in percents
        domConfig.y = `${100 * (1 - datum.work / this.topValue)}%`;
        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.

Scheduler v6.0.5

New event for tick size and new behaviour

With this release, when tick size changes, center position will be maintained. Moreover we have added a tickSizeChange event that is fired when the tick size changes.

listeners : {
    tickSizeChange({ source, tickSize }) {
        ....
    },
}

Snap to resource

The EventDrag feature has new property: snapToResource. Set it to true to be able to snap events to resources while dragging events, i.e. vertical row snap in horizontal mode and vice versa. If you want to customize the number of pixels from the dragged event that will trigger the snapping behavior to the new resource, you can set the threshold property. It works only if snap value is true.

new Scheduler({
    ...
    snap     : true,
    features : {
        eventDrag : {
            snapToResource : {
                threshold : 30
            }
        }
    },
    ...
});

Scheduler v6.1.0

New DependencyMenu feature

You can now show a menu when right-clicking a dependency line.

new Scheduler({
    ...
    features : {
        dependencyMenu : true
    },
    ...
});

Remote paging, sorting and filtering added to Store

The ability to sort, filter and paginate records remotely was previously only available when using an AjaxStore configured with a readUrl. Now, it is possible to use the built-in functionality and UI controls when using a regular Store.

3 new configs has been added to Store:

Turning any of these functions on is a simple matter of setting the config to true, and then implementing a way of providing the correct data to the Store. For that, the requestData function needs to be implemented. Here is a simple example using paging, sorting and filtering:

const store = new Store({
    remotePaging : true,
    remoteFilter : true,
    remoteSort   : true,
    requestData({ filters, sorters, page, pageSize }){
        let filteredRecords = [...allRecords];

        filters?.forEach(filter => {
            const { field, operator, value, caseSensitive } = filter;

            if(operator === '='){
                filteredRecords = filteredRecords.filter(r => r[field] === value);
            }
            else {
                /// ... implement other filter operators
            }
        });

        sorters?.forEach(sorter => filteredRecords.sort((a,b) => {
            const { field, ascending } = sorter;

            if (!ascending) {
                ([b, a] = [a, b]);
            }

            return a[field] > b[field] ? 1 : (a[field] < b[field] ? -1 : 0)
        }));

        const start = (page - 1) * pageSize;
        const data = filteredRecords.splice(start, start + pageSize);

        return {
            data,
            total : filteredRecords.length
        }

    }
});

For a more detailed explanation please see the updated Store guide. There is also a new Grid demo that demonstrates the new functionality.

Paging support

Support for paging of data has been added to the Scheduler. The config belongs to the Store or the CrudManager and supports both AjaxStore and regular Store data requests (see previous chapter).

Example of Scheduler with paged AjaxStores:

const scheduler = new Scheduler({
    resourceStore : {
        remotePaging : true,
        readUrl : './resources' 
    }, 
    eventStore : {
        remotePaging : true,
        readUrl : '/events'
    },
    bbar : {
        type : 'pagingtoolbar',
        store : 'resourceStore'
    }
});

Examples of Scheduler with paged CrudManager:

const scheduler = new Scheduler({
    crudManager : {
        remotePaging : true,
        read : './read'
    },
    bbar : {
        type : 'pagingtoolbar',
        store : 'resourceStore'
    }
});

For a more detailed explanation please see the new Paging guide. There is also a new demo that demonstrates the new functionality.

Vertical lazy loading when Resource Store is not lazy

A lazy loaded EventStore, AssignmentStore and ResourceTimeRangeStore will now lazy load when scrolling vertically, even when the ResourceStore is not lazy loaded. The previous behavior, which can be configured by setting loadFullResourceRange to true on the Store's lazyLoad config, was to always load the full resource range.

Revert to old behavior:

const scheduler = new Scheduler({
    resourceStore : {
        // Not really needed, here to be clear this only applies to a ResourceStore that is not lazy loaded
        data,
        lazyLoad : false 
    },
    eventStore : {
        lazyLoad : {
            loadFullResourceRange : true
        }
    }
});

Timeline boundaries

You can now set boundaries for the timeline using two new properties: minDate and maxDate. Actions such as timeline scrolling, all types of timeline zooms, and shifts will respect these limits.

const scheduler = new Scheduler({
    appendTo : 'container',
    minDate  : new Date(2016, 5, 1),
    maxDate  : new Date(2018, 5, 1),
});

Scheduler v6.1.1

Partnered Scheduler's locked region width syncing

If you partner two Schedulers which both uses a calculated width for their locked regions, the synced region width will from this version be the largest of the two. The previous behavior was to always use the partner's width.

Since the region only use a calculated width when all column widths are know, you can simply configure the locked region width manually.

const firstScheduler = new Scheduler({
    subGridConfigs : {
        locked : 100 // fixed with 
    }
});

const secondScheduler = new Scheduler({
    partner : firstScheduler
});

Scheduler 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:

Scheduler v6.1.76

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.

Scheduler 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.

EventCopyPaste pattern pasting

The EventCopyPaste feature will now paste multiple events into the same pattern they were copied. To revert to the previous behaviour of pasting all copied events to the same target resource and date, set unifiedPaste on the feature config object to false.

new Scheduler({
    features : {
        eventCopyPaste : {
            // This reverts to the previous behaviour
            unifiedPaste : false
        }
    }
})

Scheduler v6.2.0

New TreeSummary feature

A feature that allows you to roll up and display values in the time axis cell for each parent row in a tree scheduler.

new Scheduler({
     features : {
         treeSummary : {
             summaryRenderer({ startDate, endDate, resourceRecord, timeline }) {
                 let totalDemandedCapacity = 0;

                 resourceRecord.traverse(node => {
                     node.events.forEach(task => {
                         if (DateHelper.intersectSpans(task.startDate, task.endDate, startDate, endDate)) {
                             totalDemandedCapacity += task.demandedCapacity || 0;
                         }
                     });
                 }, true);

                 if (timeline.project.effectiveCalendar.isWorkingTime(startDate, endDate)) {
                     return 1 - totalDemandedCapacity;
                 }
                 else {
                     return 0;
                 }
             }
         }
     }
});

There are also two new demos (Tree summary and Tree summary custom) that demonstrates the new functionality.

Event highlighting

Event highlighting has been added to the Scheduler API. You can programmatically highlight one or more available events or assignments in the timeline by calling highlightEvents.

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 events 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 events with id 1, 2 and 3.
// And, if necessary, scroll them into view.
// And remove the highlighting on window click
// Only singleAssignment mode
scheduler.highlightEvents([1,2,3]);

// This will highlight a specific assignment
// Without scrolling (second argument)
// And removing the highlight after 5s only (third argument)
scheduler.highlightEvents(assignmentRecord, false, false);
setTimeout(() => scheduler.unhighlightEvents(assignmentRecord), 5000);

Quicker dependency removal

You can now delete dependencies quickly by clicking the line to reveal a delete icon. This is a more intuitive way to delete dependencies than the previous method of right-clicking the line and selecting "Delete". You can toggle this new behavior with the enableDelete config option.

const scheduler = new Scheduler({
    features : {
        dependencies : {
            // Disable the new delete icon (on by default)
            enableDelete : false
        }
    }
});

Try it out in any demo that uses dependencies, or here:

Scheduler 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.

Building upon the new module, Grid now has a Charts feature, which leverages the new Chart and ChartDesigner

There are three new Scheduler demos that showcase the new Chart module:

  • charts - showcases how to use the new Charts feature
  • scheduler-chart - combines the new Chart module with the Scheduler
  • sparklines - demonstrates how to use the new SparklineColumn

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

Contents