UNPKG

bpmn-js-element-templates

Version:
1,859 lines (1,745 loc) 2.71 MB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.BpmnJSElementTemplates = {})); })(this, (function (exports) { 'use strict'; /** * @typedef { { * [key: string]: string; * } } TranslateReplacements */ /** * A simple translation stub to be used for multi-language support * in diagrams. Can be easily replaced with a more sophisticated * solution. * * @example * * ```javascript * // use it inside any diagram component by injecting `translate`. * * function MyService(translate) { * alert(translate('HELLO {you}', { you: 'You!' })); * } * ``` * * @param {string} template to interpolate * @param {TranslateReplacements} [replacements] a map with substitutes * * @return {string} the translated string */ function translate(template, replacements) { replacements = replacements || {}; return template.replace(/{([^}]+)}/g, function (_, key) { return replacements[key] || '{' + key + '}'; }); } /** * @type { import('didi').ModuleDeclaration } */ var translateModule = { translate: ['value', translate] }; /** * Flatten array, one level deep. * * @template T * * @param {T[][]} arr * * @return {T[]} */ function flatten$1(arr) { return Array.prototype.concat.apply([], arr); } const nativeToString = Object.prototype.toString; const nativeHasOwnProperty = Object.prototype.hasOwnProperty; function isUndefined$1(obj) { return obj === undefined; } function isDefined(obj) { return obj !== undefined; } function isNil(obj) { return obj == null; } function isArray(obj) { return nativeToString.call(obj) === '[object Array]'; } function isObject(obj) { return nativeToString.call(obj) === '[object Object]'; } function isNumber(obj) { return nativeToString.call(obj) === '[object Number]'; } /** * @param {any} obj * * @return {boolean} */ function isFunction(obj) { const tag = nativeToString.call(obj); return tag === '[object Function]' || tag === '[object AsyncFunction]' || tag === '[object GeneratorFunction]' || tag === '[object AsyncGeneratorFunction]' || tag === '[object Proxy]'; } function isString(obj) { return nativeToString.call(obj) === '[object String]'; } /** * Ensure collection is an array. * * @param {Object} obj */ function ensureArray(obj) { if (isArray(obj)) { return; } throw new Error('must supply array'); } /** * Return true, if target owns a property with the given key. * * @param {Object} target * @param {String} key * * @return {Boolean} */ function has(target, key) { return nativeHasOwnProperty.call(target, key); } /** * @template T * @typedef { ( * ((e: T) => boolean) | * ((e: T, idx: number) => boolean) | * ((e: T, key: string) => boolean) | * string | * number * ) } Matcher */ /** * @template T * @template U * * @typedef { ( * ((e: T) => U) | string | number * ) } Extractor */ /** * @template T * @typedef { (val: T, key: any) => boolean } MatchFn */ /** * @template T * @typedef { T[] } ArrayCollection */ /** * @template T * @typedef { { [key: string]: T } } StringKeyValueCollection */ /** * @template T * @typedef { { [key: number]: T } } NumberKeyValueCollection */ /** * @template T * @typedef { StringKeyValueCollection<T> | NumberKeyValueCollection<T> } KeyValueCollection */ /** * @template T * @typedef { KeyValueCollection<T> | ArrayCollection<T> } Collection */ /** * Find element in collection. * * @template T * @param {Collection<T>} collection * @param {Matcher<T>} matcher * * @return {Object} */ function find$1(collection, matcher) { const matchFn = toMatcher(matcher); let match; forEach(collection, function (val, key) { if (matchFn(val, key)) { match = val; return false; } }); return match; } /** * Find element index in collection. * * @template T * @param {Collection<T>} collection * @param {Matcher<T>} matcher * * @return {number} */ function findIndex$1(collection, matcher) { const matchFn = toMatcher(matcher); let idx = isArray(collection) ? -1 : undefined; forEach(collection, function (val, key) { if (matchFn(val, key)) { idx = key; return false; } }); return idx; } /** * Filter elements in collection. * * @template T * @param {Collection<T>} collection * @param {Matcher<T>} matcher * * @return {T[]} result */ function filter(collection, matcher) { const matchFn = toMatcher(matcher); let result = []; forEach(collection, function (val, key) { if (matchFn(val, key)) { result.push(val); } }); return result; } /** * Iterate over collection; returning something * (non-undefined) will stop iteration. * * @template T * @param {Collection<T>} collection * @param { ((item: T, idx: number) => (boolean|void)) | ((item: T, key: string) => (boolean|void)) } iterator * * @return {T} return result that stopped the iteration */ function forEach(collection, iterator) { let val, result; if (isUndefined$1(collection)) { return; } const convertKey = isArray(collection) ? toNum : identity; for (let key in collection) { if (has(collection, key)) { val = collection[key]; result = iterator(val, convertKey(key)); if (result === false) { return val; } } } } /** * Return collection without element. * * @template T * @param {ArrayCollection<T>} arr * @param {Matcher<T>} matcher * * @return {T[]} */ function without(arr, matcher) { if (isUndefined$1(arr)) { return []; } ensureArray(arr); const matchFn = toMatcher(matcher); return arr.filter(function (el, idx) { return !matchFn(el, idx); }); } /** * Reduce collection, returning a single result. * * @template T * @template V * * @param {Collection<T>} collection * @param {(result: V, entry: T, index: any) => V} iterator * @param {V} result * * @return {V} result returned from last iterator */ function reduce(collection, iterator, result) { forEach(collection, function (value, idx) { result = iterator(result, value, idx); }); return result; } /** * Return true if every element in the collection * matches the criteria. * * @param {Object|Array} collection * @param {Function} matcher * * @return {Boolean} */ function every(collection, matcher) { return !!reduce(collection, function (matches, val, key) { return matches && matcher(val, key); }, true); } /** * Return true if some elements in the collection * match the criteria. * * @param {Object|Array} collection * @param {Function} matcher * * @return {Boolean} */ function some(collection, matcher) { return !!find$1(collection, matcher); } /** * Transform a collection into another collection * by piping each member through the given fn. * * @param {Object|Array} collection * @param {Function} fn * * @return {Array} transformed collection */ function map$1(collection, fn) { let result = []; forEach(collection, function (val, key) { result.push(fn(val, key)); }); return result; } /** * Get the collections keys. * * @param {Object|Array} collection * * @return {Array} */ function keys(collection) { return collection && Object.keys(collection) || []; } /** * Shorthand for `keys(o).length`. * * @param {Object|Array} collection * * @return {Number} */ function size(collection) { return keys(collection).length; } /** * Get the values in the collection. * * @param {Object|Array} collection * * @return {Array} */ function values(collection) { return map$1(collection, val => val); } /** * Group collection members by attribute. * * @param {Object|Array} collection * @param {Extractor} extractor * * @return {Object} map with { attrValue => [ a, b, c ] } */ function groupBy(collection, extractor, grouped = {}) { extractor = toExtractor(extractor); forEach(collection, function (val) { let discriminator = extractor(val) || '_'; let group = grouped[discriminator]; if (!group) { group = grouped[discriminator] = []; } group.push(val); }); return grouped; } function uniqueBy(extractor, ...collections) { extractor = toExtractor(extractor); let grouped = {}; forEach(collections, c => groupBy(c, extractor, grouped)); let result = map$1(grouped, function (val, key) { return val[0]; }); return result; } const unionBy = uniqueBy; /** * Sort collection by criteria. * * @template T * * @param {Collection<T>} collection * @param {Extractor<T, number | string>} extractor * * @return {Array} */ function sortBy(collection, extractor) { extractor = toExtractor(extractor); let sorted = []; forEach(collection, function (value, key) { let disc = extractor(value, key); let entry = { d: disc, v: value }; for (var idx = 0; idx < sorted.length; idx++) { let { d } = sorted[idx]; if (disc < d) { sorted.splice(idx, 0, entry); return; } } // not inserted, append (!) sorted.push(entry); }); return map$1(sorted, e => e.v); } /** * Create an object pattern matcher. * * @example * * ```javascript * const matcher = matchPattern({ id: 1 }); * * let element = find(elements, matcher); * ``` * * @template T * * @param {T} pattern * * @return { (el: any) => boolean } matcherFn */ function matchPattern(pattern) { return function (el) { return every(pattern, function (val, key) { return el[key] === val; }); }; } /** * @param {string | ((e: any) => any) } extractor * * @return { (e: any) => any } */ function toExtractor(extractor) { /** * @satisfies { (e: any) => any } */ return isFunction(extractor) ? extractor : e => { // @ts-ignore: just works return e[extractor]; }; } /** * @template T * @param {Matcher<T>} matcher * * @return {MatchFn<T>} */ function toMatcher(matcher) { return isFunction(matcher) ? matcher : e => { return e === matcher; }; } function identity(arg) { return arg; } function toNum(arg) { return Number(arg); } /* global setTimeout clearTimeout */ /** * @typedef { { * (...args: any[]): any; * flush: () => void; * cancel: () => void; * } } DebouncedFunction */ /** * Debounce fn, calling it only once if the given time * elapsed between calls. * * Lodash-style the function exposes methods to `#clear` * and `#flush` to control internal behavior. * * @param {Function} fn * @param {Number} timeout * * @return {DebouncedFunction} debounced function */ function debounce(fn, timeout) { let timer; let lastArgs; let lastThis; let lastNow; function fire(force) { let now = Date.now(); let scheduledDiff = force ? 0 : lastNow + timeout - now; if (scheduledDiff > 0) { return schedule(scheduledDiff); } fn.apply(lastThis, lastArgs); clear(); } function schedule(timeout) { timer = setTimeout(fire, timeout); } function clear() { if (timer) { clearTimeout(timer); } timer = lastNow = lastArgs = lastThis = undefined; } function flush() { if (timer) { fire(true); } clear(); } /** * @type { DebouncedFunction } */ function callback(...args) { lastNow = Date.now(); lastArgs = args; lastThis = this; // ensure an execution is scheduled if (!timer) { schedule(timeout); } } callback.flush = flush; callback.cancel = clear; return callback; } /** * Throttle fn, calling at most once * in the given interval. * * @param {Function} fn * @param {Number} interval * * @return {Function} throttled function */ function throttle(fn, interval) { let throttling = false; return function (...args) { if (throttling) { return; } fn(...args); throttling = true; setTimeout(() => { throttling = false; }, interval); }; } /** * Bind function against target <this>. * * @param {Function} fn * @param {Object} target * * @return {Function} bound function */ function bind(fn, target) { return fn.bind(target); } /** * Convenience wrapper for `Object.assign`. * * @param {Object} target * @param {...Object} others * * @return {Object} the target */ function assign(target, ...others) { return Object.assign(target, ...others); } /** * Sets a nested property of a given object to the specified value. * * This mutates the object and returns it. * * @template T * * @param {T} target The target of the set operation. * @param {(string|number)[]} path The path to the nested value. * @param {any} value The value to set. * * @return {T} */ function set(target, path, value) { let currentTarget = target; forEach(path, function (key, idx) { if (typeof key !== 'number' && typeof key !== 'string') { throw new Error('illegal key type: ' + typeof key + '. Key should be of type number or string.'); } if (key === 'constructor') { throw new Error('illegal key: constructor'); } if (key === '__proto__') { throw new Error('illegal key: __proto__'); } let nextKey = path[idx + 1]; let nextTarget = currentTarget[key]; if (isDefined(nextKey) && isNil(nextTarget)) { nextTarget = currentTarget[key] = isNaN(+nextKey) ? {} : []; } if (isUndefined$1(nextKey)) { if (isUndefined$1(value)) { delete currentTarget[key]; } else { currentTarget[key] = value; } } else { currentTarget = nextTarget; } }); return target; } /** * Gets a nested property of a given object. * * @param {Object} target The target of the get operation. * @param {(string|number)[]} path The path to the nested value. * @param {any} [defaultValue] The value to return if no value exists. * * @return {any} */ function get(target, path, defaultValue) { let currentTarget = target; forEach(path, function (key) { // accessing nil property yields <undefined> if (isNil(currentTarget)) { currentTarget = undefined; return false; } currentTarget = currentTarget[key]; }); return isUndefined$1(currentTarget) ? defaultValue : currentTarget; } /** * Pick properties from the given target. * * @template T * @template {any[]} V * * @param {T} target * @param {V} properties * * @return Pick<T, V> */ function pick(target, properties) { let result = {}; let obj = Object(target); forEach(properties, function (prop) { if (prop in obj) { result[prop] = target[prop]; } }); return result; } /** * Pick all target properties, excluding the given ones. * * @template T * @template {any[]} V * * @param {T} target * @param {V} properties * * @return {Omit<T, V>} target */ function omit(target, properties) { let result = {}; let obj = Object(target); forEach(obj, function (prop, key) { if (properties.indexOf(key) === -1) { result[key] = prop; } }); return result; } /** * Recursively merge `...sources` into given target. * * Does support merging objects; does not support merging arrays. * * @param {Object} target * @param {...Object} sources * * @return {Object} the target */ function merge(target, ...sources) { if (!sources.length) { return target; } forEach(sources, function (source) { // skip non-obj sources, i.e. null if (!source || !isObject(source)) { return; } forEach(source, function (sourceVal, key) { if (key === '__proto__') { return; } let targetVal = target[key]; if (isObject(sourceVal)) { if (!isObject(targetVal)) { // override target[key] with object targetVal = {}; } target[key] = merge(targetVal, sourceVal); } else { target[key] = sourceVal; } }); }); return target; } var index_esm = /*#__PURE__*/Object.freeze({ __proto__: null, assign: assign, bind: bind, debounce: debounce, ensureArray: ensureArray, every: every, filter: filter, find: find$1, findIndex: findIndex$1, flatten: flatten$1, forEach: forEach, get: get, groupBy: groupBy, has: has, isArray: isArray, isDefined: isDefined, isFunction: isFunction, isNil: isNil, isNumber: isNumber, isObject: isObject, isString: isString, isUndefined: isUndefined$1, keys: keys, map: map$1, matchPattern: matchPattern, merge: merge, omit: omit, pick: pick, reduce: reduce, set: set, size: size, some: some, sortBy: sortBy, throttle: throttle, unionBy: unionBy, uniqueBy: uniqueBy, values: values, without: without }); /** * @typedef { import('../model/Types').Element } Element * @typedef { import('../model/Types').ModdleElement } ModdleElement */ /** * Is an element of the given BPMN type? * * @param {Element|ModdleElement} element * @param {string} type * * @return {boolean} */ function is$4(element, type) { var bo = getBusinessObject$1(element); return bo && typeof bo.$instanceOf === 'function' && bo.$instanceOf(type); } /** * Return true if element has any of the given types. * * @param {Element|ModdleElement} element * @param {string[]} types * * @return {boolean} */ function isAny(element, types) { return some(types, function (t) { return is$4(element, t); }); } /** * Return the business object for a given element. * * @param {Element|ModdleElement} element * * @return {ModdleElement} */ function getBusinessObject$1(element) { return element && element.businessObject || element; } /** * Return the di object for a given element. * * @param {Element} element * * @return {ModdleElement} */ function getDi(element) { return element && element.di; } /** * @param {Element} element * * @return {boolean} */ function isEventSubProcess(element) { return element && !!getBusinessObject$1(element).triggeredByEvent; } const PROPERTY_TYPE$1 = 'property'; const ZEBBE_PROPERTY_TYPE = 'zeebe:property'; const ZEBBE_INPUT_TYPE = 'zeebe:input'; const ZEEBE_OUTPUT_TYPE = 'zeebe:output'; const ZEEBE_PROPERTY_TYPE = 'zeebe:property'; const ZEEBE_TASK_DEFINITION_TYPE_TYPE = 'zeebe:taskDefinition:type'; const ZEEBE_TASK_DEFINITION = 'zeebe:taskDefinition'; const ZEEBE_TASK_HEADER_TYPE = 'zeebe:taskHeader'; const MESSAGE_PROPERTY_TYPE = 'bpmn:Message#property'; const MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE = 'bpmn:Message#zeebe:subscription#property'; const ZEEBE_CALLED_ELEMENT = 'zeebe:calledElement'; const EXTENSION_BINDING_TYPES$1 = [MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE, ZEBBE_INPUT_TYPE, ZEEBE_OUTPUT_TYPE, ZEEBE_PROPERTY_TYPE, ZEEBE_TASK_DEFINITION_TYPE_TYPE, ZEEBE_TASK_DEFINITION, ZEEBE_TASK_HEADER_TYPE, ZEEBE_CALLED_ELEMENT]; const TASK_DEFINITION_TYPES = [ZEEBE_TASK_DEFINITION_TYPE_TYPE, ZEEBE_TASK_DEFINITION]; const IO_BINDING_TYPES$1 = [ZEBBE_INPUT_TYPE, ZEEBE_OUTPUT_TYPE]; const MESSAGE_BINDING_TYPES = [MESSAGE_PROPERTY_TYPE, MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE]; const PROPERTY_BINDING_TYPES = [PROPERTY_TYPE$1, MESSAGE_PROPERTY_TYPE]; function getTaskDefinitionPropertyName(binding) { return binding.type === ZEEBE_TASK_DEFINITION_TYPE_TYPE ? 'type' : binding.property; } // Unique ID creation requires a high quality random # generator. In the browser we therefore // require the crypto API and do not support built-in fallback to lower quality random number // generators (like Math.random()). let getRandomValues; const rnds8 = new Uint8Array(16); function rng() { // lazy load so that environments that need to polyfill have a chance to do so if (!getRandomValues) { // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto); if (!getRandomValues) { throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported'); } } return getRandomValues(rnds8); } /** * Convert array of 16 byte values to UUID string format of the form: * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ const byteToHex = []; for (let i = 0; i < 256; ++i) { byteToHex.push((i + 0x100).toString(16).slice(1)); } function unsafeStringify(arr, offset = 0) { // Note: Be careful editing this code! It's been tuned for performance // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]; } const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto); var native = { randomUUID }; function v4(options, buf, offset) { if (native.randomUUID && !buf && !options) { return native.randomUUID(); } options = options || {}; const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` rnds[6] = rnds[6] & 0x0f | 0x40; rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided if (buf) { offset = offset || 0; for (let i = 0; i < 16; ++i) { buf[offset + i] = rnds[i]; } return buf; } return unsafeStringify(rnds); } /** * The BPMN 2.0 extension attribute name under * which the element template ID is stored. * * @type {String} */ const TEMPLATE_ID_ATTR$1 = 'zeebe:modelerTemplate'; /** * The BPMN 2.0 extension attribute name under * which the element template version is stored. * * @type {String} */ const TEMPLATE_VERSION_ATTR$1 = 'zeebe:modelerTemplateVersion'; /** * Get template id for a given diagram element. * * @param {djs.model.Base} element * * @return {String} */ function getTemplateId$1(element) { const businessObject = getBusinessObject$1(element); if (businessObject) { return businessObject.get(TEMPLATE_ID_ATTR$1); } } /** * Get template version for a given diagram element. * * @param {djs.model.Base} element * * @return {String} */ function getTemplateVersion$1(element) { const businessObject = getBusinessObject$1(element); if (businessObject) { return businessObject.get(TEMPLATE_VERSION_ATTR$1); } } /** * Find extension with given type in * BPMN element, diagram element or ExtensionElement. * * @param {ModdleElement|djs.model.Base} element * @param {String} type * * @return {ModdleElement} the extension */ function findExtension$1(element, type) { const businessObject = getBusinessObject$1(element); let extensionElements; if (is$4(businessObject, 'bpmn:ExtensionElements')) { extensionElements = businessObject; } else { extensionElements = businessObject.get('extensionElements'); } if (!extensionElements) { return; } return extensionElements.get('values').find(value => { return is$4(value, type); }); } function findZeebeProperty(zeebeProperties, binding) { return zeebeProperties.get('properties').find(value => { return value.name === binding.name; }); } function findInputParameter$1(ioMapping, binding) { const parameters = ioMapping.get('inputParameters'); return parameters.find(parameter => { return parameter.target === binding.name; }); } function findOutputParameter$1(ioMapping, binding) { const parameters = ioMapping.get('outputParameters'); return parameters.find(parameter => { return parameter.source === binding.source; }); } function findTaskHeader(taskHeaders, binding) { const headers = taskHeaders.get('values'); return headers.find(header => { return header.key === binding.key; }); } function findMessage(businessObject) { if (is$4(businessObject, 'bpmn:Event')) { const eventDefinitions = businessObject.get('eventDefinitions'); if (!eventDefinitions || !eventDefinitions.length) { return; } businessObject = eventDefinitions[0]; } if (!businessObject) { return; } return businessObject.get('messageRef'); } function getDefaultValue(property) { if (property.value !== undefined) { return property.value; } if (property.generatedValue) { const { type } = property.generatedValue; if (type === 'uuid') { return v4(); } } } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var hat_1 = createCommonjsModule(function (module) { var hat = module.exports = function (bits, base) { if (!base) base = 16; if (bits === undefined) bits = 128; if (bits <= 0) return '0'; var digits = Math.log(Math.pow(2, bits)) / Math.log(base); for (var i = 2; digits === Infinity; i *= 2) { digits = Math.log(Math.pow(2, bits / i)) / Math.log(base) * i; } var rem = digits - Math.floor(digits); var res = ''; for (var i = 0; i < Math.floor(digits); i++) { var x = Math.floor(Math.random() * base).toString(base); res = x + res; } if (rem) { var b = Math.pow(base, rem); var x = Math.floor(Math.random() * b).toString(base); res = x + res; } var parsed = parseInt(res, base); if (parsed !== Infinity && parsed >= Math.pow(2, bits)) { return hat(bits, base); } else return res; }; hat.rack = function (bits, base, expandBy) { var fn = function (data) { var iters = 0; do { if (iters++ > 10) { if (expandBy) bits += expandBy;else throw new Error('too many ID collisions, use more bits'); } var id = hat(bits, base); } while (Object.hasOwnProperty.call(hats, id)); hats[id] = data; return id; }; var hats = fn.hats = {}; fn.get = function (id) { return fn.hats[id]; }; fn.set = function (id, value) { fn.hats[id] = value; return fn; }; fn.bits = bits || 128; fn.base = base || 16; return fn; }; }); /** * Create a new id generator / cache instance. * * You may optionally provide a seed that is used internally. * * @param {Seed} seed */ function Ids(seed) { if (!(this instanceof Ids)) { return new Ids(seed); } seed = seed || [128, 36, 1]; this._seed = seed.length ? hat_1.rack(seed[0], seed[1], seed[2]) : seed; } /** * Generate a next id. * * @param {Object} [element] element to bind the id to * * @return {String} id */ Ids.prototype.next = function (element) { return this._seed(element || true); }; /** * Generate a next id with a given prefix. * * @param {Object} [element] element to bind the id to * * @return {String} id */ Ids.prototype.nextPrefixed = function (prefix, element) { var id; do { id = prefix + this.next(true); } while (this.assigned(id)); // claim {prefix}{random} this.claim(id, element); // return return id; }; /** * Manually claim an existing id. * * @param {String} id * @param {String} [element] element the id is claimed by */ Ids.prototype.claim = function (id, element) { this._seed.set(id, element || true); }; /** * Returns true if the given id has already been assigned. * * @param {String} id * @return {Boolean} */ Ids.prototype.assigned = function (id) { return this._seed.get(id) || false; }; /** * Unclaim an id. * * @param {String} id the id to unclaim */ Ids.prototype.unclaim = function (id) { delete this._seed.hats[id]; }; /** * Clear all claimed ids. */ Ids.prototype.clear = function () { var hats = this._seed.hats, id; for (id in hats) { this.unclaim(id); } }; /** * Create a new element and set its parent. * * @param {String} elementType of the new element * @param {Object} properties of the new element in key-value pairs * @param {moddle.object} parent of the new element * @param {BpmnFactory} factory which creates the new element * * @returns {djs.model.Base} element which is created */ function createElement$1(elementType, properties, parent, factory) { const element = factory.create(elementType, properties); if (parent) { element.$parent = parent; } return element; } /** * generate a semantic id with given prefix */ function nextId$1(prefix) { const ids = new Ids([32, 32, 1]); return ids.nextPrefixed(prefix); } function getRoot$2(businessObject) { let parent = businessObject; while (parent.$parent) { parent = parent.$parent; } return parent; } function filterElementsByType$1(objectList, type) { const list = objectList || []; return list.filter(element => is$4(element, type)); } function findRootElementsByType$1(businessObject, referencedType) { const root = getRoot$2(businessObject); return filterElementsByType$1(root.get('rootElements'), referencedType); } function findRootElementById$1(businessObject, type, id) { const elements = findRootElementsByType$1(businessObject, type); return elements.find(element => element.id === id); } /** * Create an input parameter representing the given * binding and value. * * @param {PropertyBinding} binding * @param {String} value * @param {BpmnFactory} bpmnFactory * * @return {ModdleElement} */ function createInputParameter$1(binding, value, bpmnFactory) { const { name } = binding; return bpmnFactory.create('zeebe:Input', { source: value, target: name }); } /** * Create an output parameter representing the given * binding and value. * * @param {PropertyBinding} binding * @param {String} value * @param {BpmnFactory} bpmnFactory * * @return {ModdleElement} */ function createOutputParameter$1(binding, value, bpmnFactory) { const { source } = binding; return bpmnFactory.create('zeebe:Output', { source, target: value }); } /** * Create a task header representing the given * binding and value. * * @param {PropertyBinding} binding * @param {String} value * @param {BpmnFactory} bpmnFactory * * @return {ModdleElement} */ function createTaskHeader(binding, value, bpmnFactory) { const { key } = binding; return bpmnFactory.create('zeebe:Header', { key, value }); } /** * Create a task definition representing the given value. * * @param {object} attrs * @param {BpmnFactory} bpmnFactory * * @return {ModdleElement} */ function createTaskDefinition(attrs = {}, bpmnFactory) { return bpmnFactory.create('zeebe:TaskDefinition', attrs); } /** * Create zeebe:Property from the given binding. * * @param {PropertyBinding} binding * @param {String} value * @param {BpmnFactory} bpmnFactory * * @return {ModdleElement} */ function createZeebeProperty(binding, value = '', bpmnFactory) { const { name } = binding; return bpmnFactory.create('zeebe:Property', { name, value }); } /** * Create a called element representing the given value. * * @param {object} attrs * @param {BpmnFactory} bpmnFactory * * @return {ModdleElement} */ function createCalledElement(attrs = {}, bpmnFactory) { return bpmnFactory.create('zeebe:CalledElement', attrs); } /** * Retrieves whether an element should be updated for a given property. * * That matches once * a) the property value is not empty, or * b) the property is not optional * * @param {String} value * @param {Object} property * @returns {Boolean} */ function shouldUpdate(value, property) { const { optional } = property; return value || !optional; } /** * Gets or, in case not existent, creates extension element for given element. * * @param {djs.model.Base} element * @param {String} type * @param {BpmnFactory} bpmnFactory * @returns {ModdleElement} */ function ensureExtension(element, type, bpmnFactory) { const businessObject = getBusinessObject$1(element); let extensionElements = businessObject.get('extensionElements'); if (!extensionElements) { extensionElements = createElement$1('bpmn:ExtensionElements', {}, businessObject, bpmnFactory); businessObject.set('extensionElements', extensionElements); } let extension = findExtension$1(extensionElements, type); if (!extension) { extension = bpmnFactory.create(type); extension.$parent = extensionElements; extensionElements.get('values').push(extension); } return extension; } const PRIMITIVE_MODDLE_TYPES$1 = ['Boolean', 'Integer', 'String']; function getPropertyValue$1(element, property, scope) { let businessObject = getBusinessObject$1(element); const defaultValue = ''; const { binding } = property; const { name, property: bindingProperty, type } = binding; // property if (type === 'property') { const value = businessObject.get(name); if (!isUndefined$1(value)) { return value; } return defaultValue; } // zeebe:taskDefinition if (TASK_DEFINITION_TYPES.includes(type)) { const taskDefinition = findExtension$1(businessObject, 'zeebe:TaskDefinition'); if (taskDefinition) { if (type === ZEEBE_TASK_DEFINITION_TYPE_TYPE) { return taskDefinition.get('type'); } else if (type === ZEEBE_TASK_DEFINITION) { return taskDefinition.get(bindingProperty); } } return defaultValue; } if (IO_BINDING_TYPES$1.includes(type)) { const ioMapping = findExtension$1(businessObject, 'zeebe:IoMapping'); if (!ioMapping) { return defaultValue; } // zeebe:Input if (type === ZEBBE_INPUT_TYPE) { const inputParameter = findInputParameter$1(ioMapping, binding); if (inputParameter) { return inputParameter.get('source'); } return defaultValue; } // zeebe:Output if (type === ZEEBE_OUTPUT_TYPE) { const outputParameter = findOutputParameter$1(ioMapping, binding); if (outputParameter) { return outputParameter.get('target'); } return defaultValue; } } // zeebe:taskHeaders if (type === ZEEBE_TASK_HEADER_TYPE) { const taskHeaders = findExtension$1(businessObject, 'zeebe:TaskHeaders'); if (!taskHeaders) { return defaultValue; } const header = findTaskHeader(taskHeaders, binding); if (header) { return header.get('value'); } return defaultValue; } // zeebe:Property if (type === ZEEBE_PROPERTY_TYPE) { const zeebeProperties = findExtension$1(businessObject, 'zeebe:Properties'); if (zeebeProperties) { const zeebeProperty = findZeebeProperty(zeebeProperties, binding); if (zeebeProperty) { return zeebeProperty.get('value'); } } return defaultValue; } // bpmn:Message#property if (type === MESSAGE_PROPERTY_TYPE) { const message = findMessage(businessObject); const value = message ? message.get(name) : undefined; if (!isUndefined$1(value)) { return value; } return defaultValue; } // bpmn:Message#zeebe:subscription#property if (type === MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE) { const message = findMessage(businessObject); if (message) { const subscription = findExtension$1(message, 'zeebe:Subscription'); const value = subscription ? subscription.get(name) : undefined; if (!isUndefined$1(value)) { return subscription.get(name); } } return defaultValue; } // zeebe:calledElement if (type === ZEEBE_CALLED_ELEMENT) { const calledElement = findExtension$1(businessObject, 'zeebe:CalledElement'); return calledElement ? calledElement.get(bindingProperty) : defaultValue; } // should never throw as templates are validated beforehand throw unknownBindingError$1(element, property); } const NO_OP = null; function setPropertyValue(bpmnFactory, commandStack, element, property, value) { let businessObject = getBusinessObject$1(element); const { binding } = property; const { name, type } = binding; let extensionElements; let propertyValue; const commands = []; const context = { element, property }; // ensure message exists if (MESSAGE_BINDING_TYPES.includes(type)) { if (is$4(businessObject, 'bpmn:Event')) { businessObject = businessObject.get('eventDefinitions')[0]; } let message = findMessage(businessObject); if (!message) { message = bpmnFactory.create('bpmn:Message', { 'zeebe:modelerTemplate': getTemplateId$1(element) }); commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: businessObject, properties: { messageRef: message } } }); } businessObject = message; } // ensure extension elements if (EXTENSION_BINDING_TYPES$1.includes(type)) { extensionElements = businessObject.get('extensionElements'); if (!extensionElements) { extensionElements = createElement$1('bpmn:ExtensionElements', null, businessObject, bpmnFactory); commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: businessObject, properties: { extensionElements } } }); } else { commands.push(NO_OP); } } // property if (PROPERTY_BINDING_TYPES.includes(type)) { const propertyDescriptor = businessObject.$descriptor.propertiesByName[name]; // if property not created yet if (!propertyDescriptor) { // make sure we create the property propertyValue = value || ''; } else { const { type: propertyType } = propertyDescriptor; // do not override non-primitive types if (!PRIMITIVE_MODDLE_TYPES$1.includes(propertyType)) { throw new Error(`cannot set property of type <${propertyType}>`); } if (propertyType === 'Boolean') { propertyValue = !!value; } else if (propertyType === 'Integer') { propertyValue = parseInt(value, 10); if (isNaN(propertyValue)) { // do not set NaN value propertyValue = undefined; } } else { // make sure we don't remove the property propertyValue = value || ''; } } if (!isUndefined$1(propertyValue)) { commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: businessObject, properties: { [name]: propertyValue } } }); } else { commands.push(NO_OP); } } // zeebe:taskDefinition if (TASK_DEFINITION_TYPES.includes(type)) { const oldTaskDefinition = findExtension$1(extensionElements, 'zeebe:TaskDefinition'), propertyName = getTaskDefinitionPropertyName(binding), properties = { [propertyName]: value || '' }; if (oldTaskDefinition) { commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, properties, moddleElement: oldTaskDefinition } }); } else { const newTaskDefinition = createTaskDefinition(properties, bpmnFactory); newTaskDefinition.$parent = businessObject; const values = extensionElements.get('values'); commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: extensionElements, properties: { values: [...values, newTaskDefinition] } } }); } } if (IO_BINDING_TYPES$1.includes(type)) { let ioMapping = findExtension$1(extensionElements, 'zeebe:IoMapping'); if (!ioMapping) { ioMapping = createElement$1('zeebe:IoMapping', null, businessObject, bpmnFactory); commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: extensionElements, properties: { values: [...extensionElements.get('values'), ioMapping] } } }); } // zeebe:Input if (type === ZEBBE_INPUT_TYPE) { const oldZeebeInputParameter = findInputParameter$1(ioMapping, binding); const values = ioMapping.get('inputParameters').filter(value => value !== oldZeebeInputParameter); // do not persist empty parameters when configured as <optional> if (shouldUpdate(value, property)) { const newZeebeInputParameter = createInputParameter$1(binding, value, bpmnFactory); values.push(newZeebeInputParameter); } commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: ioMapping, properties: { inputParameters: [...values] } } }); } // zeebe:Output if (type === ZEEBE_OUTPUT_TYPE) { const oldZeebeOutputParameter = findOutputParameter$1(ioMapping, binding); const values = ioMapping.get('outputParameters').filter(value => value !== oldZeebeOutputParameter); // do not persist empty parameters when configured as <optional> if (shouldUpdate(value, property)) { const newZeebeOutputParameter = createOutputParameter$1(binding, value, bpmnFactory); values.push(newZeebeOutputParameter); } commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: ioMapping, properties: { 'outputParameters': [...values] } } }); } } // zeebe:taskHeaders if (type === ZEEBE_TASK_HEADER_TYPE) { let taskHeaders = findExtension$1(extensionElements, 'zeebe:TaskHeaders'); if (!taskHeaders) { taskHeaders = createElement$1('zeebe:TaskHeaders', null, businessObject, bpmnFactory); commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: extensionElements, properties: { values: [...extensionElements.get('values'), taskHeaders] } } }); } const oldTaskHeader = findTaskHeader(taskHeaders, binding); const values = taskHeaders.get('values').filter(value => value !== oldTaskHeader); // do not persist task headers with empty value if (!value) { commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: taskHeaders, properties: { values } } }); } else { const newTaskHeader = createTaskHeader(binding, value, bpmnFactory); commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: taskHeaders, properties: { values: [...values, newTaskHeader] } } }); } } // zeebe:Property if (type === ZEEBE_PROPERTY_TYPE) { let zeebeProperties = findExtension$1(extensionElements, 'zeebe:Properties'); if (!zeebeProperties) { zeebeProperties = createElement$1('zeebe:Properties', null, businessObject, bpmnFactory); commands.push({ cmd: 'element.updateModdleProperties', context: { element, moddleElement: extensionElements, properties: { values: [...extensionElements.get('values'), zeebeProperties] } } }); } const oldZeebeProperty = findZeebeProperty(zeebeProperties, binding); const properties = zeebeProperties.get('properties').filter(property => property !== oldZeebeProperty); if (shouldUpdate(value, property)) { const newZeebeProperty = createZeebeProperty(binding, value, bpmnFactory); properties.push(newZeebeProperty); } commands.push({ cmd: 'element.updateModdleProperties', context: { element, moddleElement: zeebeProperties, properties: { properties } } }); } // bpmn:Message#zeebe:subscription#property if (type === MESSAGE_ZEEBE_SUBSCRIPTION_PROPERTY_TYPE) { let subscription = findExtension$1(extensionElements, 'zeebe:Subscription'); const properties = { [name]: value || '' }; if (subscription) { commands.push({ cmd: 'element.updateModdleProperties', context: { element, properties, moddleElement: subscription } }); } else { subscription = createElement$1('zeebe:Subscription', properties, extensionElements, bpmnFactory); commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: extensionElements, properties: { values: [...extensionElements.get('values'), subscription] } } }); } } // zeebe:calledElement if (type === ZEEBE_CALLED_ELEMENT) { let calledElement = findExtension$1(element, 'zeebe:CalledElement'); const propertyName = binding.property; const properties = { [propertyName]: value || '' }; if (calledElement) { commands.push({ cmd: 'element.updateModdleProperties', context: { element, properties, moddleElement: calledElement } }); } else { calledElement = createElement$1('zeebe:CalledElement', properties, extensionElements, bpmnFactory); commands.push({ cmd: 'element.updateModdleProperties', context: { ...context, moddleElement: extensionElements, properties: { values: [...extensionElements.get('values'), calledElement] } } }); } } if (commands.length) { const commandsToExecute = commands.filter(command => command !== NO_OP); commandsToExecute.length && commandStack.execute('properties-panel.multi-command-executor', commandsToExecute); return; } // should never throw as templates are validated beforehand throw unknownBindingError$1(element, property); } function validateProperty(value, property, translate$1 = translate) {