A provider of sorting Outgoing SequenceFlow of ExclusiveGateway in bpmn-properties-panel


#1

The diagram is as follows:

The code is as follows:

1.provider/parts/ExecutionOrderProps.js

'use strict';

var is = require('bpmn-js/lib/util/ModelUtil').is,
  isAny = require('bpmn-js/lib/features/modeling/util/ModelingUtil').isAny,
  getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
  cmdHelper = require('bpmn-js-properties-panel/lib/helper/CmdHelper'),
  elementHelper = require('bpmn-js-properties-panel/lib/helper/ElementHelper'),
  eventDefinitionHelper = require('bpmn-js-properties-panel/lib/helper/EventDefinitionHelper'),
  script = require('bpmn-js-properties-panel/lib/provider/camunda/parts/implementation/Script')('language', 'body', true);
var domQuery = require('min-dom').query,
  domClosest = require('min-dom').closest,
  domify = require('min-dom').domify,
  domClear = require('min-dom').clear,
  forEach = require('lodash/forEach');

function getSelectBox(node, id) {
  var currentTab = domClosest(node, 'div.bpp-properties-tab');
  var query = 'select[name=selectedGatewayOutgoing]' + (id ? '[id=cam-gateway-' + id + ']' : '');
  return domQuery(query, currentTab);
}

function getSelected(node, id) {
  var selectBox = getSelectBox(node, id);
  if (selectBox)
    return {
      box: selectBox,
      value: selectBox.value,
      idx: selectBox.selectedIndex,
      length: selectBox.options.length
    };
  return null;
}

function orderSelectBoxOptions(node, id, from, to) {
  var selectBox = getSelectBox(node, id);
  if (!selectBox)
    return;
  if (selectBox.selectedIndex == -1)
    return;
  if (from == to)
    return;
  var start = Math.min(from, to);
  var end = Math.max(from, to);

  var options = new Array(selectBox.options.length);
  if (from > to) {
    for (var i = 0; i < selectBox.options.length; i++) {
      if (i < start)
        options[i] = selectBox.options[i];
      else if (i == start)
        options[i] = selectBox.options[end];
      else if (i <= end)
        options[i] = selectBox.options[i - 1];
      else
        options[i] = selectBox.options[i];

    }
  } else {
    for (var i = selectBox.options.length - 1; i >= 0; i--) {
      if (i > end)
        options[i] = selectBox.options[i];
      else if (i == end)
        options[i] = selectBox.options[start];
      else if (i >= start)
        options[i] = selectBox.options[i + 1];
      else
        options[i] = selectBox.options[i];
    }
  }

  domClear(selectBox);
  forEach(options, (o) => {
    selectBox.appendChild(o);
  });
}

function orderedOutgoing(bo, from, to) {
  if (!bo)
    return;
  if (from == to)
    return;
  var start = Math.min(from, to);
  var end = Math.max(from, to);
  var outgoing = bo.outgoing;
  if (!outgoing)
    return;
  if (from > to) {
    while (end > start) {
      var tmp = outgoing[end - 1];
      outgoing[end - 1] = outgoing[end];
      outgoing[end] = tmp;
      end = end - 1;
    }
  } else {
    while (start < end) {
      var tmp = outgoing[start + 1];
      outgoing[start + 1] = outgoing[start];
      outgoing[start] = tmp;
      start = start + 1;
    }
  }
}

