Scheduler Pro features
Features are classes that add functionality to the Scheduler Pro. The purpose of this guide is to give an overview of the features that ships with Scheduler Pro and show how you can configure them.
Bryntum Scheduler Pro is based on the Bryntum Scheduler and inherits lots of features from it. The Scheduler, in turn, is based on the Bryntum Grid, which provides capabilities like cell editing, column resizing, and many more. Please refer to this guide for general information about using the features in the Bryntum Grid.
If you want to create a custom feature, head over to GridFeatureManager docs.
Built-in features
Bryntum Scheduler Pro comes with the following features included:
AllocationCellEdit (API docs)
This is a feature of the ResourceUtilization view that allows editing an assignment's time-phased effort values.
// <code-header> // This example uses Scheduler Pro TimePhasedProjectModel class // which is named SchedulerProTimePhasedProjectModel in the Gantt distribution TimePhasedProjectModel = typeof SchedulerProTimePhasedProjectModel !== 'undefined' ? SchedulerProTimePhasedProjectModel : TimePhasedProjectModel; targetElement.innerHTML = '<p>Double click an event row effort value to edit it. Use <kbd>F2</kbd> or <kbd>ENTER</kbd> to complete the editing and <kbd>ESC</kbd> to reject changes:</p>'; // </code-header> const resourceUtilization = new ResourceUtilization({ project : new TimePhasedProjectModel({ loadUrl : 'data/SchedulerPro/examples/view/ResourceUtilization.json', autoLoad : true }), columns : [ { type : 'tree', text : 'Name', field : 'name', width : 170, renderer({ record, value }) { return record.generatedParent ? record.key.name : value; } } ], // the view should not be readOnly to allow editing readOnly : false, features : { // Allow effort values editing allocationCellEdit : true, scheduleContext : { // allow navigating the time axis cells w/ keyboard keyNavigation : true }, treeGroup : { // group by resource levels : [ // group by resource ({ origin }) => { // origin could be an array of time-phased assignments origin = origin[0] || origin; return origin.resource; } ] } }, startDate : new Date(2020, 3, 26), endDate : new Date(2020, 4, 15), appendTo : targetElement, rowHeight : 40, tickSize : 40, minHeight : '20em', // display tooltip showBarTip : true }); This feature is disabled by default.
AllocationCopyPaste (API docs)
This is a feature of the ResourceUtilization view that allows copy-pasting an assignment's time-phased effort values.
// <code-header> // This example uses Scheduler Pro TimePhasedProjectModel class // which is named SchedulerProTimePhasedProjectModel in the Gantt distribution TimePhasedProjectModel = typeof SchedulerProTimePhasedProjectModel !== 'undefined' ? SchedulerProTimePhasedProjectModel : TimePhasedProjectModel; targetElement.innerHTML = '<p>Select an event effort value then use <kbd>CTRL</kbd> + <kbd>C</kbd> to copy it and then use <kbd>CTRL</kbd> + <kbd>V</kbd> to paste it to another selected location:</p>'; // </code-header> const resourceUtilization = new ResourceUtilization({ project : new TimePhasedProjectModel({ loadUrl : 'data/SchedulerPro/examples/view/ResourceUtilization2.json', autoLoad : true, validateResponse : false }), columns : [ { type : 'tree', text : 'Name', field : 'name', width : 150, renderer({ record, value }) { return record.generatedParent ? record.key.name : value; } } ], // the view is not readOnly to allow pasting readOnly : false, features : { // Allow effort values copy/pasting allocationCopyPaste : true, allocationCellEdit : true, scheduleContext : { // allow navigating the time axis cells w/ keyboard keyNavigation : true, // allow multi selecting the time axis cells // (can be useful for copy/pasting values there) multiSelect : true }, treeGroup : { // group by resource levels : [ // group by resource ({ origin }) => { // origin could be an array of time-phased assignments origin = origin[0] || origin; return origin.resource; } ] } }, startDate : new Date(2020, 3, 26), endDate : new Date(2020, 4, 15), appendTo : targetElement, rowHeight : 40, tickSize : 40, minHeight : '21em', // display tooltip showBarTip : true }); This feature is disabled by default.
CalendarHighlight (API docs)
This feature temporarily visualizes calendars for the event or resource calendar (controlled by the calendar config).
const schedulerPro = new SchedulerPro({ appendTo : targetElement, // makes scheduler as high as it needs to be to fit rows autoHeight : true, snap : true, startDate : new Date(2022, 4, 15), endDate : new Date(2022, 4, 29), columns : [ { field : 'name', text : 'Name', width : 100 } ], features : { eventDrag : { snapToResource : true }, dependencies : false, scheduleTooltip : false, calendarHighlight : true }, project : { calendarManagerStore : { validateForCalendarEditorOnLoad : false }, resources : [ { id : 1, name : 'Bernard' }, { id : 2, name : 'Bianca' } ], events : [ { id : 1, name : 'Drag me', startDate : '2022-05-18', duration : 2, resizable : false, calendar : 'inspection' } ], assignments : [ { id : 1, event : 1, resource : 1 } ], calendars : [ { id : 'inspection', name : 'Inspection period May 16-23', unspecifiedTimeIsWorking : false, intervals : [ { name : 'Inspection period', startDate : '2022-05-16', endDate : '2022-05-24', isWorking : true } ] } ] }, getDateConstraints(resourceRecord, eventRecord) { if (eventRecord) { const { startDate, endDate } = eventRecord.effectiveCalendar.intervals.first; if (startDate) { return { start : startDate, end : endDate }; } } } }); (async() => { await schedulerPro.project.commitAsync(); if (!schedulerPro.isDestroyed) { schedulerPro.features.calendarHighlight.highlightEventCalendars(schedulerPro.eventStore.first); } })(); This feature is disabled by default.
CellEdit (API docs)
Extends the CellEdit to encapsulate SchedulerPro functionality.
This feature is enabled by default.
Dependencies (API docs)
This feature implements support for project transactions and is used by default in Scheduler Pro.
This feature is enabled by default.
DependencyEdit (API docs)
Feature that displays a popup containing fields for editing dependency data.
This feature is disabled by default.
EventBuffer (API docs)
Feature that allows showing additional time before & after an event, to visualize things like travel time - or the time you need to prepare a room for a meeting + clean it up after.
targetElement.innerHTML = '<p>Open editor to change setup / cleanup:</p>'; const schedulerPro = new SchedulerPro({ appendTo : targetElement, // makes scheduler as high as it needs to be to fit rows autoHeight : true, startDate : new Date(2022, 4, 6, 9), endDate : new Date(2022, 4, 6, 17), viewPreset : 'hourAndDay', barMargin : 12, columns : [ { type : 'resourceInfo', field : 'name', text : 'Meeting Rooms', showEventCount : false, showMeta : record => `Car: ${record.car}`, width : 150 } ], features : { eventBuffer : { renderer({ eventRecord, preambleConfig, postambleConfig }) { if (eventRecord.preamble) { preambleConfig.icon = 'fa fa-car'; preambleConfig.cls = 'travel-before'; preambleConfig.text = eventRecord.preamble.toString(true); } if (eventRecord.postamble) { postambleConfig.icon = 'fa fa-car'; postambleConfig.cls = 'travel-after'; postambleConfig.text = eventRecord.postamble.toString(true); } } } }, project : { resources : [ { id : 1, name : 'John', car : 'Tesla', image : false, iconCls : 'fa fa-user' }, { id : 2, name : 'Eva', car : 'Honda', image : false, iconCls : 'fa fa-user' }, { id : 3, name : 'Dan', car : 'Buick', image : false, iconCls : 'fa fa-user' } ], events : [ { id : 1, resourceId : 1, name : 'UN Meeting', startDate : '2022-05-06T10:00:00', duration : 3, durationUnit : 'h', preamble : '1 hour', postamble : '30 minute' }, { id : 2, resourceId : 2, name : 'Board meeting', startDate : '2022-05-06T11:00:00', duration : 2, durationUnit : 'h', preamble : '20 minute', postamble : '25 minute', resizable : false, eventColor : 'red' }, { id : 3, resourceId : 3, name : 'Starbucks meeting', startDate : '2022-05-06T13:00:00', duration : 3, durationUnit : 'h', preamble : '25 minute', postamble : '15 minute', resizable : false, eventColor : 'red' } ], calendars : [ { id : 'general', name : 'General', intervals : [ { recurrentStartDate : 'on Sat', recurrentEndDate : 'on Mon', isWorking : false } ] } ], calendar : 'general' } }); This feature is disabled by default.
EventDrag (API docs)
Drag events to reschedule their start & end dates. Can be configured to snap to certain time intervals.
This feature is enabled by default.
EventResize (API docs)
Feature that allows resizing an event by dragging its end.
This feature is enabled by default.
EventSegmentDrag (API docs)
Allows user to drag and drop event segments within the row.
This feature is enabled by default.
EventSegmentResize (API docs)
Feature that allows resizing an event segment by dragging its end.
This feature is enabled by default.
EventSegments (API docs)
This feature provides segmented events support. It implements rendering of such events and also adds a entries to the event context menu allowing to split the selected event and rename segments.
const schedulerPro = new SchedulerPro({ appendTo : targetElement, // makes scheduler as high as it needs to be to fit rows autoHeight : true, startDate : new Date(2022, 2, 20), endDate : new Date(2022, 2, 27), columns : [ { field : 'name', text : 'Name', width : 100 } ], project : { resources : [ { id : 1, name : 'Bruce' }, { id : 2, name : 'Diana' } ], events : [ { id : 1, name : 'Art project', startDate : '2022-03-21', segments : [ { startDate : '2022-03-21', duration : 1 }, { startDate : '2022-03-23', duration : 1 }, { startDate : '2022-03-25', duration : 1 } ] }, { id : 2, name : 'DIY project', startDate : '2022-03-21', segments : [ // segments can have their own names & colors { name : 'Plan', startDate : '2022-03-21', duration : 1, eventColor : 'indigo' }, { name : 'Get supplies', startDate : '2022-03-23', duration : 2 } ] } ], assignments : [ { id : 1, event : 1, resource : 1 }, { id : 7, event : 2, resource : 2 } ] }, features : { eventSegments : { // split at the exact date user clicks in UI roundedSplit : false } } }); This feature is enabled by default.
NestedEvents (API docs)
A feature that renders child events nested inside their parent. Requires Scheduler Pro to use a tree event store ( normally handled automatically when events in data has children).
const schedulerPro = new SchedulerPro({ appendTo : targetElement, // makes scheduler as high as it needs to be to fit rows autoHeight : true, features : { nestedEvents : true }, rowHeight : 160, startDate : new Date(2022, 2, 20), endDate : new Date(2022, 2, 27), columns : [ { field : 'name', text : 'Name', width : 100 } ], project : { resources : [ { id : 1, name : 'Bruce' }, { id : 2, name : 'Diana' } ], events : [ { id : 1, name : 'Art project', startDate : '2022-03-21', duration : 5, children : [ { id : 11, name : 'Get supplies', startDate : '2022-03-21', duration : 2 }, { id : 12, name : 'Sketch', startDate : '2022-03-22', duration : 1, eventColor : 'indigo' }, { id : 13, name : 'Outline', startDate : '2022-03-22', duration : 2, eventColor : 'blue' }, { id : 14, name : 'Ink', startDate : '2022-03-23', duration : 2, eventColor : 'violet' }, { id : 15, name : 'Share', startDate : '2022-03-24', duration : 2, eventColor : 'pink' } ] }, { id : 2, name : 'DIY project', startDate : '2022-03-24', duration : 5, children : [ { id : 21, name : 'Plan', startDate : '2022-03-21', duration : 1, eventColor : 'indigo' }, { id : 22, name : 'Get supplies', startDate : '2022-03-22', duration : 2 }, { id : 23, name : 'Prototype', startDate : '2022-03-22', duration : 3, eventColor : 'violet' }, { id : 24, name : 'Make', startDate : '2022-03-24', duration : 1, eventColor : 'blue' } ] } ], assignments : [ { id : 1, event : 1, resource : 1 }, { id : 2, event : 11, resource : 1 }, { id : 3, event : 12, resource : 1 }, { id : 4, event : 13, resource : 1 }, { id : 5, event : 14, resource : 1 }, { id : 6, event : 15, resource : 1 }, { id : 7, event : 2, resource : 2 }, { id : 8, event : 21, resource : 2 }, { id : 9, event : 22, resource : 2 }, { id : 10, event : 23, resource : 2 }, { id : 11, event : 24, resource : 2 } ] }, tbar : [ { type : 'buttongroup', toggleGroup : true, rendition : 'padded', items : { none : { text : 'Overlap' }, stack : { text : 'Stack' }, pack : { text : 'Pack', pressed : true } }, onToggle({ source, pressed }) { if (pressed) { schedulerPro.features.nestedEvents.eventLayout = source.ref; } } } ] }); This feature is disabled by default.
PercentBar (API docs)
This feature visualizes the percentDone field as a progress bar on the event elements. Each progress bar also optionally has a drag handle which users can drag can change the value.
const schedulerPro = new SchedulerPro({ appendTo : targetElement, // makes scheduler as high as it needs to be to fit rows autoHeight : true, startDate : new Date(2022, 2, 23), endDate : new Date(2022, 2, 28), columns : [ { field : 'name', text : 'Name', width : 100 } ], features : { percentBar : true }, project : { resources : [ { id : 1, name : 'George', eventColor : 'blue' }, { id : 2, name : 'Rob', eventColor : 'green' } ], events : [ { id : 1, name : 'Project X', startDate : '2022-03-24', duration : 4, percentDone : 80 }, { id : 2, name : 'Customer Project Y', startDate : '2022-03-23T13:00', duration : 4, percentDone : 40 } ], assignments : [ { id : 1, event : 1, resource : 1 }, { id : 2, event : 2, resource : 2 } ] } }); This feature is disabled by default.
ResourceEdit (API docs)
Feature that displays a popup containing widgets for editing resource data.
This feature is enabled by default.
ResourceNonWorkingTime (API docs)
Feature that highlights the non-working intervals for resources based on their calendar.
//<code-header> CSSHelper.insertRule('.b-sch-resource-time-range.nonworking { background: transparent repeating-linear-gradient(-55deg, var(--b-neutral-94), var(--b-neutral-94) 10px, var(--b-neutral-99) 5px, var(--b-neutral-98) 20px); }', targetElement.getRootNode()); //</code-header> const schedulerPro = new SchedulerPro({ appendTo : targetElement, // makes scheduler as high as it needs to be to fit rows autoHeight : true, startDate : new Date(2022, 7, 2), endDate : new Date(2022, 7, 14), columns : [ { field : 'name', text : 'Name' }, { field : 'calendar', text : 'Working on', editor : false } ], features : { nonWorkingTime : true, resourceNonWorkingTime : { maxTimeAxisUnit : 'week' } }, project : { resources : [ { id : 1, name : 'Bernard', calendar : 'weekends' }, { id : 2, name : 'Bianca', calendar : 'weekdays' } ], calendars : [ { id : 'weekends', name : 'Weekends', unspecifiedTimeIsWorking : true, intervals : [ { recurrentStartDate : 'on Mon', recurrentEndDate : 'on Sat', isWorking : false, cls : 'nonworking' } ] }, { id : 'weekdays', name : 'Weekdays', unspecifiedTimeIsWorking : true, intervals : [ { recurrentStartDate : 'on Sat', recurrentEndDate : 'on Mon', isWorking : false, cls : 'weekend' } ] } ] } }); This feature is disabled by default.
TaskEdit (API docs)
Feature that displays a Task editor, allowing users to edit task data. The default Task Editor is fully customizable, allowing you to add custom fields and tabs to fit your specific requirements.
const schedulerPro = new SchedulerPro({ appendTo : targetElement, flex : '1 0 100%', // Project contains all the data and is responsible for correct scheduling project : { events : [ { id : 1, name : 'Write docs', expanded : true, children : [ { id : 2, name : 'Proof-read docs', startDate : '2017-01-02', endDate : '2017-01-05' }, { id : 3, name : 'Release docs', startDate : '2017-01-09', endDate : '2017-01-10' } ] } ], resources : [ { id : 1, name : 'Albert' }, { id : 2, name : 'Bill' } ], assignments : [ { event : 2, resource : 1 }, { event : 3, resource : 2 } ] }, startDate : new Date(2016, 11, 31), endDate : new Date(2017, 0, 11), height : 250, columns : [ { field : 'name', text : 'Name' } ] }); This feature is enabled by default.
TimeSpanHighlight (API docs)
This feature exposes methods on the owning timeline widget which you can use to highlight one or multiple time spans in the schedule.
const schedulerPro = new SchedulerPro({ appendTo : targetElement, // makes scheduler as high as it needs to be to fit rows autoHeight : true, snap : true, startDate : new Date(2022, 4, 15, 10), endDate : new Date(2022, 4, 15, 17), viewPreset : 'hourAndDay', forceFit : true, columns : [ { field : 'name', text : 'Hairdressers', width : 100 }, { type : 'widget', width : 120, text : 'Availability', align : 'center', widgets : [{ type : 'button', text : 'Show', onClick : ({ source }) => { let availability; const resourceRecord = source.cellInfo.record; switch (resourceRecord.name) { case 'Benjamin': availability = [ { resourceRecord, name : 'Available ($40/h)', startDate : new Date(2022, 4, 15, 10), endDate : new Date(2022, 4, 15, 13) } ]; break; case 'Bianca': availability = [ { resourceRecord, name : 'Available ($60/h)', startDate : new Date(2022, 4, 15, 11), endDate : new Date(2022, 4, 15, 13) }, { resourceRecord, name : 'Available ($50/h)', startDate : new Date(2022, 4, 15, 14), endDate : new Date(2022, 4, 15, 16) } ]; break; case 'Sebastian': availability = [ { resourceRecord, name : 'Available (10/h)', startDate : new Date(2022, 4, 15, 10), endDate : new Date(2022, 4, 15, 12) }, { resourceRecord, name : 'Available (50/h)', startDate : new Date(2022, 4, 15, 14), endDate : new Date(2022, 4, 15, 16) } ]; break; case 'Emilio': availability = [ { resourceRecord, name : 'Available (80/h)', startDate : new Date(2022, 4, 15, 10), endDate : new Date(2022, 4, 15, 14) } ]; break; } schedulerPro.highlightTimeSpans(availability); } }] } ], features : { eventDrag : { snapToResource : true }, scheduleTooltip : false, timeSpanHighlight : true }, tbar : [ { text : 'Clear highlight', onAction() { schedulerPro.unhighlightTimeSpans(); } } ], project : { resources : [ { id : 1, name : 'Benjamin' }, { id : 2, name : 'Bianca' }, { id : 3, name : 'Sebastian' }, { id : 4, name : 'Emilio' } ], events : [ { id : 1, name : 'Crew cut', startDate : '2022-05-15T14:00:00', duration : 1.5, durationUnit : 'h', iconCls : 'fa fa-cut' }, { id : 2, name : 'Dye hair', startDate : '2022-05-15T12:00:00', duration : 2, durationUnit : 'h', iconCls : 'fa fa-female' } ], assignments : [ { id : 1, event : 1, resource : 1 }, { id : 2, event : 2, resource : 3 } ] } }); schedulerPro.highlightTimeSpan({ startDate : new Date(2022, 4, 15, 11), endDate : new Date(2022, 4, 15, 16), surround : true, name : 'Away' });
This feature is disabled by default.
Versions (API docs)
Captures versions (snapshots) of the active project, including a detailed log of the changes new in each version.
const scheduler = new SchedulerPro({ enableUndoRedoKeys : true, flex : 2, project : { resources : [ { id : 1, name : 'Resource 1' }, { id : 2, name : 'Resource 2' }, { id : 3, name : 'Resource 3' } ], autoHeight : true, events : [ { id : 11, name : 'Design website', startDate : new Date(2022, 10, 7), duration : 5, resourceId : 1 }, { id : 12, name : 'Lease office space', startDate : new Date(2022, 10, 9), duration : 4, resourceId : 1 }, { id : 13, name : 'Buy coffee machine', startDate : new Date(2022, 10, 13), duration : 3, resourceId : 3 }, { id : 14, name : 'Hire designer', startDate : new Date(2022, 10, 17), duration : 3, resourceId : 2 }, { id : 15, name : 'Write design handbook', startDate : new Date(2022, 10, 27), duration : 3, resourceId : 2 } ], // dependencies : [ // { // id : 1, // fromTask : 11, // toTask : 12 // }, // { // id : 2, // fromTask : 13, // toTask : 14 // }, // { // id : 3, // fromTask : 14, // toTask : 15 // } // ], stm : { autoRecord : true } }, columns : [ { field : 'name', text : 'Name', width : 250 }, { field : 'startDate', text : 'Start date' }, { field : 'duration', text : 'Duration' } ], subGridConfigs : { locked : { width : 300 } }, features : { versions : true, dependencies : true, dependencyEdit : true }, listeners : { /** * Demonstrates overriding the default transaction description to provide more detail * about which user action initiated the transaction. In this case, we set a custom * description for transactions involving a task drag event. */ taskDrop({ taskRecords }) { this.features.versions.transactionDescription = taskRecords.length === 1 ? `Dragged task ${taskRecords[0].name}` : `Dragged ${taskRecords.length} tasks`; }, taskResizeEnd({ taskRecord }) { this.features.versions.transactionDescription = `Resized task ${taskRecord.name}`; }, afterDependencyCreateDrop() { this.features.versions.transactionDescription = `Drew a link`; } } }); const app = new Container({ appendTo : targetElement, layout : 'box', height : 600, items : { scheduler, splitter : { type : 'splitter' }, versionGrid : { type : 'versiongrid', flex : 1, emptyText : 'No versions to display', project : scheduler.project, showUnattachedTransactions : true, selectionMode : { row : true, cell : false }, features : { cellMenu : { /** * Add a button to the version row context menu. */ items : { compareButton : undefined, duplicateButton : { text : 'Duplicate', icon : 'fa fa-copy', onItem : async({ record, source : grid }) => { const result = await MessageDialog.confirm({ title : 'Duplicate Version?', message : `This will create a new project from the content of the selected version. Do you want to continue?` }); if (result === MessageDialog.yesButton) { // Sample code demonstrating cloning a saved version await scheduler.features.versions.getVersionContent(record.versionModel); const clonedProject = new ProjectModel(record.versionModel.content); scheduler.project = clonedProject; } } } } } }, dateFormat : 'M/D/YY h:mm a', tbar : { items : { saveButton : { text : 'Save Version', icon : 'fa fa-plus', listeners : { click : () => { scheduler.features.versions.saveVersion(); } } }, spacer : { text : '->' }, onlyNamedToggle : { type : 'slidetoggle', text : 'Show named versions only', listeners : { change : ({ checked }) => { app.widgetMap.versionGrid.showNamedVersionsOnly = checked; } } }, showVersionsToggle : { type : 'slidetoggle', text : 'Changes only', checked : false, listeners : { change : ({ checked }) => { app.widgetMap.versionGrid.showVersions = !checked; } } } } }, listeners : { // Handle the user asking to restore a given version restore : async({ version }) => { const result = await MessageDialog.confirm({ title : 'Restore Version?', message : `Are you sure you want to restore the selected version, replacing the current project? You will lose any unsaved changes.` }); if (result === MessageDialog.yesButton) { await gantt.features.versions.restoreVersion(version); gantt.features.baselines.disabled = true; // FIXME known issue with Undo after restoring version project.stm.resetQueue(); } } } } } }); scheduler.project.stm.enable();
This feature is disabled by default.
Importing features from sources
A feature is registered when the application imports it. When using the regular module/umd bundle, this is done automatically, as the bundle encapsulates all code inside. However, when utilizing sources or thin bundles, a feature might not be imported by default. For any feature not enabled by default, it is essential to ensure that you have imported it to be able to use it.
Example:
import SchedulerPro from 'PATH_TO_SOURCE/SchedulerPro/view/SchedulerPro.js';
import 'PATH_TO_SOURCE/SchedulerPro/feature/Baselines.js';
const SchedulerPro = new SchedulerPro({
features : {
baselines : {
// feature config
}
}
});
Contents