What's new in Gantt v7.0.0
New themes & CSS
All products in the Bryntum suite now has new themes:
- Svalbard Light & Dark
- Stockholm Light & Dark
- Visby Light & Dark
- Material3 Light & Dark
- High Contrast Light & Dark
The new themes are based on CSS variables and are easier to customize than the old themes. The themes only change CSS variable (CSS custom properties) values, there are no custom selectors etc. in them. A single theme file has the custom values for all products.
The structural CSS for each product is separated from the theme CSS, making the theme files much smaller than before.
To for example include the "Material3 Light" theme in your app for Gantt, you need to include the following CSS files:
<!-- Structural CSS -->
<link rel="stylesheet" href="build/gantt.css">
<!-- Theme CSS -->
<link rel="stylesheet" href="build/material3-light.css">
Also note that none of the new themes applies any font-family. The demo styling does, but the themes themselves do not. Previously the Material theme pulled in Roboto.
No built-in FontAwesome Free
The themes also no longer include FontAwesome Free, so you need to include it yourself if you want to use icons. This change was made to not bloat the CSS files for apps that do not use our default icons.
This also means that we no longer re-scope FontAwesome (there are no b-fa-xx rules). Instead, use FontAwesome classes as you normally would.
There is still a version of FontAwesome Free included in the build folder of the Gantt package for your convenience. Include it in your app with something like this:
<!-- Optionally include FontAwesome Free -->
<link rel="stylesheet" href="build/fontawesome/css/fontawesome.css">
<link rel="stylesheet" href="build/fontawesome/css/solid.css">
If you chose to not include it (or your own version of FontAwesome), your app will need to override our b-icon-xx rules to show the icons you are using instead.
CSS variables
As mentioned above, the styling is now based on CSS variables (CSS custom properties). All Bryntum CSS variables are prefixed with --b- to avoid conflicts with other CSS variables in your app. For example, the background of a Panel is set using the --b-panel-background variable:
.my-custom-panel {
--b-panel-background : #ccc;
}
Available CSS variables are listed in the docs. Make sure to also check the updated customization guides.
Selector normalization
Previously we used a somewhat random mix of single words and kebab-casing for the CSS selectors (for example b-celledit, but b-grid-cell). This has been normalized to use kebab-case. For example the CellEdit features no longer adds the .b-celledit class, but instead correctly kebab cased .b-cell-edit.
This will likely affect any custom styling you have, please check your selectors.
Advanced - Loading from sources
When loading from sources, the CSS is pulled in automatically. Each imported class adds a <link> tag to the head of the document. This should not be used in production, and it might lead to some timing issues. But, it lets you create custom structural CSS files with only the components you need. We will be adding a guide on this later.
Time-phased assignments
Time-phased assignments are a special kind of resource assignments, that can be limited in time. Normal assignments lasts during their events time-span, time-phased assignments however, can have their own start/end date, separate from the event's start and end dates.
To accommodate for complex scenarios with time-phased assignments, since the 7.0.0 release, there can be more than one assignment of the same resource to a certain event. Each of those assignments can have its own start/end dates.
For example:
const project = new TimePhasedProjectModel({
resourcesData : [
{ id : 'r1', name : 'Resource1' }
],
tasksData : [
{ id : 't1', name : 'Event1', startDate : '2024-01-01' }
],
assignmentsData : [
{ id : 'a1', resource : 'r1', event : 'e1', startDate : '2024-01-01', endDate : '2024-01-04', effort : 24 },
{ id : 'a1', resource : 'r1', event : 'e1', startDate : '2024-01-07', endDate : '2024-01-10', effort : 48 }
]
})
In the example above, there are 2 time-phased assignments of the same 'Resource1' for the event 'Event1'. The 1st assignment lasts from 2024-01-01 till 2024-01-04 and the 2nd from 2024-01-07 till 2024-01-10.
Please refer to this guide for more details.
Cost calculation support
This release introduces a number of changes implementing resource cost calculations.
In order to see the changes on user interface level please use the following code:
new Gantt({
...
// will show new cost related controls in UI
showCostControls : true
});
On the data level the ResourceModel class has got some new fields and now supports new types of resources. In addition to existing resources of work type it's now possible to have material and cost resources which represent material and cost expenditures respectively.
Also resources depending on their types now can have tables of rates (for resources that are meant to be cost by a rate).
There are new cost fields added to assignment, resource, task and project models.
Please see the "Calculation of costs" for details.
New resource grid view
This release introduces a new ResourceGrid view that displays and allows editing the provided project resources.
const grid = new ResourceGrid({ project : { loadUrl : 'data/SchedulerPro/examples/view/ResourceHistogram.json', autoLoad : true }, startDate : new Date(2020, 3, 19), endDate : new Date(2020, 4, 15), appendTo : targetElement, autoHeight : true, minHeight : '20em' }); New resource editor widget
This release also adds a new ResourceEditor widget that allows editing the provided resource.
const project = new ProjectModel({ resources : [ { name : 'John Smith', defaultRateTable : 'default', rateTables : [ { id : 'default', name : 'Default', rates : [ { id : 1, startDate : '2025-01-01', standardRate : 40, standardRateEffortUnit : 'hour', perUseCost : 5 } ] }, { id : 'discount-20', name : '20% off', rates : [ { id : 2, startDate : '2025-01-01', standardRate : 32, standardRateEffortUnit : 'hour', perUseCost : 4 } ] } ] } ] }); const editor = new ResourceEditor({ resource : project.resources[0], autoClose : false }); const button = new Button({ text : '-> OPEN RESOURCE EDITOR <-', appendTo : targetElement, onAction() { editor.show(); } }); New columns on the Task Editor "Resources" tab
The TaskEditor "Resources" tab has got few new columns to support new data structure:
Quantity- displays the amount of material resource spent on the assignment.Cost- displays the assignment costRate table- displays the rate table used for the assignment
Assignment field picker now subclasses TabPanel
The assignment field picker has changed its base class from Grid to TabPanel. It now has a separate tab per each type of resource: "Work", "Material" and "Cost". And each tab contains a grid of resources of the corresponding type only.
The field picker by default displays only tabs for types of resources existing in the resource store. So existing applications won't see them unless a resource of new type gets added.
Resource utilization view
The resource utilization view has changed to adopt new types of resources as well. In addition to displaying effort the view now has two more series: cost and quantity that display resource cost and material expenditure respectively. The quantity is naturally collected for the resources of material-type only while cost can be collected for all types of resources.
By default new series are disabled so the view displays only effort values. Please use the following code to make them visible:
new ResourceUtilization({
// enable showing resource cost & quantity series too
// (in addition to resource effort)
series : {
cost : {
disabled : false
},
quantity : {
disabled : false
}
},
// extend the row height to fit all three series data
rowHeight : 45,
...
});
Besides new resource types supports the view has got two new features for editing effort values which under the hood uses time-phased assignments:
- AllocationCellEdit allows user to enter effort values of ticks
- AllocationCopyPaste allows copy/pasting effort values of ticks
The features rely on exiting ScheduleContext feature and can be configured like this:
new ResourceUtilization({
...
features : {
scheduleContext : {
// allow navigating the timeaxis cells w/ keyboard
keyNavigation : true,
// allow multi selecting the timeaxis cells
// (can be useful for copy/pasting values there)
multiSelect : true
},
// enable effort values editing
allocationCellEdit : true,
// enable effort values copy/pasting
allocationCopyPaste : true
},
...
});
Task editor
The task editor "Resources" tab has been changed to support new time-phased assignments. Each resource row can now be expanded to display and edit the resource assignments.
This user interface gets enabled automatically when a time-phased project is used but can be disabled explicitly if needed like this:
new Gantt({
...
features : {
taskEdit : {
items : {
resourcesTab : {
// prevent time-phased assignments grid showing
showTimePhasedAssignmentsGrid : false
}
}
}
}
});
New TaskModel class actualEffort field
TaskModel class has got new actualEffort field. The field displays the amount of effort that has already been done by resources assigned to the task.
For summary tasks the field value is calculated as the sum of child actual effort values. For regular tasks with assignments the value is calculated as the sum of assignments actual efforts. In other cases the field value is calculated as the task effort multiplied by its % complete.
The field is calculated and is not meant to be edited manually.
New Baseline model effort field
Baseline class has got three new fields representing effort value: effort, effortUnit and fullEffort,
The fields is going to be filled when taking a task snapshot.
New BaselineEffortColumn column
New BaselineEffortColumn column has been added to the Gantt to display the above mentioned baseline effort values.
Please use the following code to add the column:
new Gantt({
...
columns : [
{
type : 'baselineeffort'
},
...
]
})
By default the column displays the 0-index baseline effort. To change that please use the following syntax:
new Gantt({
...
columns : [
{
type : 'baselineeffort',
// display the baseline with index 3
field : 'baselines[3].fullEffort'
},
...
]
})
Please see the column in action in the updated baselines demo.
New ActualEffortColumn column
New ActualEffortColumn column has been added to the Gantt to display the above mentioned actualEffort values.
Please use the following code to add the column:
new Gantt({
...
columns : [
{
type : 'actualeffort'
},
...
]
})
Please see the column in action in the updated baselines demo.
Conflicts postponing logic changes
The conflicts postponing logic has been changed. It used to cover only cases when a task own constraint contradicted with its dependency but now it covers all scheduling conflicts.