module.exports = function (group, element, bpmnFactory, translate, eventBus) {
  var bo = getBusinessObject(element);
  var id = "outgoing";
  var label = translate('Outgoing');
  var defaultSize = 5;
  if (!bo) {
    return;
  }

  if (!is(element, 'bpmn:ExclusiveGateway'))
    return;


  var initSelectionSize = function (selectBox, optionsLength) {
    selectBox.size = optionsLength > defaultSize ? optionsLength : defaultSize;
  };

  var createOption = function (value) {
    return '<option value="' + value + '" data-value data-name="extensionElementValue">' + value + '</option>';
  };

  group.entries.push({
    id: id,
    label: label,
    modelProperty: '',
    html: '<div class="bpp-row bpp-element-list" ' + '>' +
      '<label for="cam-gateway-' + id + '">' + label + '</label>' +
      '<div class="bpp-field-wrapper">' +
      '<select id="cam-gateway-' + id + '"' +
      'name="selectedGatewayOutgoing" ' +
      'size="' + defaultSize + '" ' +
      'data-list-entry-container >' +
      '</select>' +
      '<button class="top" ' +
      'id="cam-gateway-top-' + id + '" ' +
      'data-action="topElement" >' +
      '<span class="fa fa-angle-double-up top"></span>' +
      '</button>' +
      '<button class="up" ' +
      'id="cam-gateway-up-' + id + '" ' +
      'data-action="upElement" >' +
      '<span class="fa fa-angle-up"></span>' +
      '</button>' +
      '<button class="down" ' +
      'id="cam-gateway-down-' + id + '" ' +
      'data-action="downElement" >' +
      '<span class="fas fa-angle-down"></span>' +
      '</button>' +
      '<button class="bottom" ' +
      'id="cam-gateway-bottom-' + id + '" ' +
      'data-action="bottomElement" >' +
      '<span class="fas fa-angle-double-down"></span>' +
      '</button>' +
      '</div>' +
      '</div>',

    get: function (element, node) {

      var result = [];
      forEach(bo.outgoing, function (elem) {
        result.push({
          extensionElementValue: elem.id
        });
      });

      var selectBox = getSelectBox(node.parentNode, id);
      initSelectionSize(selectBox, result.length);

      return result;

    },

    set: function (element, values, containerElement) {

      bo = bo || getBusinessObject(element);
      var commands = [];
      var outgoing = bo.outgoing;
      if (!outgoing)
        commands.push(cmdHelper.updateBusinessObject(element, bo, {
          outgoing: outgoing
        }));
      return commands;
    },

    createListEntryTemplate: function (value, index, selectBox) {
      initSelectionSize(selectBox, selectBox.options.length + 1);
      return createOption(value.extensionElementValue);
    },


    topElement: function (element, node) {
      var box = getSelected(node, id);
      if (!box)
        return false;
      if (box.idx <= 0)
        return false;
      orderSelectBoxOptions(node, id, box.idx, 0);
      orderedOutgoing(bo, box.idx, 0);
      return true;
    },

    upElement: function (element, node) {
      var box = getSelected(node, id);
      if (!box)
        return false;
      if (box.idx <= 0)
        return false;
      orderSelectBoxOptions(node, id, box.idx, box.idx - 1);
      orderedOutgoing(bo, box.idx, box.idx - 1);
      return true;
    },

    downElement: function (element, node) {
      var box = getSelected(node, id);
      if (!box)
        return false;
      if (box.idx < 0 || box.idx >= box.length - 1)
        return false;
      orderSelectBoxOptions(node, id, box.idx, box.idx + 1);
      orderedOutgoing(bo, box.idx, box.idx + 1);
      return true;
    },

    bottomElement: function (element, node) {
      var box = getSelected(node, id);
      if (!box)
        return false;
      if (box.idx < 0 || box.idx >= box.length - 1)
        return false;
      orderSelectBoxOptions(node, id, box.idx, box.length - 1);
      orderedOutgoing(bo, box.idx, box.length - 1);
      return true;
    }

  });
};

2.PropertiesProvider.js

function createGeneralTabGroups(element, bpmnFactory, elementRegistry, elementTemplates, translate, eventBus) {
  
  // ......

  var executionOrderGroup = {
    id: 'executionOrder',
    label: translate('Execution Order'),
    entries: []
  };
  executionOrderProps(executionOrderGroup, element, bpmnFactory, translate, eventBus); //The execution order of the outgoing branches of the exclusive gateway 

  var groups = [];
 // ...
  groups.push(executionOrderGroup);

  return groups;
}

3.app.cs

.bpp-element-list button.top,

.bpp-element-list button.up,

.bpp-element-list button.down,

.bpp-element-list button.bottom {

top: -23px;

border-bottom: none;

}

.bpp-element-list button.top&gt;span,

.bpp-element-list button.up&gt;span,

.bpp-element-list button.down&gt;span,

.bpp-element-list button.bottom&gt;span {

display: block;

}

.bpp-element-list button.bottom {

right: 0px;

}

.bpp-element-list button.down {

right: 23px;

}

.bpp-element-list button.up {

right: 46px;

}

.bpp-element-list button.top {

right: 69px;

}

#2

What are you trying to achieve?


#3

I want to specify the order of condition execution


#4
if(exp1){
    do somethings;
}else if(exp2){
    do somethings;
}else{
    do somethings;
}

If both exp1 and exp2 conditions are true,I need to specify the order of condition execution