UNPKG

camunda-dmn-js

Version:

Embeddable Camunda modeling distributions based on dmn-js

1,383 lines (1,328 loc) 44.1 kB
'use strict'; var DmnModeler = require('dmn-js/lib/Modeler'); var diagramOriginModule = require('diagram-js-origin'); var gridModule = require('diagram-js-grid'); var alignToOriginModule = require('@bpmn-io/align-to-origin'); var dmnJsPropertiesPanel = require('dmn-js-properties-panel'); var minDash = require('min-dash'); var CamundaModdle = require('camunda-dmn-moddle/resources/camunda.json'); var inferno = require('inferno'); var zeebeModdle = require('zeebe-dmn-moddle/resources/zeebe.json'); function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; } function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return (String )(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } /** * Is an element of the given DMN type? * * @param {tjs.model.Base|ModdleElement} element * @param {string} type * * @return {boolean} */ function is(element, type) { var bo = getBusinessObject(element); return bo && typeof bo.$instanceOf === 'function' && bo.$instanceOf(type); } function isInput(element) { return is(element, 'dmn:InputClause'); } function isOutput(element) { return is(element, 'dmn:OutputClause'); } /** * Return the business object for a given element. * * @param {tjs.model.Base|ModdleElement} element * * @return {ModdleElement} */ function getBusinessObject(element) { return element && element.businessObject || element; } /** * Camunda-specific variable provider. Replaces variable name with element's id. */ var CamundaVariableProvider = /*#__PURE__*/function () { function CamundaVariableProvider(variableResolver) { _classCallCheck(this, CamundaVariableProvider); variableResolver.registerProvider(this); } return _createClass(CamundaVariableProvider, [{ key: "getVariables", value: function getVariables(variables, element) { return variables.map(function (variable) { return _objectSpread2(_objectSpread2({}, variable), {}, { name: getVariableName(variable) }); }); } }]); }(); CamundaVariableProvider.$inject = ['variableResolver']; function getVariableName(variable) { var origin = variable.origin; if (origin && is(origin, 'dmn:Decision')) { return origin.get('id'); } return variable.name; } /** * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH * under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. * * Camunda licenses this file to you under the MIT; you may not use this file * except in compliance with the MIT License. */ var CamundaVariableProviderModule = { __init__: ['camundaVariableProvider'], camundaVariableProvider: ['type', CamundaVariableProvider] }; var _excluded = ["boxedExpression", "common", "decisionTable", "drd", "literalExpression"]; var CamundaDmnModeler$2 = /*#__PURE__*/function (_DmnModeler) { function CamundaDmnModeler() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, CamundaDmnModeler); var _options$boxedExpress = options.boxedExpression, boxedExpression = _options$boxedExpress === void 0 ? {} : _options$boxedExpress, _options$common = options.common, common = _options$common === void 0 ? {} : _options$common, _options$decisionTabl = options.decisionTable, decisionTable = _options$decisionTabl === void 0 ? {} : _options$decisionTabl, _options$drd = options.drd, drd = _options$drd === void 0 ? {} : _options$drd, _options$literalExpre = options.literalExpression, literalExpression = _options$literalExpre === void 0 ? {} : _options$literalExpre, otherOptions = _objectWithoutProperties(options, _excluded); var disableAdjustOrigin = drd.disableAdjustOrigin || common.disableAdjustOrigin; var disableGrid = drd.disableGrid || common.disableGrid; return _callSuper(this, CamundaDmnModeler, [_objectSpread2(_objectSpread2({}, otherOptions), {}, { common: _objectSpread2(_objectSpread2({}, common), {}, { feelLanguageContext: _objectSpread2({ parserDialect: 'camunda' }, common === null || common === void 0 ? void 0 : common.feelLanguageContext) }), boxedExpression: mergeModules$2(boxedExpression, [CamundaVariableProviderModule]), decisionTable: mergeModules$2(decisionTable, [CamundaVariableProviderModule]), drd: mergeModules$2(drd, [disableAdjustOrigin ? diagramOriginModule : alignToOriginModule, disableGrid ? {} : gridModule, dmnJsPropertiesPanel.DmnPropertiesPanelModule, dmnJsPropertiesPanel.DmnPropertiesProviderModule]), literalExpression: mergeModules$2(literalExpression, [CamundaVariableProviderModule]) })]); } _inherits(CamundaDmnModeler, _DmnModeler); return _createClass(CamundaDmnModeler); }(DmnModeler); // helpers /////////////////////// function mergeModules$2(config, editorModules) { var additionalModules = config.additionalModules || []; return _objectSpread2(_objectSpread2({}, config), {}, { additionalModules: [].concat(_toConsumableArray(editorModules), _toConsumableArray(additionalModules)) }); } class Input extends inferno.Component { constructor(props, context) { super(props, context); this.state = { value: props.value }; } onInput = event => { const { onInput } = this.props; const value = event.target.value; this.setState({ value }, () => { if (typeof onInput !== 'function') { return; } onInput(value); }); }; onChange = event => { const { onChange } = this.props; if (typeof onChange !== 'function') { return; } onChange(event.target.value); }; onKeyDown = event => { const { onKeyDown } = this.props; if (typeof onKeyDown !== 'function') { return; } onKeyDown(event); }; onKeyUp = event => { const { onKeyUp } = this.props; if (typeof onKeyUp !== 'function') { return; } onKeyUp(event); }; componentDidUpdate(prevProps) { const { value } = this.props; if (value !== prevProps.value && value !== this.state.value) { this.setState({ value }); } } render() { const { className, label, id, placeholder, type } = this.props; const { value } = this.state; return inferno.createVNode(64, "input", [className || '', 'dms-input'].join(' '), null, 1, { "aria-label": label, "placeholder": placeholder || '', "onChange": this.onChange, "onInput": this.onInput, "onKeyDown": this.onKeyDown, "onKeyUp": this.onKeyUp, "spellCheck": "false", "type": type || 'text', "value": value, "id": id }); } } var InputEditor = /*#__PURE__*/function (_Component) { function InputEditor(props, context) { var _this; _classCallCheck(this, InputEditor); _this = _callSuper(this, InputEditor, [props, context]); _this._translate = context.injector.get('translate'); _this._modeling = context.injector.get('modeling'); var debounceInput = context.injector.get('debounceInput'); _this.state = { inputVariable: _this.props.context.input.get('camunda:inputVariable') || '' }; _this.handleInputVariableChange = _this.handleInputVariableChange.bind(_this); _this._setInputVariable = debounceInput(_this._setInputVariable); return _this; } _inherits(InputEditor, _Component); return _createClass(InputEditor, [{ key: "handleInputVariableChange", value: function handleInputVariableChange(value) { var _this2 = this; this.setState({ inputVariable: value || undefined }, function () { return _this2._setInputVariable(value); }); } }, { key: "_setInputVariable", value: function _setInputVariable(inputVariable) { return this._modeling.updateProperties(this.props.context.input, { // set to <undefined> to remove the property 'camunda:inputVariable': inputVariable || undefined }); } }, { key: "render", value: function render() { var inputVariable = this.state.inputVariable; return inferno.createVNode(1, "div", "context-menu-container", inferno.createVNode(1, "div", "dms-form-control", [inferno.createVNode(1, "label", "dms-label", this._translate('Input Variable'), 0), inferno.createComponentVNode(2, Input, { "className": "ref-input-variable", "value": inputVariable || '', "onInput": this.handleInputVariableChange, "placeholder": this._translate('cellInput') })], 4), 2); } }]); }(inferno.Component); var InputVariableProvider = /*#__PURE__*/_createClass(function InputVariableProvider(components) { _classCallCheck(this, InputVariableProvider); components.onGetComponent('context-menu', function () { var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (context.contextMenuType === 'input-edit') { return InputEditor; } }); }); InputVariableProvider.$inject = ['components']; var InputVariableModule = { __init__: ['camundaPlatformInputVariable'], camundaPlatformInputVariable: ['type', InputVariableProvider] }; /** * Input with optional validation. */ class ValidatedInput extends inferno.Component { constructor(props, context) { super(props, context); const { validate, value } = props; const validationWarning = validate ? validate(value || '') : undefined; this.state = { validationWarning, value }; this.onInput = this.onInput.bind(this); this.onKeyDown = this.onKeyDown.bind(this); this.onKeyUp = this.onKeyUp.bind(this); } componentWillReceiveProps(props) { const { validate, value } = props; const validationWarning = validate ? validate(value || '') : undefined; this.setState({ validationWarning, value }); } onInput(value) { const { onInput, validate } = this.props; const validationWarning = validate ? validate(value) : undefined; this.setState({ validationWarning, value }); if (typeof onInput !== 'function') { return; } onInput && onInput({ isValid: !validationWarning, value }); } onKeyDown(event) { const { target } = event, { value } = target; const { onKeyDown, validate } = this.props; const validationWarning = validate ? validate(value) : undefined; if (typeof onKeyDown !== 'function') { return; } onKeyDown({ isValid: !validationWarning, value, event }); } onKeyUp(event) { const { target } = event, { value } = target; const { onKeyUp, validate } = this.props; const validationWarning = validate ? validate(value) : undefined; if (typeof onKeyUp !== 'function') { return; } onKeyUp({ isValid: !validationWarning, value, event }); } render() { const { placeholder, type, className, label } = this.props; const { validationWarning, value } = this.state; const parentClasses = ['dms-validated-input', className].join(' '); const inputClasses = []; if (validationWarning) { inputClasses.push('invalid'); } return inferno.createVNode(1, "div", parentClasses, [inferno.createComponentVNode(2, Input, { "className": inputClasses, "label": label, "onInput": this.onInput, "onKeyDown": this.onKeyDown, "onKeyUp": this.onKeyUp, "placeholder": placeholder || '', "type": type, "value": value || '' }), validationWarning && inferno.createVNode(1, "p", "dms-hint dms-validation-warning", validationWarning, 0)], 0); } } function inject(component) { const Type = component.constructor; return injectType(Type, component); } function injectType(Type, component) { const annotation = Type.$inject; if (!annotation) { return; } const { injector } = component.context; const setupFn = [...annotation, function (...args) { for (const idx in args) { const name = annotation[idx]; const value = args[idx]; component[name] = value; } }]; injector.invoke(setupFn); } /** * Expose `parse`. */ var domify = parse; /** * Tests for browser support. */ var innerHTMLBug = false; var bugTestDiv; if (typeof document !== 'undefined') { bugTestDiv = document.createElement('div'); // Setup bugTestDiv.innerHTML = ' <link/><table></table><a href="/a">a</a><input type="checkbox"/>'; // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length; bugTestDiv = undefined; } /** * Wrap map from jquery. */ var map = { legend: [1, '<fieldset>', '</fieldset>'], tr: [2, '<table><tbody>', '</tbody></table>'], col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'], // for script/link/style tags to work in IE6-8, you have to wrap // in a div with a non-whitespace character in front, ha! _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', ''] }; map.td = map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>']; map.option = map.optgroup = [1, '<select multiple="multiple">', '</select>']; map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '<table>', '</table>']; map.polyline = map.ellipse = map.polygon = map.circle = map.text = map.line = map.path = map.rect = map.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">', '</svg>']; /** * Parse `html` and return a DOM Node instance, which could be a TextNode, * HTML DOM Node of some kind (<div> for example), or a DocumentFragment * instance, depending on the contents of the `html` string. * * @param {String} html - HTML string to "domify" * @param {Document} doc - The `document` instance to create the Node for * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance * @api private */ function parse(html, doc) { if ('string' != typeof html) throw new TypeError('String expected'); // default to the global `document` object if (!doc) doc = document; // tag name var m = /<([\w:]+)/.exec(html); if (!m) return doc.createTextNode(html); html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace var tag = m[1]; // body support if (tag == 'body') { var el = doc.createElement('html'); el.innerHTML = html; return el.removeChild(el.lastChild); } // wrap map var wrap = Object.prototype.hasOwnProperty.call(map, tag) ? map[tag] : map._default; var depth = wrap[0]; var prefix = wrap[1]; var suffix = wrap[2]; var el = doc.createElement('div'); el.innerHTML = prefix + html + suffix; while (depth--) el = el.lastChild; // one element if (el.firstChild == el.lastChild) { return el.removeChild(el.firstChild); } // several elements var fragment = doc.createDocumentFragment(); while (el.firstChild) { fragment.appendChild(el.removeChild(el.firstChild)); } return fragment; } var domify$1 = domify; function remove(el) { el.parentNode && el.parentNode.removeChild(el); } class InputSelect extends inferno.Component { constructor(props, context) { super(props, context); inject(this); const { value } = props; this.state = { value, optionsVisible: false }; this._portalEl = null; } componentDidMount() { document.addEventListener('mousedown', this.onGlobalClick); document.addEventListener('focusin', this.onFocusChanged); this.keyboard.addListener(this.onKeyboard); } componentWillUnmount() { document.removeEventListener('focusin', this.onFocusChanged); document.removeEventListener('mousedown', this.onGlobalClick); this.keyboard.removeListener(this.onKeyboard); this.removePortalEl(); } componentWillReceiveProps(props) { const { value } = props; this.setState({ value }); } componentWillUpdate(nextProps, nextState) { const { optionsVisible } = nextState; if (optionsVisible) { if (!this._portalEl) { this.addPortalEl(); } } else { if (this._portalEl) { this.removePortalEl(); } } } componentDidUpdate() { const { optionsVisible } = this.state; if (!optionsVisible || !this.inputNode) { return; } const optionsBounds = this.getOptionsBounds(); minDash.assign(this._portalEl.style, optionsBounds); } getOptionsBounds() { const container = this.renderer.getContainer(); const { top: containerTop, left: containerLeft, bottom: containerBottom } = container.getBoundingClientRect(); const { top: inputTop, left: inputLeft, width, height, bottom: inputBottom } = this.inputNode.getBoundingClientRect(); const top = inputTop + height - containerTop + container.scrollTop; const left = inputLeft - containerLeft + container.scrollLeft; const bounds = { top: `${top}px`, left: `${left}px`, width: `${width}px`, 'max-height': `calc(100% - ${top}px)` }; // open the options upwards when not even one option (=input height) fits if (containerBottom - inputBottom < height) { const bottom = containerBottom - inputTop; bounds.bottom = `${bottom}px`; bounds['max-height'] = `calc(100% - ${bottom})`; delete bounds.top; } return bounds; } addPortalEl() { this._portalEl = domify$1('<div class="dms-select-options"></div>'); const container = this.renderer.getContainer(); container.appendChild(this._portalEl); // suppress mousedown event propagation to handle click events inside the component this._portalEl.addEventListener('mousedown', stopPropagation); } removePortalEl() { if (this._portalEl) { this._portalEl.removeEventListener('mousedown', stopPropagation); remove(this._portalEl); this._portalEl = null; } } onChange = value => { this.setState({ value }); const { onChange } = this.props; if (typeof onChange !== 'function') { return; } onChange(value); }; onInputClick = event => { event.preventDefault(); event.stopPropagation(); this.setOptionsVisible(!this.state.optionsVisible); this.focusInput(); }; onInput = event => { const { value } = event.target; this.onChange(value); }; onOptionClick = (value, event) => { event.preventDefault(); event.stopPropagation(); this.setOptionsVisible(false); this.onChange(value); this.focusInput(); }; /** * Focus input node */ focusInput() { const node = this.inputNode; node.focus(); // move cursor to end of input if ('selectionStart' in node) { node.selectionStart = 100000; } } checkClose(focusTarget) { if (this._portalEl && !this._portalEl.contains(focusTarget) && !this.parentNode.contains(focusTarget)) { this.setOptionsVisible(false); } } onFocusChanged = evt => { this.checkClose(evt.target); }; onGlobalClick = evt => { this.checkClose(evt.target); }; select(direction) { const { options } = this.props; const { value } = this.state; if (!options) { return; } const option = options.filter(o => o.value === value)[0]; const idx = option ? options.indexOf(option) : -1; const nextIdx = idx === -1 ? direction === 1 ? 0 : options.length - 1 : (idx + direction) % options.length; const nextOption = options[nextIdx < 0 ? options.length + nextIdx : nextIdx]; this.onChange(nextOption.value); } setOptionsVisible(optionsVisible) { this.setState({ optionsVisible }); } onKeyDown = evt => { const { optionsVisible } = this.state; var code = evt.which; // DOWN or UP if (code === 40 || code === 38) { evt.stopPropagation(); evt.preventDefault(); if (!optionsVisible) { this.setOptionsVisible(true); } else { this.select(code === 40 ? 1 : -1); } } if (optionsVisible) { // ENTER // ESC if (code === 13 || code === 27) { evt.stopPropagation(); evt.preventDefault(); this.setOptionsVisible(false); } } }; onKeyboard = keycode => { const { optionsVisible } = this.state; if (!optionsVisible) { return; } // close on ESC if (keycode === 27) { this.setOptionsVisible(false); return true; } }; renderOptions(options, activeOption) { return inferno.createVNode(1, "div", "options", options.map(option => { return inferno.createVNode(1, "div", ['option', activeOption === option ? 'active' : ''].join(' '), option.label, 0, { "data-value": option.value, "onClick": e => this.onOptionClick(option.value, e) }); }), 0); } render() { const { className, label: inputLabel, id, options, noInput, title } = this.props; const { optionsVisible, value } = this.state; const option = options ? options.filter(o => o.value === value)[0] : false; const label = option ? option.label : value; return inferno.createVNode(1, "div", [className || '', 'dms-input-select'].join(' '), [noInput ? inferno.createVNode(1, "div", "dms-input", label, 0, { "aria-label": inputLabel, "tabIndex": "0", "onKeyDown": this.onKeyDown }, null, node => this.inputNode = node) : inferno.createVNode(64, "input", "dms-input", null, 1, { "aria-label": inputLabel, "onInput": this.onInput, "onKeyDown": this.onKeyDown, "spellCheck": "false", "type": "text", "value": value, "id": id }, null, node => this.inputNode = node), inferno.createVNode(1, "span", ['dms-input-select-icon', optionsVisible ? 'dmn-icon-up' : 'dmn-icon-down'].join(' ')), optionsVisible && inferno.createPortal(this.renderOptions(options, option), this._portalEl)], 0, { "title": title, "onClick": this.onInputClick }, null, node => this.parentNode = node); } } InputSelect.$inject = ['keyboard', 'renderer']; // helper //// function stopPropagation(event) { event.stopPropagation(); } var ISO_DATE_REGEX = /^\d{4}(?:-\d\d){2}T(?:\d\d:){2}\d\d$/; var BETWEEN_DATE_REGEX = /^\[date and time\("(\d{4}(?:-\d\d){2}T(?:\d\d:){2}\d\d)"\)..date and time\("(\d{4}(?:-\d\d){2}T(?:\d\d:){2}\d\d)"/; var BEFORE_AFTER_DATE_REGEX = /^(<|>)\s*date and time\("(\d{4}(?:-\d\d){2}T(?:\d\d:){2}\d\d)"\)/; var EXACT_DATE_REGEX = /^date and time\("(\d{4}(?:-\d\d){2}T(?:\d\d:){2}\d\d)"\)$/; var EXACT$1 = 'exact', BEFORE$1 = 'before', AFTER$1 = 'after', BETWEEN$1 = 'between'; function validateISOString(string) { if (!ISO_DATE_REGEX.test(string.trim())) { return 'Date must match pattern yyyy-MM-ddTHH:mm:ss.'; } } function getDateString(type, dates) { if (type === EXACT$1) { return "date and time(\"".concat(dates[0], "\")"); } else if (type === BEFORE$1) { return "< date and time(\"".concat(dates[0], "\")"); } else if (type === AFTER$1) { return "> date and time(\"".concat(dates[0], "\")"); } else if (type === BETWEEN$1) { return "[date and time(\"".concat(dates[0], "\")..date and time(\"").concat(dates[1], "\")]"); } } function getSampleDate() { var date = new Date(); date.setUTCHours(0, 0, 0, 0); return date.toISOString().slice(0, -5); } function parseString(string) { // emtpy if (!string || string.trim() === '') { return { type: 'exact', date: '' }; } // between var matches = string.match(BETWEEN_DATE_REGEX); if (matches) { return { type: 'between', dates: [matches[1], matches[2]] }; } // before or after matches = string.match(BEFORE_AFTER_DATE_REGEX); if (matches) { return { type: matches[1] === '<' ? 'before' : 'after', date: matches[2] }; } // exact matches = string.match(EXACT_DATE_REGEX); if (matches) { return { type: 'exact', date: matches[1] }; } } var EXACT = 'exact', BEFORE = 'before', AFTER = 'after', BETWEEN = 'between'; var InputDateEdit = /*#__PURE__*/function (_Component) { function InputDateEdit(props, context) { var _this; _classCallCheck(this, InputDateEdit); _this = _callSuper(this, InputDateEdit, [props, context]); _this._modeling = context.injector.get('modeling'); var element = _this.props.context.element; var parsedString = parseString(element.businessObject.text); if (parsedString) { var dates; if (parsedString.date) { dates = [parsedString.date, '']; } else if (parsedString.dates) { dates = parsedString.dates; } else { dates = ['', '']; } _this.state = { type: parsedString.type, dates: dates }; } else { _this.state = { type: EXACT, dates: ['', ''] }; } var debounceInput = context.injector.get('debounceInput'); _this.debouncedEditCell = debounceInput(_this.editCell.bind(_this)); _this.editCell = _this.editCell.bind(_this); _this.onTypeChange = _this.onTypeChange.bind(_this); _this.onSetStartDateTodayClick = _this.onSetStartDateTodayClick.bind(_this); _this.onSetEndDateTodayClick = _this.onSetEndDateTodayClick.bind(_this); _this.onStartDateInput = _this.onStartDateInput.bind(_this); _this.onEndDateInput = _this.onEndDateInput.bind(_this); return _this; } _inherits(InputDateEdit, _Component); return _createClass(InputDateEdit, [{ key: "editCell", value: function editCell(cell, text) { this._modeling.editCell(cell, text); } }, { key: "onTypeChange", value: function onTypeChange(value) { var element = this.props.context.element; var dates = this.state.dates; this.setState({ type: value }); if (parseString(getDateString(value, dates))) { this.editCell(element.businessObject, getDateString(value, dates)); } } }, { key: "onSetStartDateTodayClick", value: function onSetStartDateTodayClick() { var element = this.props.context.element; var _this$state = this.state, dates = _this$state.dates, type = _this$state.type; var date = getSampleDate(); this.setState({ dates: [date, dates[1]] }); if (parseString(getDateString(type, [date, dates[1]]))) { this.editCell(element.businessObject, getDateString(type, [date, dates[1]])); } } }, { key: "onSetEndDateTodayClick", value: function onSetEndDateTodayClick() { var element = this.props.context.element; var _this$state2 = this.state, dates = _this$state2.dates, type = _this$state2.type; var date = getSampleDate(); this.setState({ dates: [dates[0], date] }); if (parseString(getDateString(type, [dates[0], date]))) { this.editCell(element.businessObject, getDateString(type, [dates[0], date])); } } }, { key: "onStartDateInput", value: function onStartDateInput(_ref) { var isValid = _ref.isValid, value = _ref.value; if (isValid) { var element = this.props.context.element; var _this$state3 = this.state, dates = _this$state3.dates, type = _this$state3.type; this.setState({ dates: [value, dates[1]] }); this.debouncedEditCell(element.businessObject, getDateString(type, [value, dates[1]])); } } }, { key: "onEndDateInput", value: function onEndDateInput(_ref2) { var isValid = _ref2.isValid, value = _ref2.value; if (isValid) { var element = this.props.context.element; var _this$state4 = this.state, dates = _this$state4.dates, type = _this$state4.type; this.setState({ dates: [dates[0], value] }); this.debouncedEditCell(element.businessObject, getDateString(type, [dates[0], value])); } } }, { key: "render", value: function render() { var _this$state5 = this.state, dates = _this$state5.dates, type = _this$state5.type; var options = [{ label: 'Exactly', value: EXACT }, { label: 'Before', value: BEFORE }, { label: 'After', value: AFTER }, { label: 'Between', value: BETWEEN }]; return inferno.createVNode(1, "div", "context-menu-container simple-date-edit", [inferno.createVNode(1, "h3", "dms-heading", inferno.createTextVNode("Edit Date"), 2), inferno.createVNode(1, "div", "dms-fill-row", inferno.createComponentVNode(2, InputSelect, { "noInput": true, "onChange": this.onTypeChange, "options": options, "value": type }), 2), inferno.createVNode(1, "h4", "dms-heading", type === BETWEEN ? 'Edit Start Date' : 'Set Date', 0), inferno.createVNode(1, "div", null, [inferno.createComponentVNode(2, ValidatedInput, { "className": "start-date-input dms-block", "onInput": this.onStartDateInput, "placeholder": "e.g. ".concat(getSampleDate()), "validate": validateISOString, "value": dates[0] }), inferno.createVNode(1, "p", "dms-hint", [inferno.createVNode(1, "button", "use-today", inferno.createTextVNode("Use today"), 2, { "type": "button", "onClick": this.onSetStartDateTodayClick }), inferno.createTextVNode(".")], 4)], 4), type === BETWEEN && inferno.createVNode(1, "h4", "dms-heading", inferno.createTextVNode("Edit End Date"), 2), type === BETWEEN && inferno.createVNode(1, "div", null, [inferno.createComponentVNode(2, ValidatedInput, { "className": "end-date-input dms-block", "onInput": this.onEndDateInput, "placeholder": "e.g. ".concat(getSampleDate()), "validate": validateISOString, "value": dates[1] }), inferno.createVNode(1, "p", "dms-hint", [inferno.createVNode(1, "button", "use-today", inferno.createTextVNode("Use today"), 2, { "type": "button", "onClick": this.onSetEndDateTodayClick }), inferno.createTextVNode(".")], 4)], 4)], 0); } }]); }(inferno.Component); var OutputDateEdit = /*#__PURE__*/function (_Component) { function OutputDateEdit(props, context) { var _this; _classCallCheck(this, OutputDateEdit); _this = _callSuper(this, OutputDateEdit, [props, context]); _this._modeling = context.injector.get('modeling'); var element = _this.props.context.element; var parsedString = parseString(element.businessObject.text); _this.state = { date: parsedString ? parsedString.date : '' }; var debounceInput = context.injector.get('debounceInput'); _this.debouncedEditCell = debounceInput(_this.editCell.bind(_this)); _this.editCell = _this.editCell.bind(_this); _this.onClick = _this.onClick.bind(_this); _this.onInput = _this.onInput.bind(_this); return _this; } _inherits(OutputDateEdit, _Component); return _createClass(OutputDateEdit, [{ key: "editCell", value: function editCell(cell, text) { this._modeling.editCell(cell, text); } }, { key: "onClick", value: function onClick() { var element = this.props.context.element; var date = getSampleDate(); this.setState({ date: date }); this.editCell(element.businessObject, "date and time(\"".concat(date, "\")")); } }, { key: "onInput", value: function onInput(_ref) { var isValid = _ref.isValid, value = _ref.value; if (isValid) { var element = this.props.context.element; this.setState({ date: value }); this.debouncedEditCell(element.businessObject, "date and time(\"".concat(value, "\")")); } } }, { key: "render", value: function render() { var date = this.state.date; return inferno.createVNode(1, "div", "context-menu-container simple-date-edit", [inferno.createVNode(1, "h3", "dms-heading", inferno.createTextVNode("Edit Date"), 2), inferno.createVNode(1, "h4", "dms-heading", inferno.createTextVNode("Set Date"), 2), inferno.createVNode(1, "div", null, [inferno.createComponentVNode(2, ValidatedInput, { "onInput": this.onInput, "placeholder": "e.g. ".concat(getSampleDate()), "validate": validateISOString, "value": date, "className": "dms-block" }), inferno.createVNode(1, "p", "dms-hint", [inferno.createTextVNode("Set date "), inferno.createVNode(1, "button", "use-today", inferno.createTextVNode("to today"), 2, { "type": "button", "onClick": this.onClick }), inferno.createTextVNode(".")], 4)], 4)], 4); } }]); }(inferno.Component); var SimpleDateEdit = /*#__PURE__*/_createClass(function SimpleDateEdit(components, simpleMode) { _classCallCheck(this, SimpleDateEdit); simpleMode.registerProvider(function (element) { var typeRef = getTypeRef(element); return (isInput(element.col) || isOutput(element.col)) && isDate(typeRef); }); components.onGetComponent('context-menu', function () { var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (context.contextMenuType && context.contextMenuType === 'simple-mode-edit') { if (!context.element) { return; } var typeRef = getTypeRef(context.element); if (isDate(typeRef)) { if (isInput(context.element.col)) { return InputDateEdit; } else if (isOutput(context.element.col)) { return OutputDateEdit; } } } }); }); SimpleDateEdit.$inject = ['components', 'simpleMode']; // helpers ////////////////////// function getTypeRef(element) { if (isInput(element.col)) { return element.col && element.col.businessObject.inputExpression.typeRef; } else { return element.col && element.col.businessObject.typeRef; } } function isDate(typeRef) { return typeRef === 'date'; } var SimpleDateEditModule = { __init__: ['simpleDateEdit'], simpleDateEdit: ['type', SimpleDateEdit] }; // disables simple edit mode for unsupported data types var SimpleModeModule = { simpleDurationEdit: ['type', noop], simpleDateTimeEdit: ['type', noop], simpleTimeEdit: ['type', noop] }; function noop() {} var EXPRESSION_LANGUAGE_OPTIONS = [{ label: 'FEEL', value: 'feel' }, { label: 'JUEL', value: 'juel' }, { label: 'JavaScript', value: 'javascript' }, { label: 'Groovy', value: 'groovy' }, { label: 'Python', value: 'python' }, { label: 'JRuby', value: 'jruby' }]; var dataTypes = ['string', 'boolean', 'integer', 'long', 'double', 'date']; var CamundaDmnModeler$1 = /*#__PURE__*/function (_BaseModeler) { function CamundaDmnModeler() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, CamundaDmnModeler); var expressionLanguages = mergeExpressionLanguagesConfig(options.common); var decisionTable = options.decisionTable || {}; var drd = options.drd || {}; var boxedExpression = options.boxedExpression || {}; return _callSuper(this, CamundaDmnModeler, [_objectSpread2(_objectSpread2({}, options), {}, { boxedExpression: boxedExpression, common: _objectSpread2(_objectSpread2({ dataTypes: dataTypes }, options.common), {}, { expressionLanguages: expressionLanguages }), decisionTable: mergeModules$1(decisionTable, [InputVariableModule, SimpleDateEditModule, SimpleModeModule]), drd: mergeModules$1(drd, [dmnJsPropertiesPanel.CamundaPropertiesProviderModule]), moddleExtensions: _objectSpread2({ camunda: CamundaModdle }, options.moddleExtensions) })]); } _inherits(CamundaDmnModeler, _BaseModeler); return _createClass(CamundaDmnModeler); }(CamundaDmnModeler$2); function mergeExpressionLanguagesConfig() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var expressionLanguagesConfig = options.expressionLanguages || {}; var effectiveConfig = { options: expressionLanguagesConfig.options || EXPRESSION_LANGUAGE_OPTIONS, "default": expressionLanguagesConfig["default"] || { editor: 'feel' } }; return effectiveConfig; } // helpers /////////////////////// function mergeModules$1(config, editorModules) { var additionalModules = config.additionalModules || []; return _objectSpread2(_objectSpread2({}, config), {}, { additionalModules: [].concat(_toConsumableArray(editorModules), _toConsumableArray(additionalModules)) }); } /** * @type { { * zeebe: any * } } */ var commonModdleExtensions = { zeebe: zeebeModdle }; var CamundaDmnModeler = /*#__PURE__*/function (_BaseModeler) { function CamundaDmnModeler() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, CamundaDmnModeler); var _options$common = options.common, common = _options$common === void 0 ? {} : _options$common, _options$drd = options.drd, drd = _options$drd === void 0 ? {} : _options$drd, _options$moddleExtens = options.moddleExtensions, moddleExtensions = _options$moddleExtens === void 0 ? {} : _options$moddleExtens; var _common$propertiesPan = common.propertiesPanel, propertiesPanel = _common$propertiesPan === void 0 ? {} : _common$propertiesPan; return _callSuper(this, CamundaDmnModeler, [_objectSpread2(_objectSpread2({}, options), {}, { common: _objectSpread2(_objectSpread2({}, common), {}, { propertiesPanel: _objectSpread2(_objectSpread2({}, propertiesPanel), {}, { tooltip: dmnJsPropertiesPanel.ZeebeTooltipProvider }) }), drd: mergeModules(drd, [dmnJsPropertiesPanel.ZeebePropertiesProviderModule]), moddleExtensions: _objectSpread2(_objectSpread2({}, commonModdleExtensions), moddleExtensions) })]); } _inherits(CamundaDmnModeler, _BaseModeler); return _createClass(CamundaDmnModeler); }(CamundaDmnModeler$2); // helpers /////////////////////// function mergeModules(config, editorModules) { var additionalModules = config.additionalModules || []; return _objectSpread2(_objectSpread2({}, config), {}, { additionalModules: [].concat(_toConsumableArray(editorModules), _toConsumableArray(additionalModules)) }); } exports.BaseModeler = CamundaDmnModeler$2; exports.CamundaCloudModeler = CamundaDmnModeler; exports.CamundaPlatformModeler = CamundaDmnModeler$1; //# sourceMappingURL=index.js.map