Hi Bryntum team,
I’m using STM (StateTrackingManager) in Gantt with autoRecord: true to validate edits against custom authorization logic. My goal is:
When a user edits a task or dependency, I check if they have permission.
If unauthorized, I want to cancel/undo the entire transaction and show an error popup.
Here’s a simplified snippet of my STM config:
stm: {
autoRecord: true,
listeners: {
recordingStop: ({ stm, transaction }) => {
this.unauthorizedTasks = [];
if (this.readOnlyTagVisible == false && !this.isCurrentUserAdmin) {
let invalid = false;
transaction.queue.forEach((queueItem: any) => {
// Case 1: Task updates
if (queueItem.$$name === "EventUpdateAction" && queueItem.model) {
const editorIds = [
...(queueItem.model?.editor || []),
...(queueItem.model?.inheritedEditor || [])
];
if (!this.isUserAuthorized(editorIds)) {
invalid = true;
this.unauthorizedTasks.push({
name: queueItem.model?.name,
wbs: queueItem.model?.wbsValue?._value,
sequenceNumber: queueItem.model?.sequenceNumber
});
}
}
// Case 2: Dependency changes
else if (
queueItem.store._id === "dependencies" &&
(queueItem.$$name === "AddAction" || queueItem.$$name === "RemoveAction") &&
queueItem.modelList
) {
const fromEvent = queueItem.modelList[0]?.fromEvent;
const toEvent = queueItem.modelList[0]?.toEvent;
const fromEditorIds = [
...(fromEvent?.editor || []),
...(fromEvent?.inheritedEditor || [])
];
const toEditorIds = [
...(toEvent?.editor || []),
...(toEvent?.inheritedEditor || [])
];
if (fromEvent && !this.isUserAuthorized(fromEditorIds)) {
invalid = true;
this.unauthorizedTasks.push({
name: fromEvent.name,
wbs: fromEvent.wbsValue?._value,
sequenceNumber: fromEvent.sequenceNumber
});
}
if (toEvent && !this.isUserAuthorized(toEditorIds)) {
invalid = true;
this.unauthorizedTasks.push({
name: toEvent.name,
wbs: toEvent.wbsValue?._value,
sequenceNumber: toEvent.sequenceNumber
});
}
}
});
if (invalid) {
stm.undo(); // rollback
this.isUnauthorizedEditVisible = true; // show popup
console.warn("Invalid transaction, undoing...");
}
}
}
}
}
Problem I’m facing:
The first time unauthorized changes are made, stm.undo() works correctly.
But on the second attempt, the changes are still applied in the Gantt and stm.undo() does not revert them.
It seems like after the first undo, STM does not always record the next invalid transaction, so there’s nothing to undo.
Question:
Is there a recommended way to cancel/rollback an STM transaction before it’s committed (so changes are never reflected in the Gantt)?
If not, how should I correctly use STM to ensure multiple consecutive unauthorized edits are always undone?
Thanks in advance!