How to add a second label to a connection

Hi everyone,

I am developing an extension of bpmn-js to allow the management of temporal attributes.
In such an extension, each bpmn:SequenceFlow has an extended property ‘duration’ composed of two fields: ‘min’ and ‘max’. ‘min’ and ‘max’ can be edited in a tab of the property panel.

I am trying to add a read-only label ‘[min, max]’ beside the ‘name’ label of a SequenceFlow.
Such a label mustn’t be edited directly, but it should be updated automatically every time min/max are updated in the property panel.

I can add a method that maintains the update string ‘[min, max]’ as an attribute of SequenceFlow if this simplifies the setting.

If I use ‘modeling.createLabel()’ passing the businessObject of the considered connection,
the resulting label is a label associated with the ‘name’ field of the businessObject, and it is editable.
It seems that:

  1. it is not possible to make it read-only
  2. it is not possible to associate it with another field of businessObject

Question
Is there a clean way (clean=foreseen by the system architecture) to implement the above kind of label?

I have tried to customize some modules that manage Labels, but I wasn’t able to build a working mechanism.
I am not able to understand the following:

  • which files I have to customize without losing the standard feature of ‘name’ label management.
  • how to integrate them
  • the creation of the label should be triggered when event ‘connection.create’ or ‘connection.add’ occur,
    but it seems that CommandInterceptor can manage only ‘connection.create’.
    So, when I load an XML diagram, labels are not created.

Any hints/roadmap/link to document is very appreciated.

Roberto

It looks like everybody at the University of Verona is into temporal constraints :blush:
Francesca Zerbato from your university published many great papers on temporal constraints. She covers min/max duration constraints in detail.

I had the same idea as Francesca and implemented a few temporal constraints with bpmn.js.

I would be interested in why you are trying to use min/max durations on flows? Why not activities?

Hi Borut,
I am one of the coauthors of the papers you cited as Francesca’s.

We published TimeAwareBPMN (univr.di / TimeAwareBPMN · GitLab), where some temporal constraints are represented and, more important, verified w.r.t. the controllability concept.

In the current version of TimeAwareBPMN, I’m not too fond of how some temporal attributes are managed and published.
I am working on version 2.0, where (I hope) the management will be clearer, and some other features will be available (management of temporal sub-processes).

:slight_smile:

I forgot to add to the initial post that I had also considered the possibility of decorating a connection with a text as suggested in How to put label in a custom element - #2 by Niklas_Kiefer, but it didn’t work.
In particular, I tested the following function to draw a custom connection

this.drawCustomConnection = function( visual, element ) {
	let colorFrame = (TemporalAttributesValidator.isRelativeConstraintValid(element)) ? COLOR_GREEN : COLOR_RED;
	let minD = Number(element.businessObject.minDuration || '');
	let maxD = Number(element.businessObject.maxDuration || Infinity);
	let propositionalLabel = element.businessObject.propositionalLabel || '';

	let attrs = computeStyle(attrs, {
			stroke: colorFrame,
			strokeWidth: 2,
			strokeDasharray: '20,5,5,5,5,5',
			strokeLinecap: 'square',
			// strokeLinecap:'round',
			markerEnd: marker('sequenceflow-end', 'white', colorFrame),
	});
 	// add the line representing the connection
	let connectionSVGElement = svgAppend(visual, createLine(element.waypoints, attrs));

	//add a 'label' to show the temporal range '[minD, maxD]', propositionalLabel
	// The next code adds the text,
	// but it is displayed only when the connection is being created
	// once it is created it disappears
	// https://forum.bpmn.io/t/how-to-put-label-in-a-custom-element/3287/2
	let {x :refX, y: refY} = getExternalLabelMid(element);
	let text = textRenderer.createText("["+minD + ", " + maxD+"]"); // (label || '', options);
	svgAttr(text, {
		transform: "translate(" + refX + ", " + refY + ")"
	});
	svgAppend(connectionSVGElement, text);

	return connectionSVGElement;
}

As noted in the source comment, the ‘label’ is created and shown only a connection is in editing mode (initially when it is created using the mouse to connect the source element to the destination one, then when it is modified by moving it or adding a point to it).
Then, the ‘label’ disappears.

Moreover, I would prefer to work at the bpmn-js level: decorate an element with a label containing a constant/dynamic text.

I’ve read your articles too! I apologize for not realizing your Roberto account here, is from the co-author of the TimeAwareBPMN-js paper :blush:

Great work on TimeAwareBPMN-js. I’m looking forward to version 2.

Found the reason of the problem!

With diagram-js 11.3.0 and bpmn-js v11.0.5, the preview feature does not allow attaching any SVG element different from polyLine to a bpmn-js connection.

In details

The preview feature allows one to see how a connection is rendered during the creation or modification.
All SVG elements specified in the method CustomRenderer.prototype.drawConnection() are rendered correctly.
Let us assume that CustomRenderer.prototype.drawConnection() adds two SVG polylines and one SVG text.

Once, the user releases the mouse, the system (I was not able to catch which method) sets the following SVG elements inside the main SVG element of the HTML document:

  1. an SVG g element with CSS djs-element djs-connection corresponding to the considered connection. (I call this g main).
  2. inside to the main g, another g element containing all the SVG element created in CustomRenderer.prototype.drawConnection(). This last g is not rendered because it has CSS djs-connection djs-visual that prevents the rendering.
  3. inside to the main g, all the SVG polyline element present in g element of point 2.

Therefore, the SVG text created in CustomRenderer.prototype.drawConnection() is present, but it is not copied in the main g and, therefore, not rendered.

Roberto

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.