-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: default user tasks with
zeebe:UserTask
extension element
Related to camunda/camunda-modeler#4648
- Loading branch information
Showing
5 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { createElement } from "../util/ElementUtil"; | ||
import { getZeebeUserTaskElement } from "./util/ZeebeUserTaskUtil"; | ||
import { getBusinessObject, is } from "bpmn-js/lib/util/ModelUtil"; | ||
import CommandInterceptor from "diagram-js/lib/command/CommandInterceptor"; | ||
|
||
const HIGH_PRIORITY = 5000; | ||
|
||
/** | ||
* Zeebe BPMN specific behavior for creating user tasks. | ||
*/ | ||
export default class CreateZeebeUserTaskBehavior extends CommandInterceptor { | ||
constructor(bpmnFactory, eventBus, modeling) { | ||
super(eventBus); | ||
|
||
/** | ||
* Add zeebe:userTask extension element when creating bpmn:UserTask. | ||
*/ | ||
this.postExecuted( | ||
"shape.create", | ||
HIGH_PRIORITY, | ||
function (context) { | ||
const { shape } = context; | ||
|
||
if (!is(shape, "bpmn:UserTask")) { | ||
return; | ||
} | ||
|
||
const businessObject = getBusinessObject(shape); | ||
|
||
// Use getZeebeUserTaskElement to check if zeebe:userTask already exists | ||
let userTaskElement = getZeebeUserTaskElement(businessObject); | ||
|
||
if (!userTaskElement) { | ||
let extensionElements = businessObject.get("extensionElements"); | ||
|
||
if (!extensionElements) { | ||
extensionElements = createElement( | ||
"bpmn:ExtensionElements", | ||
{ | ||
values: [], | ||
}, | ||
businessObject, | ||
bpmnFactory | ||
); | ||
|
||
modeling.updateProperties(shape, { extensionElements }); | ||
} | ||
|
||
userTaskElement = createElement( | ||
"zeebe:UserTask", | ||
{}, | ||
extensionElements, | ||
bpmnFactory | ||
); | ||
|
||
modeling.updateModdleProperties(shape, extensionElements, { | ||
values: [...(extensionElements.values || []), userTaskElement], | ||
}); | ||
} | ||
}, | ||
true | ||
); | ||
} | ||
} | ||
|
||
CreateZeebeUserTaskBehavior.$inject = ["bpmnFactory", "eventBus", "modeling"]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { getExtensionElementsList } from "../../util/ExtensionElementsUtil"; | ||
|
||
import { getBusinessObject, is } from "bpmn-js/lib/util/ModelUtil"; | ||
|
||
/** | ||
* Get all zeebe:userTask elements of an element. | ||
* | ||
* @param {djs.model.Base|ModdleElement} element | ||
* | ||
* @returns {Array<ModdleElement>} | ||
*/ | ||
export function getZeebeUserTaskElements(element) { | ||
const businessObject = getBusinessObject(element); | ||
return getExtensionElementsList(businessObject, 'zeebe:UserTask'); | ||
} | ||
|
||
/** | ||
* Get the first zeebe:userTask element of an element. | ||
* | ||
* @param {djs.model.Base|ModdleElement} element | ||
* | ||
* @returns {ModdleElement|null} | ||
*/ | ||
export function getZeebeUserTaskElement(element) { | ||
const userTaskElements = getZeebeUserTaskElements(element); | ||
return userTaskElements[0] || null; | ||
} | ||
|
||
/** | ||
* Check whether a zeebe:userTask extension element is set on an element. | ||
* | ||
* @param {djs.model.Base|ModdleElement} element | ||
* | ||
* @returns {boolean} | ||
*/ | ||
export function hasZeebeUserTaskExtension(element) { | ||
if (!is(element, "bpmn:UserTask")) { | ||
return false; | ||
} | ||
|
||
return !!getZeebeUserTaskElement(element); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import { bootstrapCamundaCloudModeler, inject } from "test/TestHelper"; | ||
|
||
import { find } from "min-dash"; | ||
|
||
import { | ||
getZeebeUserTaskElement, | ||
getZeebeUserTaskElements, | ||
} from "../../lib/camunda-cloud/util/ZeebeUserTaskUtil"; | ||
|
||
import { getBusinessObject, is } from "bpmn-js/lib/util/ModelUtil"; | ||
|
||
import emptyProcessDiagramXML from "./process-empty.bpmn"; | ||
import userTasksXML from "./process-user-tasks.bpmn"; | ||
|
||
describe.only("camunda-cloud/features/modeling - CreateZeebeUserTaskBehavior", function () { | ||
describe("populate zeebe:userTask", function () { | ||
describe("when creating new shapes", function () { | ||
beforeEach(bootstrapCamundaCloudModeler(emptyProcessDiagramXML)); | ||
|
||
it("should execute when creating bpmn:UserTask", inject(function ( | ||
canvas, | ||
modeling | ||
) { | ||
// given | ||
const rootElement = canvas.getRootElement(); | ||
|
||
// when | ||
const newShape = modeling.createShape( | ||
{ type: "bpmn:UserTask" }, | ||
{ x: 100, y: 100 }, | ||
rootElement | ||
); | ||
|
||
// then | ||
const businessObject = getBusinessObject(newShape), | ||
extensionElements = businessObject.get("extensionElements"), | ||
zeebeUserTaskExtension = getZeebeUserTaskElement(newShape); | ||
|
||
expect(zeebeUserTaskExtension).to.exist; | ||
expect(extensionElements).to.exist; | ||
expect(zeebeUserTaskExtension.$parent).to.equal(extensionElements); | ||
})); | ||
|
||
it("should not execute when creating bpmn:Task", inject(function ( | ||
canvas, | ||
modeling | ||
) { | ||
// given | ||
const rootElement = canvas.getRootElement(); | ||
|
||
// when | ||
const newShape = modeling.createShape( | ||
{ type: "bpmn:Task" }, | ||
{ x: 100, y: 100 }, | ||
rootElement | ||
); | ||
|
||
// then | ||
const zeebeUserTaskExtension = getZeebeUserTaskElement(newShape); | ||
|
||
expect(zeebeUserTaskExtension).not.to.exist; | ||
})); | ||
}); | ||
|
||
describe("when copying bpmn:UserTask", function () { | ||
beforeEach(bootstrapCamundaCloudModeler(userTasksXML)); | ||
|
||
it("should re-use existing extensionElement", inject(function ( | ||
canvas, | ||
copyPaste, | ||
elementRegistry | ||
) { | ||
// given | ||
const rootElement = canvas.getRootElement(); | ||
const userTask = elementRegistry.get("withZeebeUserTask"); | ||
|
||
// when | ||
copyPaste.copy(userTask); | ||
|
||
const elements = copyPaste.paste({ | ||
element: rootElement, | ||
point: { | ||
x: 1000, | ||
y: 1000, | ||
}, | ||
}); | ||
|
||
// then | ||
const pastedUserTask = find(elements, (element) => | ||
is(element, "bpmn:UserTask") | ||
); | ||
|
||
const businessObject = getBusinessObject(pastedUserTask), | ||
extensionElements = businessObject.get("extensionElements"), | ||
zeebeUserTaskExtensions = getZeebeUserTaskElements(pastedUserTask); | ||
|
||
expect(zeebeUserTaskExtensions).to.exist; | ||
expect(extensionElements).to.exist; | ||
expect(zeebeUserTaskExtensions.length).to.equal(1); | ||
expect(zeebeUserTaskExtensions[0].$parent).to.equal(extensionElements); | ||
})); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters