From ee86b31cd7fc6f42f92f56171a9945a8ff22773a Mon Sep 17 00:00:00 2001 From: Kevin Burnett <18027+burnettk@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:00:11 +0000 Subject: [PATCH] Feature/spiff message branch (#100) * Add new props from editor * Fix receive message * Handle no messages found * remove debounce * Spiff message : Custom MultiSelect Input * Add event for open json schema editor * Get Schemas Ids - Mock API * Implement MessageJsonSchemaSelect * Lint * Refactoring * Add some missing dependencies * Branch Refactoring * Fix broken tests clear extensions element on change message selected Fix Send Task Add Is Matching Correlation enabled Add Variable condition Move variable Move Payload List correlation props based on element AddMatching condition Array Branch Refactoring * Adding spiffworkflow namespace * Handle message APIs * hooking message button to post and listen to the event bus. * Fix Message Editor Button Labeling * load files with jsx as jsx w/ burnettk * updates to work with vite in the frontend w/ burnettk * Add Correlation Key * fix automatic deletion of messages&&correlationProps * Hide message on process level * Sync Messages and correlations on DeleteEvent * Fix deletion of correlation properties * Message Payload issue * Fix payload for message events * Fix matching condition * fix matching condition - css issue * Fire add new message event * Fix AddMessage event * Fix AddMessage event * Fix/message tests - duplicated correlations keys (#99) * Append correlation Properties in Launch editor event * Not allow two parent correlation keys * Fix Message tests #1 * fix broken tests * Add unit test for add message event * some updates while reviewing w/ burnettk --------- Co-authored-by: jasquat --------- Co-authored-by: Ayoub Ait Lachgar <44379029+theaubmov@users.noreply.github.com> Co-authored-by: Ayoub ait lachgar Co-authored-by: Dan Funk Co-authored-by: jasquat --- app/app.js | 78 ++- app/css/app.css | 42 ++ app/index.html | 71 +- app/spiffworkflow/eventSelect.js | 4 +- app/spiffworkflow/index.js | 3 + app/spiffworkflow/messages/MessageHelpers.js | 636 +++++++++++++++++- .../messages/MessageInterceptor.js | 57 ++ app/spiffworkflow/messages/index.js | 5 +- .../CorrelationPropertiesArray.js | 291 -------- .../MessageCorrelationPropertiesArray.js | 481 ++++++------- .../propertiesPanel/MessagePayload.jsx | 65 -- .../propertiesPanel/MessageSelect.jsx | 87 --- .../MessagesPropertiesProvider.js | 157 +---- .../CorrelationCheckbox.jsx | 42 ++ .../CorrelationPropertiesList.js | 189 ++++++ .../MatchingConditionArray.js | 117 ++++ .../MatchingCorrelationCheckbox.jsx | 43 ++ .../MessageJsonSchemaSelect.js | 134 ++++ .../MessageLaunchEditorButton.js | 57 ++ .../elementLevelProvider/MessagePayload.jsx | 104 +++ .../elementLevelProvider/MessageSelect.jsx | 206 ++++++ .../MessageVariable.jsx | 27 +- .../TaskEventMessageProvider.js | 199 ++++++ .../CollaborationPropertiesProvider.js | 69 ++ .../CorrelationKeysArray.js | 23 +- .../CorrelationPropertiesArray.js | 150 +++++ .../MessageArray.js | 47 +- .../MessagePropertiesMultiSelect.js | 87 +++ app/spiffworkflow/moddle/spiffworkflow.json | 20 + package-lock.json | 501 +++++++++++--- package.json | 1 + test/spec/MessagesSpec.js | 191 +++++- test/spec/bpmn/collaboration.bpmn | 37 +- 33 files changed, 3153 insertions(+), 1068 deletions(-) mode change 100644 => 100755 app/spiffworkflow/messages/MessageHelpers.js create mode 100644 app/spiffworkflow/messages/MessageInterceptor.js mode change 100644 => 100755 app/spiffworkflow/messages/index.js delete mode 100644 app/spiffworkflow/messages/propertiesPanel/CorrelationPropertiesArray.js mode change 100644 => 100755 app/spiffworkflow/messages/propertiesPanel/MessageCorrelationPropertiesArray.js delete mode 100644 app/spiffworkflow/messages/propertiesPanel/MessagePayload.jsx delete mode 100644 app/spiffworkflow/messages/propertiesPanel/MessageSelect.jsx mode change 100644 => 100755 app/spiffworkflow/messages/propertiesPanel/MessagesPropertiesProvider.js create mode 100755 app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/CorrelationCheckbox.jsx create mode 100755 app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/CorrelationPropertiesList.js create mode 100755 app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MatchingConditionArray.js create mode 100755 app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MatchingCorrelationCheckbox.jsx create mode 100755 app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageJsonSchemaSelect.js create mode 100755 app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageLaunchEditorButton.js create mode 100755 app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessagePayload.jsx create mode 100755 app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageSelect.jsx rename app/spiffworkflow/messages/propertiesPanel/{ => elementLevelProvider}/MessageVariable.jsx (62%) mode change 100644 => 100755 create mode 100755 app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/TaskEventMessageProvider.js create mode 100755 app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CollaborationPropertiesProvider.js rename app/spiffworkflow/messages/propertiesPanel/{ => processLevelProvider}/CorrelationKeysArray.js (78%) mode change 100644 => 100755 create mode 100755 app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CorrelationPropertiesArray.js rename app/spiffworkflow/messages/propertiesPanel/{ => processLevelProvider}/MessageArray.js (81%) mode change 100644 => 100755 create mode 100755 app/spiffworkflow/messages/propertiesPanel/processLevelProvider/MessagePropertiesMultiSelect.js diff --git a/app/app.js b/app/app.js index 39b020c..7f19879 100644 --- a/app/app.js +++ b/app/app.js @@ -152,6 +152,7 @@ bpmnModeler.on('spiff.callactivity.edit', (newEvent) => { bpmnModeler.on('spiff.file.edit', (newEvent) => { console.log('Open new window to edit file: ', newEvent.value); }); + bpmnModeler.on('spiff.dmn.edit', (newEvent) => { console.log('Open new window to edit DMN table: ', newEvent.value); }); @@ -169,6 +170,10 @@ bpmnModeler.on('spiff.json_schema_files.requested', (event) => { }); }); +bpmnModeler.on('spiff.msg_json_schema_files.requested', (event) => { + console.log('Open new window to edit Message json schema: '); +}); + bpmnModeler.on('spiff.dmn_files.requested', (event) => { event.eventBus.fire('spiff.dmn_files.returned', { options: [ @@ -188,6 +193,75 @@ bpmnModeler.on('spiff.data_stores.requested', (event) => { }); }); +bpmnModeler.on('spiff.messages.requested', (event) => { + event.eventBus.fire('spiff.messages.returned', { + configuration: { + "messages": [ + { + "identifier": "basic_message", + "location": "examples/1-basic-concepts", + "schema": {}, + "correlation_properties": [] + }, + { + "identifier": "end_of_day_receipts", + "location": "examples", + "schema": {}, + "correlation_properties": [] + }, + { + "identifier": "order_ready", + "location": "examples", + "schema": {}, + "correlation_properties": [ + { + "identifier": "table_number", + "retrieval_expression": "table_number" + }, + { + "identifier": "franchise_id", + "retrieval_expression": "franchise_id" + } + ] + }, + { + "identifier": "table_seated", + "location": "examples", + "schema": {}, + "correlation_properties": [ + { + "identifier": "table_number", + "retrieval_expression": "table_number-v2" + }, + { + "identifier": "franchise_id", + "retrieval_expression": "franchise_id-v2" + } + ] + } + ] + } + }); +}); + +bpmnModeler.on('spiff.add_message.requested', (event) => { + event.eventBus.fire('spiff.add_message.returned', { + name: 'msgName', + correlation_properties: { + "c1": { + "retrieval_expressions": [ + "c1x" + ] + }, + "c2": { + "retrieval_expressions": [ + "cxxxx1x" + ] + } + } + }); +}); + // As call activites might refernce processes across the system // it should be possible to search for a paticular call activity. bpmnModeler.on('spiff.callactivity.search', (event) => { @@ -206,7 +280,7 @@ bpmnModeler.on('import.parse.complete', event => { refs.forEach(ref => { const props = { id: ref.id, - name: ref.id ? typeof(ref.name) === 'undefined': ref.name, + name: ref.id ? typeof (ref.name) === 'undefined' : ref.name, }; let elem = bpmnModeler._moddle.create(desc, props); elem.$parent = ref.element; @@ -214,7 +288,7 @@ bpmnModeler.on('import.parse.complete', event => { }); }); -bpmnModeler.importXML(diagramXML).then(() => {}); +bpmnModeler.importXML(diagramXML).then(() => { }); // This handles the download and upload buttons - it isn't specific to // the BPMN modeler or these extensions, just a quick way to allow you to diff --git a/app/css/app.css b/app/css/app.css index 7e70a2d..e49c5c0 100644 --- a/app/css/app.css +++ b/app/css/app.css @@ -24,6 +24,7 @@ html, body { border-radius: 2px; font-family: 'Arial', sans-serif; padding: 10px; + /* width: 400px; */ min-width: 400px; } @@ -50,6 +51,11 @@ adjust CSS props so that padding won't add to dimensions. padding-right: 2px; } +/* .properties-panel-parent { + border-left: unset !important; + overflow: unset !important; +} */ + /* Style buttons */ .bpmn-js-spiffworkflow-btn { background-color: DodgerBlue; @@ -61,6 +67,16 @@ adjust CSS props so that padding won't add to dimensions. margin: 12px; } +.bio-properties-panel-description { + word-wrap: break-word; + max-width: 350px; +} + +.bio-properties-panel-group-entries > .bio-properties-panel-description { + padding-inline: 15px; + padding-block: 8px; +} + /* Darker background on mouse-over */ .bpmn-js-spiffworkflow-btn:hover { background-color: RoyalBlue; @@ -95,3 +111,29 @@ adjust CSS props so that padding won't add to dimensions. .djs-palette.two-column.open { width: 95px; } + +.nice-select { + background-color: #f7f7f8 !important; + border: 1px solid var(--input-border-color) !important; + border-radius: 2px !important; + padding-left: 8px !important; +} + +.nice-select .nice-select-dropdown { + z-index: 50 !important; + width: 100%; +} + +.nice-select .multiple-options .current { + margin: 2px; + padding: 5px; + background-color: #ffffff; + border: 1px solid #ccc; + border-radius: 3px; + font-size: 0.9em; + color: #333; +} + +.d-grid { + display: grid !important; +} \ No newline at end of file diff --git a/app/index.html b/app/index.html index ca7d9aa..b90b4f5 100644 --- a/app/index.html +++ b/app/index.html @@ -1,5 +1,6 @@ + bpmn-js-spiffworkflow - + - - - - + + + + - + @@ -31,34 +32,38 @@ + + - - -
-
-
-
- -
-
-
- -
-
-
-
- -
-
- -
-
- - + + +
+
+
+
+ +
+
+
+ +
+
+
+
+ +
+
+ +
+
+ + + - + + \ No newline at end of file diff --git a/app/spiffworkflow/eventSelect.js b/app/spiffworkflow/eventSelect.js index ffd823f..87c4980 100644 --- a/app/spiffworkflow/eventSelect.js +++ b/app/spiffworkflow/eventSelect.js @@ -123,7 +123,7 @@ function getSelectorForType(eventDetails) { const getOptions = (val) => { const matching = root.rootElements ? root.rootElements.filter(elem => elem.$type === eventType) : []; const options = []; - matching.map(option => options.push({label: option.name, value: option.id})); + matching.map(option => options.push({ label: option.name, value: option.id })); return options; } @@ -169,7 +169,7 @@ function getTextFieldForExtension(eventDetails, label, description, catching) { } } - const setValue = (value) => { + const setValue = (value) => { const bpmnEvent = getEvent(); if (bpmnEvent) { if (!bpmnEvent.extensionElements) diff --git a/app/spiffworkflow/index.js b/app/spiffworkflow/index.js index 536e136..362951c 100644 --- a/app/spiffworkflow/index.js +++ b/app/spiffworkflow/index.js @@ -19,6 +19,7 @@ import CallActivityPropertiesProvider from './callActivity/propertiesPanel/CallA import StandardLoopPropertiesProvider from './loops/propertiesPanel/StandardLoopPropertiesProvider'; import MultiInstancePropertiesProvider from './loops/propertiesPanel/MultiInstancePropertiesProvider'; import CallActivityInterceptor from './callActivity/CallActivityInterceptor'; +import MessageInterceptor from './messages/MessageInterceptor'; export default { __depends__: [RulesModule], @@ -32,6 +33,7 @@ export default { 'conditionsPropertiesProvider', 'extensionsPropertiesProvider', 'messagesPropertiesProvider', + 'messageInterceptor', 'signalPropertiesProvider', 'errorPropertiesProvider', 'escalationPropertiesProvider', @@ -57,6 +59,7 @@ export default { errorPropertiesProvider: ['type', ErrorPropertiesProvider], escalationPropertiesProvider: ['type', EscalationPropertiesProvider], messagesPropertiesProvider: ['type', MessagesPropertiesProvider], + messageInterceptor: ['type', MessageInterceptor], callActivityPropertiesProvider: ['type', CallActivityPropertiesProvider], ioPalette: ['type', IoPalette], ioRules: ['type', IoRules], diff --git a/app/spiffworkflow/messages/MessageHelpers.js b/app/spiffworkflow/messages/MessageHelpers.js old mode 100644 new mode 100755 index 6c5b8a8..80d297d --- a/app/spiffworkflow/messages/MessageHelpers.js +++ b/app/spiffworkflow/messages/MessageHelpers.js @@ -14,16 +14,28 @@ export function getRoot(businessObject, moddle) { } } else { // todo: Do we want businessObject to be a shape or moddle object? - if (businessObject.$type === 'bpmn:Definitions') { + if (businessObject && businessObject.$type === 'bpmn:Definitions') { return businessObject; } - if (typeof businessObject.$parent !== 'undefined') { + if (businessObject && typeof businessObject.$parent !== 'undefined') { return getRoot(businessObject.$parent); } } return businessObject; } +export function getAbsoluteRoot(businessObject, moddle) { + // todo: Do we want businessObject to be a shape or moddle object? + if (businessObject.$type === 'bpmn:Definitions') { + return businessObject; + } + if (typeof businessObject.$parent !== 'undefined') { + return getRoot(businessObject.$parent); + } + + return businessObject; +} + export function isMessageElement(shapeElement) { return ( is(shapeElement, 'bpmn:SendTask') || @@ -33,11 +45,18 @@ export function isMessageElement(shapeElement) { } export function isMessageEvent(shapeElement) { - const { eventDefinitions } = shapeElement.businessObject; - if (eventDefinitions && eventDefinitions[0]) { - return eventDefinitions[0].$type === 'bpmn:MessageEventDefinition'; + try { + const bo = shapeElement.businessObject + ? shapeElement.businessObject + : shapeElement; + const { eventDefinitions } = bo; + if (eventDefinitions && eventDefinitions[0]) { + return eventDefinitions[0].$type === 'bpmn:MessageEventDefinition'; + } + return false; + } catch (error) { + return false; } - return false; } export function canReceiveMessage(shapeElement) { @@ -83,7 +102,7 @@ export function findCorrelationKeyForCorrelationProperty(shapeElement, moddle) { } export function findCorrelationPropertiesAndRetrievalExpressionsForMessage( - shapeElement, + shapeElement ) { const formalExpressions = []; const messageRefElement = getMessageRefElement(shapeElement); @@ -95,7 +114,7 @@ export function findCorrelationPropertiesAndRetrievalExpressionsForMessage( const retrievalExpression = getRetrievalExpressionFromCorrelationProperty( childElement, - messageRefElement, + messageRefElement ); if (retrievalExpression) { const formalExpression = { @@ -128,7 +147,7 @@ export function getMessageElementForShapeElement(shapeElement) { function getRetrievalExpressionFromCorrelationProperty( correlationProperty, - message, + message ) { if (correlationProperty.correlationPropertyRetrievalExpression) { for (const retrievalExpression of correlationProperty.correlationPropertyRetrievalExpression) { @@ -158,6 +177,50 @@ export function findCorrelationProperties(businessObject, moddle) { return correlationProperties; } +export function findCorrelationPropertiesByMessage(element) { + let messageId; + + const { businessObject } = element; + const root = getRoot(businessObject); + const correlationProperties = []; + + if (isMessageEvent(element)) { + if ( + !businessObject.eventDefinitions || + !businessObject.eventDefinitions[0].messageRef + ) { + return []; + } else { + messageId = businessObject.eventDefinitions[0].messageRef.id; + } + } else if (isMessageElement(element)) { + if (!businessObject.messageRef) return; + messageId = businessObject.messageRef.id; + } + + if (isIterable(root.rootElements)) { + for (const rootElement of root.rootElements) { + if (rootElement.$type === 'bpmn:CorrelationProperty') { + rootElement.correlationPropertyRetrievalExpression = + rootElement.correlationPropertyRetrievalExpression + ? rootElement.correlationPropertyRetrievalExpression + : []; + const existingExpressionIndex = + rootElement.correlationPropertyRetrievalExpression.findIndex( + (retrievalExpr) => + retrievalExpr.messageRef && + retrievalExpr.messageRef.id === messageId + ); + existingExpressionIndex !== -1 + ? correlationProperties.push(rootElement) + : null; + } + } + } + + return correlationProperties; +} + function isIterable(obj) { // checks for null and undefined if (obj == null) { @@ -196,3 +259,558 @@ export function findMessageModdleElements(businessObject) { } return messages; } + +export function findMessageElement(businessObject, messageId, definitions) { + let root = getRoot(businessObject); + + // This case is to handle root for deleted elements + if (!root && definitions) { + root = definitions; + } + + if (root.rootElements) { + for (const rootElement of root.rootElements) { + if ( + rootElement.$type === 'bpmn:Message' && + rootElement.name == messageId + ) { + return rootElement; + } + } + } + return null; +} + +export function createOrUpdateCorrelationProperties( + bpmnFactory, + commandStack, + element, + propertiesConfig, + messageId +) { + let definitions = getRoot(element.businessObject); + + if (propertiesConfig) { + // Iterate over each property configuration + propertiesConfig.forEach((propConfig) => { + if (isMessageIdInRetrievalExpressions(propConfig, messageId)) { + let correlationProperty = findCorrelationPropertyById( + definitions, + propConfig.id + ); + + // If the correlationProperty does not exist, create it + if (correlationProperty === null) { + correlationProperty = bpmnFactory.create('bpmn:CorrelationProperty'); + correlationProperty.id = propConfig.id; + correlationProperty.name = propConfig.id; + correlationProperty.correlationPropertyRetrievalExpression = []; + } else if ( + correlationProperty && + !correlationProperty.correlationPropertyRetrievalExpression + ) { + correlationProperty.correlationPropertyRetrievalExpression = []; + } + + // Iterate over retrieval expressions and add them to the correlationProperty + propConfig.retrieval_expressions.forEach((expr) => { + const existingExpressionIndex = + correlationProperty.correlationPropertyRetrievalExpression.findIndex( + (retrievalExpr) => + retrievalExpr.messageRef && + retrievalExpr.messageRef.id === messageId + ); + if (expr.message_ref == messageId && existingExpressionIndex === -1) { + const retrievalExpression = bpmnFactory.create( + 'bpmn:CorrelationPropertyRetrievalExpression' + ); + const formalExpression = bpmnFactory.create( + 'bpmn:FormalExpression' + ); + formalExpression.body = expr.formal_expression + ? expr.formal_expression + : ''; + retrievalExpression.messagePath = formalExpression; + const msgElement = findMessageElement( + element.businessObject, + expr.message_ref + ); + retrievalExpression.messageRef = msgElement; + correlationProperty.correlationPropertyRetrievalExpression.push( + retrievalExpression + ); + } + }); + + const existingIndex = definitions.rootElements.findIndex( + (element) => + element.id === correlationProperty.id && + element.$type === correlationProperty.$type + ); + + if (existingIndex !== -1) { + // Update existing correlationProperty + definitions.rootElements[existingIndex] = correlationProperty; + } else { + // Add new correlationProperty + definitions.rootElements.push(correlationProperty); + } + + commandStack.execute('element.updateProperties', { + element, + properties: {}, + }); + } + }); + } +} + +export function createOrUpdateCorrelationPropertiesV2( + bpmnFactory, + commandStack, + element, + propertiesConfig, + messageId +) { + let definitions = getRoot(element.businessObject); + + if (propertiesConfig) { + // Iterate over each property configuration + propertiesConfig.forEach((propConfig) => { + let correlationProperty = findCorrelationPropertyById( + definitions, + propConfig.identifier + ); + const msgElement = findMessageElement(element.businessObject, messageId); + + if (correlationProperty === null) { + correlationProperty = bpmnFactory.create('bpmn:CorrelationProperty'); + correlationProperty.id = propConfig.identifier; + correlationProperty.name = propConfig.identifier; + correlationProperty.correlationPropertyRetrievalExpression = []; + } + + correlationProperty.correlationPropertyRetrievalExpression = + !correlationProperty.correlationPropertyRetrievalExpression + ? [] + : correlationProperty.correlationPropertyRetrievalExpression; + + const existingExpressionIndex = + correlationProperty.correlationPropertyRetrievalExpression.findIndex( + (retrievalExpr) => + retrievalExpr.messageRef && + retrievalExpr.messageRef.id === messageId + ); + + if (existingExpressionIndex === -1) { + const retrievalExpression = bpmnFactory.create( + 'bpmn:CorrelationPropertyRetrievalExpression' + ); + const formalExpression = bpmnFactory.create('bpmn:FormalExpression'); + formalExpression.body = propConfig.retrieval_expression + ? propConfig.retrieval_expression + : ''; + retrievalExpression.messagePath = formalExpression; + retrievalExpression.messageRef = msgElement; + correlationProperty.correlationPropertyRetrievalExpression.push( + retrievalExpression + ); + } + + const existingIndex = definitions.rootElements.findIndex( + (element) => + element.id === correlationProperty.id && + element.$type === correlationProperty.$type + ); + + if (existingIndex !== -1) { + // Update existing correlationProperty + definitions.rootElements[existingIndex] = correlationProperty; + } else { + // Add new correlationProperty + definitions.rootElements.push(correlationProperty); + } + + commandStack.execute('element.updateProperties', { + element, + properties: {}, + }); + }); + } +} + +export function findCorrelationPropertyById(definitions, id) { + let foundCorrelationProperty = null; + definitions.rootElements.forEach((rootElement) => { + if ( + rootElement.$type === 'bpmn:CorrelationProperty' && + rootElement.id === id + ) { + foundCorrelationProperty = rootElement; + } + }); + return foundCorrelationProperty; +} + +export function isMessageRefUsed(definitions, messageRef) { + if (!definitions.rootElements) { + return true; + } + + for (const rootElement of definitions.rootElements) { + if (rootElement.$type === 'bpmn:Process') { + const process = rootElement; + for (const element of process.flowElements) { + if ( + isMessageEvent(element) && + element.eventDefinitions && + element.eventDefinitions[0] && + element.eventDefinitions[0].messageRef && + element.eventDefinitions[0].messageRef.id === messageRef + ) { + return true; + } else if ( + isMessageElement(element) && + element.messageRef && + element.messageRef.id === messageRef + ) { + return true; + } + } + } + } + + return false; +} + +function isMessageIdInRetrievalExpressions(propConfig, messageId) { + return propConfig.retrieval_expressions.some( + (expr) => expr.message_ref === messageId + ); +} + +function isMessageRefInCorrelationPropertiesRetrivalExpression( + correlationProperty, + messageRef +) { + return correlationProperty.correlationPropertyRetrievalExpression + ? correlationProperty.correlationPropertyRetrievalExpression.some( + (expr) => expr.messageRef === messageRef + ) + : false; +} + +// Create new correlation property from editor +export function createNewCorrelationProperty( + element, + moddle, + commandStack, + messageRef +) { + const rootElement = getRoot(element.businessObject); + const { rootElements } = rootElement; + + const newCorrelationPropertyElement = moddle.create( + 'bpmn:CorrelationProperty' + ); + + const correlationPropertyId = moddle.ids.nextPrefixed('CorrelationProperty_'); + + newCorrelationPropertyElement.id = correlationPropertyId; + newCorrelationPropertyElement.name = correlationPropertyId; + newCorrelationPropertyElement.correlationPropertyRetrievalExpression = []; + + if (messageRef) { + const retrievalExpression = moddle.create( + 'bpmn:CorrelationPropertyRetrievalExpression' + ); + const formalExpression = moddle.create('bpmn:FormalExpression'); + formalExpression.body = ''; + retrievalExpression.messagePath = formalExpression; + retrievalExpression.messageRef = messageRef; + newCorrelationPropertyElement.correlationPropertyRetrievalExpression.push( + retrievalExpression + ); + } + + rootElements.push(newCorrelationPropertyElement); + + commandStack.execute('element.updateProperties', { + element, + properties: {}, + }); +} + +// Create new correlation key from editor +export function createNewCorrelationKey( + element, + moddle, + commandStack, + messageRef +) { + if (element.type === 'bpmn:Collaboration') { + const newCorrelationKeyElement = moddle.create('bpmn:CorrelationKey'); + const newCorrelationKey = moddle.ids.nextPrefixed('CorrelationKey_'); + newCorrelationKeyElement.name = newCorrelationKey; + newCorrelationKeyElement.id = newCorrelationKey; + + const currentCorrelationKeyElements = + element.businessObject.get('correlationKeys'); + currentCorrelationKeyElements.push(newCorrelationKeyElement); + + commandStack.execute('element.updateProperties', { + element, + properties: {}, + }); + } +} + +// Create new message from editor +export function createNewMessage(element, moddle, commandStack) { + if ( + element.type === 'bpmn:Collaboration' || + element.type === 'bpmn:Process' + ) { + const rootElement = getRoot(element.businessObject); + const { rootElements } = rootElement; + const messageId = moddle.ids.nextPrefixed('Message_'); + const newMessageElement = moddle.create('bpmn:Message'); + + newMessageElement.id = messageId; + newMessageElement.name = messageId; + + rootElements.push(newMessageElement); + + commandStack.execute('element.updateProperties', { + element, + properties: {}, + }); + } +} + +// Set a message to a list of correlation properties +export function setMessageRefToListofCorrelationProperties( + messageRef, + correlationPropertyIDs, + element, + moddle, + commandStack +) { + let definitions = getRoot(element.businessObject); + if (definitions) { + definitions.rootElements.forEach((rootElement) => { + if ( + rootElement.$type === 'bpmn:CorrelationProperty' && + correlationPropertyIDs.includes(rootElement.id) && + !isMessageRefInCorrelationPropertiesRetrivalExpression( + rootElement, + messageRef + ) + ) { + const retrievalExpression = moddle.create( + 'bpmn:CorrelationPropertyRetrievalExpression' + ); + const formalExpression = moddle.create('bpmn:FormalExpression'); + formalExpression.body = ''; + retrievalExpression.messagePath = formalExpression; + retrievalExpression.messageRef = messageRef; + rootElement.correlationPropertyRetrievalExpression + ? rootElement.correlationPropertyRetrievalExpression.push( + retrievalExpression + ) + : (rootElement.correlationPropertyRetrievalExpression = [ + retrievalExpression, + ]); + } else if ( + rootElement.$type === 'bpmn:CorrelationProperty' && + !correlationPropertyIDs.includes(rootElement.id) && + isMessageRefInCorrelationPropertiesRetrivalExpression( + rootElement, + messageRef + ) + ) { + rootElement.correlationPropertyRetrievalExpression = + rootElement.correlationPropertyRetrievalExpression.filter( + (expr) => expr.messageRef !== messageRef + ); + } + }); + } +} + +export function getCorrelationPropertiesIDsFiltredByMessageRef( + businessObject, + moddle, + messageRef +) { + const root = getRoot(businessObject, moddle); + const IDs = []; + if (isIterable(root.rootElements)) { + for (const rootElement of root.rootElements) { + if ( + rootElement.$type === 'bpmn:CorrelationProperty' && + isMessageRefInCorrelationPropertiesRetrivalExpression( + rootElement, + messageRef + ) + ) { + IDs.push({ + value: rootElement.id, + text: rootElement.name || rootElement.id, + selected: true, + }); + } else if ( + rootElement.$type === 'bpmn:CorrelationProperty' && + !isMessageRefInCorrelationPropertiesRetrivalExpression( + rootElement, + messageRef + ) + ) { + IDs.push({ + value: rootElement.id, + text: rootElement.name || rootElement.id, + selected: false, + }); + } + } + } + return IDs; +} + +export function setParentCorrelationKeys( + definitions, + bpmnFactory, + element, + moddle +) { + // Retrieve all correlation properties + let correlationProperties = findCorrelationProperties( + element.businessObject, + moddle + ); + correlationProperties = correlationProperties || []; + + let mainCorrelationKey = findOrCreateMainCorrelationKey( + definitions, + bpmnFactory, + moddle + ); + + // Clear existing ones + mainCorrelationKey.get('correlationPropertyRef').length = 0; + + // Sync correlation properties + correlationProperties.forEach((cP) => { + const cPElement = bpmnFactory.create('bpmn:CorrelationProperty', { + id: cP.id, + name: cP.name, + }); + mainCorrelationKey.get('correlationPropertyRef').push(cPElement); + }); + + // check if process has collaboration + let collaboration = definitions + .get('rootElements') + .find((element) => element.$type === 'bpmn:Collaboration'); + + if (collaboration) { + // Remove existing correlation keys other than the main correlation key + collaboration.get('correlationKeys').forEach((key, index) => { + if (key.name !== 'MainCorrelationKey') { + collaboration.get('correlationKeys').splice(index, 1); + } + }); + + const existingKey = collaboration + .get('correlationKeys') + .find((key) => key.name === 'MainCorrelationKey'); + if (!existingKey) { + collaboration.get('correlationKeys').push(mainCorrelationKey); + } + } else { + // Handle case where no collaboration is found + definitions.get('rootElements').forEach((element, index) => { + if ( + element.$type === 'bpmn:CorrelationKey' && + element.name !== 'MainCorrelationKey' + ) { + definitions.get('rootElements').splice(index, 1); + } + }); + + const existingKey = definitions + .get('rootElements') + .find( + (key) => + key.$type === 'bpmn:CorrelationKey' && + key.name === 'MainCorrelationKey' + ); + if (!existingKey) { + definitions.get('rootElements').push(mainCorrelationKey); + } + } +} + +function findOrCreateMainCorrelationKey(definitions, bpmnFactory, moddle) { + let mainCorrelationKey = definitions + .get('rootElements') + .find( + (element) => + element.$type === 'bpmn:CorrelationKey' && + element.name === 'MainCorrelationKey' + ); + + if (!mainCorrelationKey) { + const newCorrelationKeyId = moddle.ids.nextPrefixed('CorrelationKey_'); + mainCorrelationKey = bpmnFactory.create('bpmn:CorrelationKey', { + id: newCorrelationKeyId, + name: 'MainCorrelationKey', + }); + } + + return mainCorrelationKey; +} + +export function synCorrleationProperties(element, definitions, moddle) { + const { businessObject } = element; + const correlationProps = findCorrelationProperties(businessObject, moddle); + const expressionsToDelete = []; + + for (let cProperty of correlationProps) { + let isUsed = false; + for (const cpExpression of cProperty.correlationPropertyRetrievalExpression) { + const msgRef = findMessageElement( + businessObject, + cpExpression.messageRef.id, + definitions + ); + isUsed = msgRef ? true : isUsed; + // if unused false, delete retrival expression + if (!msgRef) { + expressionsToDelete.push(cpExpression); + } + } + + // Delete the retrieval expressions that are not used + for (const expression of expressionsToDelete) { + const index = + cProperty.correlationPropertyRetrievalExpression.indexOf(expression); + if (index > -1) { + cProperty.correlationPropertyRetrievalExpression.splice(index, 1); + const cPropertyIndex = definitions + .get('rootElements') + .indexOf(cProperty); + definitions.rootElements.splice(cPropertyIndex, 1, cProperty); + } + } + + // If Unused, delete the correlation property + if (!isUsed) { + const index = definitions.get('rootElements').indexOf(cProperty); + if (index > -1) { + definitions.rootElements.splice(index, 1); + } + } + } +} + diff --git a/app/spiffworkflow/messages/MessageInterceptor.js b/app/spiffworkflow/messages/MessageInterceptor.js new file mode 100644 index 0000000..3c4ec17 --- /dev/null +++ b/app/spiffworkflow/messages/MessageInterceptor.js @@ -0,0 +1,57 @@ +import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor'; +import { isMessageElement, isMessageRefUsed, setParentCorrelationKeys, synCorrleationProperties } from './MessageHelpers'; + +const HIGH_PRIORITY = 90500; + +export default class MessageInterceptor extends CommandInterceptor { + + constructor(eventBus, bpmnFactory, commandStack, bpmnUpdater, moddle) { + super(eventBus); + + this.postExecuted(['shape.delete'], HIGH_PRIORITY, function (event) { + const { context } = event; + const { shape, rootElement } = context; + const { businessObject } = shape; + + if (isMessageElement(shape)) { + + let oldMessageRef = (businessObject.eventDefinitions) ? businessObject.eventDefinitions[0].messageRef : businessObject.messageRef; + + let definitions = rootElement.businessObject.$parent; + if (!definitions.get('rootElements')) { + definitions.set('rootElements', []); + } + + if (oldMessageRef) { + // Remove previous message in case it's not used anymore + const isOldMessageUsed = isMessageRefUsed(definitions, oldMessageRef.id); + if (!isOldMessageUsed) { + const rootElements = definitions.get('rootElements'); + const oldMessageIndex = rootElements.findIndex( + (element) => + element.$type === 'bpmn:Message' && element.id === oldMessageRef.id, + ); + if (oldMessageIndex !== -1) { + rootElements.splice(oldMessageIndex, 1); + definitions.rootElements = rootElements; + } + } + + // Automatic deletion of previous message correlation properties + synCorrleationProperties(shape, definitions, moddle); + } + + // Update Correlation key if Process has collaboration + try { + setParentCorrelationKeys(definitions, bpmnFactory, shape, moddle); + } catch (error) { + console.error('Error Caught while synchronizing Correlation key', error); + } + + } + }); + + } +} + +MessageInterceptor.$inject = ['eventBus', 'bpmnFactory', 'commandStack', 'bpmnUpdater', 'moddle']; diff --git a/app/spiffworkflow/messages/index.js b/app/spiffworkflow/messages/index.js old mode 100644 new mode 100755 index 3c54f26..356f4e5 --- a/app/spiffworkflow/messages/index.js +++ b/app/spiffworkflow/messages/index.js @@ -1,6 +1,9 @@ +import MessageInterceptor from './MessageInterceptor'; import MessagesPropertiesProvider from './propertiesPanel/MessagesPropertiesProvider'; export default { - __init__: ['messagesPropertiesProvider'], + __init__: ['messagesPropertiesProvider', 'messageInterceptor'], messagesPropertiesProvider: ['type', MessagesPropertiesProvider], + messageInterceptor: [ 'type', MessageInterceptor ], + }; diff --git a/app/spiffworkflow/messages/propertiesPanel/CorrelationPropertiesArray.js b/app/spiffworkflow/messages/propertiesPanel/CorrelationPropertiesArray.js deleted file mode 100644 index 0e73336..0000000 --- a/app/spiffworkflow/messages/propertiesPanel/CorrelationPropertiesArray.js +++ /dev/null @@ -1,291 +0,0 @@ -import { useService } from 'bpmn-js-properties-panel'; -import { - SelectEntry, - isTextFieldEntryEdited, - TextFieldEntry, -} from '@bpmn-io/properties-panel'; -import { - getRoot, - findCorrelationKeys, - findCorrelationProperties, - findCorrelationKeyForCorrelationProperty, -} from '../MessageHelpers'; -import { removeFirstInstanceOfItemFromArrayInPlace } from '../../helpers'; - -/** - * Allows the creation, or editing of messageCorrelations at the bpmn:sendTask level of a BPMN document. - */ -export function CorrelationPropertiesArray(props) { - const { moddle } = props; - const { element } = props; - const { commandStack } = props; - const { translate } = props; - - const correlationPropertyArray = findCorrelationProperties( - element.businessObject - ); - const items = correlationPropertyArray.map( - (correlationPropertyModdleElement, index) => { - const id = `correlation-${index}`; - const entries = MessageCorrelationPropertyGroup({ - idPrefix: id, - correlationPropertyModdleElement, - translate, - element, - commandStack, - moddle, - }); - return { - id, - label: correlationPropertyModdleElement.name, - entries, - autoFocusEntry: id, - remove: removeFactory({ - element, - correlationPropertyModdleElement, - commandStack, - moddle, - }), - }; - } - ); - - function add(event) { - event.stopPropagation(); - const newCorrelationPropertyElement = moddle.create( - 'bpmn:CorrelationProperty' - ); - const correlationPropertyId = moddle.ids.nextPrefixed( - 'CorrelationProperty_' - ); - newCorrelationPropertyElement.id = correlationPropertyId; - newCorrelationPropertyElement.name = correlationPropertyId; - const rootElement = getRoot(element.businessObject); - const { rootElements } = rootElement; - rootElements.push(newCorrelationPropertyElement); - - const correlationKeyElements = findCorrelationKeys( - newCorrelationPropertyElement, - moddle - ); - const correlationKeyElement = correlationKeyElements[0]; - if (correlationKeyElement.correlationPropertyRef) { - correlationKeyElement.correlationPropertyRef.push( - newCorrelationPropertyElement - ); - } else { - correlationKeyElement.correlationPropertyRef = [ - newCorrelationPropertyElement, - ]; - } - - commandStack.execute('element.updateProperties', { - element, - properties: {}, - }); - } - - return { items, add }; -} - -function removeFactory(props) { - const { element, correlationPropertyModdleElement, moddle, commandStack } = - props; - - return function (event) { - event.stopPropagation(); - const rootElement = getRoot(element.businessObject); - const { rootElements } = rootElement; - - const oldCorrelationKeyElement = findCorrelationKeyForCorrelationProperty( - correlationPropertyModdleElement, - moddle - ); - if (oldCorrelationKeyElement) { - removeFirstInstanceOfItemFromArrayInPlace( - oldCorrelationKeyElement.correlationPropertyRef, - correlationPropertyModdleElement - ); - } - - removeFirstInstanceOfItemFromArrayInPlace( - rootElements, - correlationPropertyModdleElement - ); - commandStack.execute('element.updateProperties', { - element, - properties: { - messages: rootElements, - }, - }); - }; -} - -function MessageCorrelationPropertyGroup(props) { - const { - idPrefix, - correlationPropertyModdleElement, - translate, - element, - commandStack, - moddle, - } = props; - return [ - { - id: `${idPrefix}-correlation-key`, - component: MessageCorrelationKeySelect, - isEdited: isTextFieldEntryEdited, - idPrefix, - element, - correlationPropertyModdleElement, - translate, - moddle, - commandStack, - }, - { - id: `${idPrefix}-correlation-property-name`, - component: CorrelationPropertyNameTextField, - isEdited: isTextFieldEntryEdited, - idPrefix, - element, - correlationPropertyModdleElement, - translate, - commandStack, - }, - ]; -} - -function MessageCorrelationKeySelect(props) { - const { - idPrefix, - correlationPropertyModdleElement, - translate, - element, - moddle, - commandStack, - } = props; - const debounce = useService('debounceInput'); - - const setValue = (value) => { - if ( - value === 'placeholder-never-should-be-used-as-an-actual-correlation-key' - ) { - return; - } - const correlationKeyElements = findCorrelationKeys( - correlationPropertyModdleElement, - moddle - ); - let newCorrelationKeyElement; - for (const cke of correlationKeyElements) { - if (cke.name === value) { - newCorrelationKeyElement = cke; - } - } - const oldCorrelationKeyElement = findCorrelationKeyForCorrelationProperty( - correlationPropertyModdleElement, - moddle - ); - - if (newCorrelationKeyElement.correlationPropertyRef) { - newCorrelationKeyElement.correlationPropertyRef.push( - correlationPropertyModdleElement - ); - } else { - newCorrelationKeyElement.correlationPropertyRef = [ - correlationPropertyModdleElement, - ]; - } - - if (oldCorrelationKeyElement) { - removeFirstInstanceOfItemFromArrayInPlace( - oldCorrelationKeyElement.correlationPropertyRef, - correlationPropertyModdleElement - ); - } - - commandStack.execute('element.updateModdleProperties', { - element, - moddleElement: correlationPropertyModdleElement, - properties: {}, - }); - }; - - const getValue = () => { - const correlationKeyElement = findCorrelationKeyForCorrelationProperty( - correlationPropertyModdleElement, - moddle - ); - if (correlationKeyElement) { - return correlationKeyElement.name; - } - return null; - }; - - const getOptions = () => { - const correlationKeyElements = findCorrelationKeys( - correlationPropertyModdleElement, - moddle - ); - const options = []; - if (correlationKeyElements.length === 0) { - options.push({ - label: 'Please Create a Correlation Key', - value: 'placeholder-never-should-be-used-as-an-actual-correlation-key', - disabled: true, - }); - } - for (const correlationKeyElement of correlationKeyElements) { - options.push({ - label: correlationKeyElement.name, - value: correlationKeyElement.name, - }); - } - return options; - }; - - return SelectEntry({ - id: `${idPrefix}-select`, - element, - label: translate('Correlation Key'), - getValue, - setValue, - getOptions, - debounce, - }); -} - -function CorrelationPropertyNameTextField(props) { - const { - id, - element, - correlationPropertyModdleElement, - commandStack, - translate, - } = props; - - const debounce = useService('debounceInput'); - const setValue = (value) => { - commandStack.execute('element.updateModdleProperties', { - element, - moddleElement: correlationPropertyModdleElement, - properties: { - name: value, - id: value, - }, - }); - }; - - const getValue = () => { - return correlationPropertyModdleElement.name; - }; - - return TextFieldEntry({ - element, - id: `${id}-name-textField`, - label: translate('Name'), - getValue, - setValue, - debounce, - }); -} diff --git a/app/spiffworkflow/messages/propertiesPanel/MessageCorrelationPropertiesArray.js b/app/spiffworkflow/messages/propertiesPanel/MessageCorrelationPropertiesArray.js old mode 100644 new mode 100755 index 743db12..8106e6b --- a/app/spiffworkflow/messages/propertiesPanel/MessageCorrelationPropertiesArray.js +++ b/app/spiffworkflow/messages/propertiesPanel/MessageCorrelationPropertiesArray.js @@ -11,268 +11,271 @@ import { } from '../MessageHelpers'; import { removeFirstInstanceOfItemFromArrayInPlace } from '../../helpers'; +// UNUSED MODULE + /** * Allows the creation, or editing of messageCorrelations at the bpmn:sendTask level of a BPMN document. */ export function MessageCorrelationPropertiesArray(props) { - const { moddle } = props; - const { element } = props; - const { commandStack } = props; - const { translate } = props; + // const { moddle } = props; + // const { element } = props; + // const { commandStack } = props; + // const { translate } = props; - const correlationPropertyObjectsForCurrentMessage = - findCorrelationPropertiesAndRetrievalExpressionsForMessage(element); - const allCorrelationPropertyModdleElements = findCorrelationProperties( - element, - moddle - ); - const items = correlationPropertyObjectsForCurrentMessage.map( - (correlationPropertyObject, index) => { - const { - correlationPropertyModdleElement, - correlationPropertyRetrievalExpressionModdleElement, - } = correlationPropertyObject; - const id = `correlation-${index}`; - const entries = MessageCorrelationPropertyGroup({ - idPrefix: id, - correlationPropertyModdleElement, - correlationPropertyRetrievalExpressionModdleElement, - translate, - moddle, - element, - commandStack, - }); - return { - id, - label: correlationPropertyModdleElement.name, - entries, - autoFocusEntry: id, - remove: removeFactory({ - element, - correlationPropertyModdleElement, - correlationPropertyRetrievalExpressionModdleElement, - commandStack, - }), - }; - } - ); + // const correlationPropertyObjectsForCurrentMessage = + // findCorrelationPropertiesAndRetrievalExpressionsForMessage(element); + // const allCorrelationPropertyModdleElements = findCorrelationProperties( + // element, + // moddle + // ); + // const items = correlationPropertyObjectsForCurrentMessage.map( + // (correlationPropertyObject, index) => { + // const { + // correlationPropertyModdleElement, + // correlationPropertyRetrievalExpressionModdleElement, + // } = correlationPropertyObject; + // const id = `correlation-${index}`; + // const entries = MessageCorrelationPropertyGroup({ + // idPrefix: id, + // correlationPropertyModdleElement, + // correlationPropertyRetrievalExpressionModdleElement, + // translate, + // moddle, + // element, + // commandStack, + // }); + // return { + // id, + // label: correlationPropertyModdleElement.name, + // entries, + // autoFocusEntry: id, + // remove: removeFactory({ + // element, + // correlationPropertyModdleElement, + // correlationPropertyRetrievalExpressionModdleElement, + // commandStack, + // }), + // }; + // } + // ); - function add(event) { - event.stopPropagation(); + // function add(event) { + // event.stopPropagation(); - let correlationPropertyElement; - allCorrelationPropertyModdleElements.forEach((cpe) => { - let foundElement = false; - correlationPropertyObjectsForCurrentMessage.forEach((cpo) => { - const cpme = cpo.correlationPropertyModdleElement; - if (cpme.id === cpe.id) { - foundElement = true; - } - }); - if (!foundElement) { - correlationPropertyElement = cpe; - } - }); + // let correlationPropertyElement; + // allCorrelationPropertyModdleElements.forEach((cpe) => { + // let foundElement = false; + // correlationPropertyObjectsForCurrentMessage.forEach((cpo) => { + // const cpme = cpo.correlationPropertyModdleElement; + // if (cpme.id === cpe.id) { + // foundElement = true; + // } + // }); + // if (!foundElement) { + // correlationPropertyElement = cpe; + // } + // }); - // TODO: we should have some way to show an error if element is not found instead - // we need to check this since the code assumes each message only has one ref - // and will not display all properties if there are multiple - if (correlationPropertyElement) { - const newRetrievalExpressionElement = moddle.create( - 'bpmn:CorrelationPropertyRetrievalExpression' - ); - const messageRefElement = getMessageRefElement(element); - const newFormalExpression = moddle.create('bpmn:FormalExpression'); - newFormalExpression.body = ''; + // // TODO: we should have some way to show an error if element is not found instead + // // we need to check this since the code assumes each message only has one ref + // // and will not display all properties if there are multiple + // if (correlationPropertyElement) { + // const newRetrievalExpressionElement = moddle.create( + // 'bpmn:CorrelationPropertyRetrievalExpression' + // ); + // const messageRefElement = getMessageRefElement(element); + // const newFormalExpression = moddle.create('bpmn:FormalExpression'); + // newFormalExpression.body = ''; - newRetrievalExpressionElement.messageRef = messageRefElement; - newRetrievalExpressionElement.messagePath = newFormalExpression; + // newRetrievalExpressionElement.messageRef = messageRefElement; + // newRetrievalExpressionElement.messagePath = newFormalExpression; - if (!correlationPropertyElement.correlationPropertyRetrievalExpression) { - correlationPropertyElement.correlationPropertyRetrievalExpression = []; - } - correlationPropertyElement.correlationPropertyRetrievalExpression.push( - newRetrievalExpressionElement - ); - commandStack.execute('element.updateProperties', { - element, - properties: {}, - }); - } else { - console.error( - 'ERROR: There are not any more correlation properties this message can be added to' - ); - } - } + // if (!correlationPropertyElement.correlationPropertyRetrievalExpression) { + // correlationPropertyElement.correlationPropertyRetrievalExpression = []; + // } + // correlationPropertyElement.correlationPropertyRetrievalExpression.push( + // newRetrievalExpressionElement + // ); + // commandStack.execute('element.updateProperties', { + // element, + // properties: {}, + // }); + // } else { + // console.error( + // 'ERROR: There are not any more correlation properties this message can be added to' + // ); + // } + // } - const returnObject = { items }; - if (allCorrelationPropertyModdleElements.length !== 0) { - returnObject.add = add; - } - return returnObject; + // const returnObject = { items }; + // if (allCorrelationPropertyModdleElements.length !== 0) { + // returnObject.add = add; + // } + + // return returnObject; } -function removeFactory(props) { - const { - element, - correlationPropertyModdleElement, - correlationPropertyRetrievalExpressionModdleElement, - commandStack, - } = props; +// function removeFactory(props) { +// const { +// element, +// correlationPropertyModdleElement, +// correlationPropertyRetrievalExpressionModdleElement, +// commandStack, +// } = props; - return function (event) { - event.stopPropagation(); - removeFirstInstanceOfItemFromArrayInPlace( - correlationPropertyModdleElement.correlationPropertyRetrievalExpression, - correlationPropertyRetrievalExpressionModdleElement - ); - commandStack.execute('element.updateProperties', { - element, - properties: {}, - }); - }; -} +// return function (event) { +// event.stopPropagation(); +// removeFirstInstanceOfItemFromArrayInPlace( +// correlationPropertyModdleElement.correlationPropertyRetrievalExpression, +// correlationPropertyRetrievalExpressionModdleElement +// ); +// commandStack.execute('element.updateProperties', { +// element, +// properties: {}, +// }); +// }; +// } -function MessageCorrelationPropertyGroup(props) { - const { - idPrefix, - correlationPropertyModdleElement, - correlationPropertyRetrievalExpressionModdleElement, - translate, - moddle, - element, - commandStack, - } = props; - return [ - { - id: `${idPrefix}-correlation-key`, - component: MessageCorrelationPropertySelect, - isEdited: isTextFieldEntryEdited, - idPrefix, - correlationPropertyModdleElement, - correlationPropertyRetrievalExpressionModdleElement, - translate, - moddle, - element, - commandStack, - }, - { - id: `${idPrefix}-expression`, - component: MessageCorrelationExpressionTextField, - isEdited: isTextFieldEntryEdited, - idPrefix, - correlationPropertyRetrievalExpressionModdleElement, - translate, - }, - ]; -} +// function MessageCorrelationPropertyGroup(props) { +// const { +// idPrefix, +// correlationPropertyModdleElement, +// correlationPropertyRetrievalExpressionModdleElement, +// translate, +// moddle, +// element, +// commandStack, +// } = props; +// return [ +// { +// id: `${idPrefix}-correlation-key`, +// component: MessageCorrelationPropertySelect, +// isEdited: isTextFieldEntryEdited, +// idPrefix, +// correlationPropertyModdleElement, +// correlationPropertyRetrievalExpressionModdleElement, +// translate, +// moddle, +// element, +// commandStack, +// }, +// { +// id: `${idPrefix}-expression`, +// component: MessageCorrelationExpressionTextField, +// isEdited: isTextFieldEntryEdited, +// idPrefix, +// correlationPropertyRetrievalExpressionModdleElement, +// translate, +// }, +// ]; +// } -function MessageCorrelationPropertySelect(props) { - const { - idPrefix, - correlationPropertyModdleElement, - correlationPropertyRetrievalExpressionModdleElement, - translate, - parameter, - moddle, - element, - commandStack, - } = props; - const debounce = useService('debounceInput'); +// function MessageCorrelationPropertySelect(props) { +// const { +// idPrefix, +// correlationPropertyModdleElement, +// correlationPropertyRetrievalExpressionModdleElement, +// translate, +// parameter, +// moddle, +// element, +// commandStack, +// } = props; +// const debounce = useService('debounceInput'); - const setValue = (value) => { - const allCorrelationPropertyModdleElements = findCorrelationProperties( - correlationPropertyModdleElement, - moddle - ); - const newCorrelationPropertyElement = - allCorrelationPropertyModdleElements.find((cpe) => cpe.id === value); +// const setValue = (value) => { +// const allCorrelationPropertyModdleElements = findCorrelationProperties( +// correlationPropertyModdleElement, +// moddle +// ); +// const newCorrelationPropertyElement = +// allCorrelationPropertyModdleElements.find((cpe) => cpe.id === value); - if (!newCorrelationPropertyElement.correlationPropertyRetrievalExpression) { - newCorrelationPropertyElement.correlationPropertyRetrievalExpression = []; - } - newCorrelationPropertyElement.correlationPropertyRetrievalExpression.push( - correlationPropertyRetrievalExpressionModdleElement - ); - removeFirstInstanceOfItemFromArrayInPlace( - correlationPropertyModdleElement.correlationPropertyRetrievalExpression, - correlationPropertyRetrievalExpressionModdleElement - ); - commandStack.execute('element.updateProperties', { - element, - properties: {}, - }); - }; +// if (!newCorrelationPropertyElement.correlationPropertyRetrievalExpression) { +// newCorrelationPropertyElement.correlationPropertyRetrievalExpression = []; +// } +// newCorrelationPropertyElement.correlationPropertyRetrievalExpression.push( +// correlationPropertyRetrievalExpressionModdleElement +// ); +// removeFirstInstanceOfItemFromArrayInPlace( +// correlationPropertyModdleElement.correlationPropertyRetrievalExpression, +// correlationPropertyRetrievalExpressionModdleElement +// ); +// commandStack.execute('element.updateProperties', { +// element, +// properties: {}, +// }); +// }; - const getValue = () => { - return correlationPropertyModdleElement.id; - }; +// const getValue = () => { +// return correlationPropertyModdleElement.id; +// }; - const getOptions = () => { - const allCorrelationPropertyModdleElements = findCorrelationProperties( - correlationPropertyModdleElement, - moddle - ); - const correlationPropertyObjectsForCurrentMessage = - findCorrelationPropertiesAndRetrievalExpressionsForMessage(element); - const options = []; - for (const cpe of allCorrelationPropertyModdleElements) { - const foundElement = correlationPropertyObjectsForCurrentMessage.find( - (cpo) => { - const cpme = cpo.correlationPropertyModdleElement; - return cpme.id === cpe.id; - } - ); - if ( - !foundElement || - foundElement.correlationPropertyModdleElement === - correlationPropertyModdleElement - ) { - options.push({ - label: cpe.name, - value: cpe.id, - }); - } - } - return options; - }; +// const getOptions = () => { +// const allCorrelationPropertyModdleElements = findCorrelationProperties( +// correlationPropertyModdleElement, +// moddle +// ); +// const correlationPropertyObjectsForCurrentMessage = +// findCorrelationPropertiesAndRetrievalExpressionsForMessage(element); +// const options = []; +// for (const cpe of allCorrelationPropertyModdleElements) { +// const foundElement = correlationPropertyObjectsForCurrentMessage.find( +// (cpo) => { +// const cpme = cpo.correlationPropertyModdleElement; +// return cpme.id === cpe.id; +// } +// ); +// if ( +// !foundElement || +// foundElement.correlationPropertyModdleElement === +// correlationPropertyModdleElement +// ) { +// options.push({ +// label: cpe.name, +// value: cpe.id, +// }); +// } +// } +// return options; +// }; - return SelectEntry({ - id: `${idPrefix}-select`, - element: parameter, - label: translate('Correlation Property'), - getValue, - setValue, - getOptions, - debounce, - }); -} +// return SelectEntry({ +// id: `${idPrefix}-select`, +// element: parameter, +// label: translate('Correlation Property'), +// getValue, +// setValue, +// getOptions, +// debounce, +// }); +// } -function MessageCorrelationExpressionTextField(props) { - const { - idPrefix, - parameter, - correlationPropertyRetrievalExpressionModdleElement, - translate, - } = props; +// function MessageCorrelationExpressionTextField(props) { +// const { +// idPrefix, +// parameter, +// correlationPropertyRetrievalExpressionModdleElement, +// translate, +// } = props; - const debounce = useService('debounceInput'); +// const debounce = useService('debounceInput'); - const setValue = (value) => { - correlationPropertyRetrievalExpressionModdleElement.messagePath.body = - value; - }; +// const setValue = (value) => { +// correlationPropertyRetrievalExpressionModdleElement.messagePath.body = +// value; +// }; - const getValue = (_parameter) => { - return correlationPropertyRetrievalExpressionModdleElement.messagePath.body; - }; +// const getValue = (_parameter) => { +// return correlationPropertyRetrievalExpressionModdleElement.messagePath.body; +// }; - return TextFieldEntry({ - element: parameter, - id: `${idPrefix}-textField`, - label: translate('Expression'), - getValue, - setValue, - debounce, - }); -} +// return TextFieldEntry({ +// element: parameter, +// id: `${idPrefix}-textField`, +// label: translate('Expression'), +// getValue, +// setValue, +// debounce, +// }); +// } diff --git a/app/spiffworkflow/messages/propertiesPanel/MessagePayload.jsx b/app/spiffworkflow/messages/propertiesPanel/MessagePayload.jsx deleted file mode 100644 index 4481f16..0000000 --- a/app/spiffworkflow/messages/propertiesPanel/MessagePayload.jsx +++ /dev/null @@ -1,65 +0,0 @@ -import React from 'react'; -import { useService } from 'bpmn-js-properties-panel'; -import { TextAreaEntry } from '@bpmn-io/properties-panel'; -import { getMessageElementForShapeElement } from '../MessageHelpers'; - -/** - * Allows the creation, or editing of messagePayload at the bpmn:sendTask level of a BPMN document. - */ -export function MessagePayload(props) { - const shapeElement = props.element; - const debounce = useService('debounceInput'); - const messageElement = getMessageElementForShapeElement(shapeElement); - const disabled = !messageElement; - - const getMessagePayloadObject = () => { - if (messageElement) { - const { extensionElements } = messageElement; - if (extensionElements) { - return messageElement.extensionElements - .get('values') - .filter(function getInstanceOfType(e) { - return e.$instanceOf('spiffworkflow:MessagePayload'); - })[0]; - } - } - return null; - }; - - const getValue = () => { - const messagePayloadObject = getMessagePayloadObject(); - if (messagePayloadObject) { - return messagePayloadObject.value; - } - return ''; - }; - - const setValue = (value) => { - let messagePayloadObject = getMessagePayloadObject(); - if (!messagePayloadObject) { - messagePayloadObject = messageElement.$model.create( - 'spiffworkflow:MessagePayload', - ); - if (!messageElement.extensionElements) { - messageElement.extensionElements = messageElement.$model.create( - 'bpmn:ExtensionElements', - ); - } - messageElement.extensionElements.get('values').push(messagePayloadObject); - } - messagePayloadObject.value = value; - }; - - return ( - - ); -} diff --git a/app/spiffworkflow/messages/propertiesPanel/MessageSelect.jsx b/app/spiffworkflow/messages/propertiesPanel/MessageSelect.jsx deleted file mode 100644 index 0777616..0000000 --- a/app/spiffworkflow/messages/propertiesPanel/MessageSelect.jsx +++ /dev/null @@ -1,87 +0,0 @@ -import React from 'react'; -import { useService } from 'bpmn-js-properties-panel'; -import { SelectEntry } from '@bpmn-io/properties-panel'; -import { - findMessageModdleElements, - getMessageRefElement, - isMessageEvent, -} from '../MessageHelpers'; - -/** - * Allows the selection, or creation, of Message at the Definitions level of a BPMN document. - */ -export function MessageSelect(props) { - const shapeElement = props.element; - const { commandStack } = props; - const debounce = useService('debounceInput'); - - const getValue = () => { - const messageRefElement = getMessageRefElement(shapeElement); - if (messageRefElement) { - return messageRefElement.id; - } - return ''; - }; - - const setValue = (value) => { - /* Need to add the selected message as the messageRef on the current message task */ - const { businessObject } = shapeElement; - const messages = findMessageModdleElements(shapeElement.businessObject); - for (const message of messages) { - if (message.id === value) { - if (isMessageEvent(shapeElement)) { - const messageEventDefinition = businessObject.eventDefinitions[0]; - messageEventDefinition.messageRef = message; - // call this to update the other elements in the props panel like payload - commandStack.execute('element.updateModdleProperties', { - element: shapeElement, - moddleElement: businessObject, - properties: { - messageRef: message, - }, - }); - } else if ( - businessObject.$type === 'bpmn:ReceiveTask' || - businessObject.$type === 'bpmn:SendTask' - ) { - commandStack.execute('element.updateModdleProperties', { - element: shapeElement, - moddleElement: businessObject, - properties: { - messageRef: message, - }, - }); - commandStack.execute('element.updateProperties', { - element: shapeElement, - moddleElement: businessObject, - properties: { - messageRef: message, - }, - }); - } - } - } - }; - - const getOptions = (_value) => { - const messages = findMessageModdleElements(shapeElement.businessObject); - const options = []; - for (const message of messages) { - options.push({ label: message.name, value: message.id }); - } - return options; - }; - - return ( - - ); -} diff --git a/app/spiffworkflow/messages/propertiesPanel/MessagesPropertiesProvider.js b/app/spiffworkflow/messages/propertiesPanel/MessagesPropertiesProvider.js old mode 100644 new mode 100755 index 6abf6c7..1fb92e9 --- a/app/spiffworkflow/messages/propertiesPanel/MessagesPropertiesProvider.js +++ b/app/spiffworkflow/messages/propertiesPanel/MessagesPropertiesProvider.js @@ -1,13 +1,8 @@ -import { ListGroup, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; import { is } from 'bpmn-js/lib/util/ModelUtil'; -import { CorrelationKeysArray } from './CorrelationKeysArray'; -import { MessageSelect } from './MessageSelect'; -import { MessagePayload } from './MessagePayload'; -import { MessageVariable } from './MessageVariable'; -import { CorrelationPropertiesArray } from './CorrelationPropertiesArray'; -import { MessageCorrelationPropertiesArray } from './MessageCorrelationPropertiesArray'; -import { MessageArray } from './MessageArray'; -import { isMessageElement, canReceiveMessage } from '../MessageHelpers'; +import { isMessageElement } from '../MessageHelpers'; + +import { createCollaborationGroup } from './processLevelProvider/CollaborationPropertiesProvider'; +import { createMessageGroup } from './elementLevelProvider/TaskEventMessageProvider'; const LOW_PRIORITY = 500; @@ -20,23 +15,24 @@ export default function MessagesPropertiesProvider( ) { this.getGroups = function getGroupsCallback(element) { return function pushGroup(groups) { - if (is(element, 'bpmn:Collaboration')) { - groups.push( - ...createCollaborationGroup( - element, - translate, - moddle, - commandStack, - elementRegistry - ) - ); - } else if (isMessageElement(element)) { + // if (is(element, 'bpmn:Collaboration') || is(element, 'bpmn:Process')) { + // groups.push( + // ...createCollaborationGroup( + // element, + // translate, + // moddle, + // commandStack, + // elementRegistry + // ) + // ); + // } else + if (isMessageElement(element)) { const messageIndex = findEntry(groups, 'message'); if (messageIndex) { groups.splice(messageIndex, 1); } groups.push( - createMessageGroup( + ...createMessageGroup( element, translate, moddle, @@ -58,6 +54,7 @@ export default function MessagesPropertiesProvider( }); return entryIndex; } + propertiesPanel.registerProvider(LOW_PRIORITY, this); } @@ -67,120 +64,4 @@ MessagesPropertiesProvider.$inject = [ 'moddle', 'commandStack', 'elementRegistry', -]; - -/** - * Adds a group to the properties panel for the script task that allows you - * to set the script. - * @param element - * @param translate - * @returns The components to add to the properties panel. */ -function createCollaborationGroup( - element, - translate, - moddle, - commandStack, - elementRegistry -) { - return [ - { - id: 'correlation_keys', - label: translate('Correlation Keys'), - component: ListGroup, - ...CorrelationKeysArray({ - element, - moddle, - commandStack, - elementRegistry, - translate, - }), - }, - { - id: 'correlation_properties', - label: translate('Correlation Properties'), - component: ListGroup, - ...CorrelationPropertiesArray({ - element, - moddle, - commandStack, - elementRegistry, - translate, - }), - }, - { - id: 'messages', - label: translate('Messages'), - component: ListGroup, - ...MessageArray({ - element, - moddle, - commandStack, - elementRegistry, - translate, - }), - }, - ]; -} - -/** - * Adds a group to the properties panel for editing messages for the SendTask - * @param element - * @param translate - * @returns The components to add to the properties panel. */ -function createMessageGroup( - element, - translate, - moddle, - commandStack, - elementRegistry -) { - const entries = [ - { - id: 'selectMessage', - element, - component: MessageSelect, - isEdited: isTextFieldEntryEdited, - moddle, - commandStack, - }, - ]; - - if (canReceiveMessage(element)) { - entries.push({ - id: 'messageVariable', - element, - component: MessageVariable, - isEdited: isTextFieldEntryEdited, - moddle, - commandStack, - }); - } else { - entries.push({ - id: 'messagePayload', - element, - component: MessagePayload, - isEdited: isTextFieldEntryEdited, - moddle, - commandStack, - }); - } - - entries.push({ - id: 'correlationProperties', - label: translate('Correlation'), - component: ListGroup, - ...MessageCorrelationPropertiesArray({ - element, - moddle, - commandStack, - elementRegistry, - translate, - }), - }); - - return { - id: 'messages', - label: translate('Message'), - entries, - }; -} +]; \ No newline at end of file diff --git a/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/CorrelationCheckbox.jsx b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/CorrelationCheckbox.jsx new file mode 100755 index 0000000..d5f0e28 --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/CorrelationCheckbox.jsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { useService } from 'bpmn-js-properties-panel'; +import { CheckboxEntry } from '@bpmn-io/properties-panel'; + +/** + * A generic properties' editor for text area. + */ +export function CorrelationCheckboxEntry(props) { + const { element, commandStack, moddle } = props; + const { name, label, description } = props; + const { businessObject } = element; + + const debounce = useService('debounceInput'); + + const getValue = () => { + const value = businessObject.get('isCorrelated') + ? businessObject.get('isCorrelated') + : false; + return value; + }; + + const setValue = (value) => { + commandStack.execute('element.updateProperties', { + element, + properties: { + isCorrelated: value, + }, + }); + }; + + return ( + + ); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/CorrelationPropertiesList.js b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/CorrelationPropertiesList.js new file mode 100755 index 0000000..8002162 --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/CorrelationPropertiesList.js @@ -0,0 +1,189 @@ +import { + isTextFieldEntryEdited, + TextFieldEntry, +} from '@bpmn-io/properties-panel'; +import { + getRoot, + findCorrelationKeyForCorrelationProperty, + findCorrelationPropertiesByMessage, + isMessageEvent, + createNewCorrelationProperty, + getMessageRefElement +} from '../../MessageHelpers'; +import { removeFirstInstanceOfItemFromArrayInPlace } from '../../../helpers'; +import { useService } from 'bpmn-js-properties-panel'; + +/** + * Allows the creation, or editing of messageCorrelations at the bpmn:sendTask level of a BPMN document. + */ +export function CorrelationPropertiesList(props) { + const { moddle } = props; + const { element } = props; + const { commandStack } = props; + const { translate } = props; + + const correlationPropertyArray = findCorrelationPropertiesByMessage( + element + ); + + const items = (correlationPropertyArray) ? correlationPropertyArray.map( + (correlationPropertyModdleElement, index) => { + + const id = `correlation-${index}`; + + const entries = MessageCorrelationPropertyGroup({ + idPrefix: id, + correlationPropertyModdleElement, + translate, + element, + commandStack, + moddle, + }); + + return { + id, + label: correlationPropertyModdleElement.name, + entries, + autoFocusEntry: id, + // remove: removeFactory({ + // element, + // correlationPropertyModdleElement, + // commandStack, + // moddle, + // }), + }; + } + ): []; + + function add(event) { + + event.stopPropagation(); + + const messageRef = getMessageRefElement(element); + + if(!messageRef){ + alert('Please select a message'); + return; + } + + createNewCorrelationProperty(element, moddle, commandStack, messageRef); + + } + + return { items, add }; +} + +function removeFactory(props) { + const { element, correlationPropertyModdleElement, moddle, commandStack } = props; + + return function (event) { + event.stopPropagation(); + const rootElement = getRoot(element.businessObject); + const { rootElements } = rootElement; + + const oldCorrelationKeyElement = findCorrelationKeyForCorrelationProperty( + correlationPropertyModdleElement, + moddle + ); + if (oldCorrelationKeyElement) { + removeFirstInstanceOfItemFromArrayInPlace( + oldCorrelationKeyElement.correlationPropertyRef, + correlationPropertyModdleElement + ); + } + + removeFirstInstanceOfItemFromArrayInPlace( + rootElements, + correlationPropertyModdleElement + ); + commandStack.execute('element.updateProperties', { + element, + properties: { + messages: rootElements, + }, + }); + }; +} + +function MessageCorrelationPropertyGroup(props) { + const { + idPrefix, + correlationPropertyModdleElement, + translate, + element, + commandStack, + moddle, + } = props; + return [ + { + id: `${idPrefix}-correlation-property-retrivial-expression`, + component: CorrelationPropertyRetrivialExpressionTextField, + isEdited: isTextFieldEntryEdited, + idPrefix, + element, + correlationPropertyModdleElement, + translate, + commandStack + }, + ]; +} + +function CorrelationPropertyRetrivialExpressionTextField(props) { + const { + id, + element, + correlationPropertyModdleElement, + commandStack, + translate, + idPrefix + } = props; + + const debounce = useService('debounceInput'); + + const setValue = (value) => { + + const message = (isMessageEvent(element)) ? element.businessObject.eventDefinitions[0].messageRef : element.businessObject.messageRef; + const process = element.businessObject.$parent; + const definitions = process.$parent; + + if (!definitions.get('rootElements')) { + definitions.set('rootElements', []); + } + definitions.rootElements.forEach(rootElement => { + if(rootElement.id == correlationPropertyModdleElement.id && rootElement.$type == 'bpmn:CorrelationProperty'){ + const matchingRetrievalExpression = rootElement.correlationPropertyRetrievalExpression.find(expr => + expr.messageRef && expr.messageRef === message + ); + if(matchingRetrievalExpression){ + matchingRetrievalExpression.messagePath.body = value; + commandStack.execute('element.updateProperties', { + element, + properties: {}, + }); + return; + } + } + }); + + }; + + const getValue = () => { + + const message = (isMessageEvent(element)) ? element.businessObject.eventDefinitions[0].messageRef : element.businessObject.messageRef; + + const matchingRetrievalExpression = correlationPropertyModdleElement.correlationPropertyRetrievalExpression.find(expr => + expr.messageRef && expr.messageRef === message + ); + + return (matchingRetrievalExpression) ? matchingRetrievalExpression.messagePath.body : '' ; + }; + + return TextFieldEntry({ + element, + id: `${id}-name-xp-textField`, + label: translate('Retrivial Expression'), + getValue, + setValue, + debounce + }); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MatchingConditionArray.js b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MatchingConditionArray.js new file mode 100755 index 0000000..35d5e96 --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MatchingConditionArray.js @@ -0,0 +1,117 @@ +import { useService } from 'bpmn-js-properties-panel'; +import { + TextFieldEntry, + DescriptionEntry +} from '@bpmn-io/properties-panel'; +import { + findCorrelationPropertiesByMessage, isMessageEvent, +} from '../../MessageHelpers'; + +/** + * Matching correlation conditions + */ +export function MatchingCorrelationEntries(props) { + const { + idPrefix, + translate, + element, + commandStack, + moddle, + } = props; + + const correlationPropertyArray = findCorrelationPropertiesByMessage( + element + ); + + const entries = (correlationPropertyArray && correlationPropertyArray.length !== 0) ? correlationPropertyArray.map( + (correlationPropertyModdleElement, index) => { + return { + id: `${idPrefix}-correlation-property-name`, + component: MatchingConditionTextField, + correlationPropertyModdleElement, + element, + translate, + commandStack, + moddle + }; + } + ) : [{ + id: `${idPrefix}-name-textField`, + component: DescriptionEntry, + value: 'ℹ️ No matching conditions can be established since the selected message has no correlation properties', + element, + translate, + commandStack, + }]; + + return { entries }; +} + +function MatchingConditionTextField(props) { + const { + id, + element, + commandStack, + translate, + correlationPropertyModdleElement, + moddle + } = props; + + const debounce = useService('debounceInput'); + + const getVariableCorrelationObject = () => { + if (element) { + const { extensionElements } = (isMessageEvent(element)) ? element.businessObject.eventDefinitions[0] : element.businessObject; + if (extensionElements) { + return extensionElements + .get('values') + .filter(function getInstanceOfType(e) { + return e.$instanceOf('spiffworkflow:ProcessVariableCorrelation') && + e.propertyId === correlationPropertyModdleElement.id; + })[0]; + } + } + return null; + }; + + const setValue = (value) => { + var extensions = (isMessageEvent(element)) ? + element.businessObject.eventDefinitions[0].get('extensionElements') || moddle.create('bpmn:ExtensionElements') : + element.businessObject.get('extensionElements') || moddle.create('bpmn:ExtensionElements'); + + let variableCorrelationObject = getVariableCorrelationObject(); + + if (!variableCorrelationObject) { + variableCorrelationObject = moddle.create('spiffworkflow:ProcessVariableCorrelation', { + propertyId: correlationPropertyModdleElement.id, + expression: value + }); + extensions + .get('values') + .push(variableCorrelationObject); + } + variableCorrelationObject.expression = value; + (isMessageEvent(element)) ? element.businessObject.eventDefinitions[0].set('extensionElements', extensions) : element.businessObject.set('extensionElements', extensions); + commandStack.execute('element.updateProperties', { + element, + properties: {}, + }); + }; + + const getValue = () => { + const variableCorrelationObject = getVariableCorrelationObject(); + if (variableCorrelationObject && variableCorrelationObject.propertyId === correlationPropertyModdleElement.id) { + return variableCorrelationObject.expression; + } + return ''; + }; + + return TextFieldEntry({ + element, + id: `${id}-name-textField`, + label: translate(correlationPropertyModdleElement.id), + getValue, + setValue, + debounce, + }); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MatchingCorrelationCheckbox.jsx b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MatchingCorrelationCheckbox.jsx new file mode 100755 index 0000000..e64260e --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MatchingCorrelationCheckbox.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { useService } from 'bpmn-js-properties-panel'; +import { CheckboxEntry } from '@bpmn-io/properties-panel'; + +/** + * A generic properties' editor for text area. + */ +export function MatchingCorrelationCheckboxEntry(props) { + const { element, commandStack, moddle } = props; + const { name, label, description } = props; + const { businessObject } = element; + + const debounce = useService('debounceInput'); + + const getValue = () => { + const isMatchingCorrelation = businessObject.get('spiffworkflow:isMatchingCorrelation'); + const value = isMatchingCorrelation && isMatchingCorrelation !== 'false' + ? true + : false; + return value; + }; + + const setValue = (value) => { + commandStack.execute('element.updateProperties', { + element, + properties: { + 'spiffworkflow:isMatchingCorrelation': value, + }, + }); + }; + + return ( + + ); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageJsonSchemaSelect.js b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageJsonSchemaSelect.js new file mode 100755 index 0000000..7d34b98 --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageJsonSchemaSelect.js @@ -0,0 +1,134 @@ +import { useService } from 'bpmn-js-properties-panel'; +import { SelectEntry } from '@bpmn-io/properties-panel'; +import { getMessageRefElement, getRoot } from '../../MessageHelpers'; + +export const spiffExtensionOptions = {}; + +export function MessageJsonSchemaSelect(props) { + + const { id, label, description } = props; + + const { element } = props; + const { commandStack } = props; + + const debounce = useService('debounceInput'); + const eventBus = useService('eventBus'); + const bpmnFactory = useService('bpmnFactory'); + + const optionType = "messages_schemas" + + const getValue = () => { + + const { businessObject } = element; + + const msgRef = getMessageRefElement(element); + if (!msgRef) { + return ''; + } + + let definitions = getRoot(businessObject); + if (!definitions.get('rootElements')) { + definitions.set('rootElements', []); + } + + // Retrieve Message + let bpmnMessage = definitions.get('rootElements').find(element => + element.$type === 'bpmn:Message' && (element.id === msgRef.id || element.name === msgRef.id) + ); + + if (!bpmnMessage) { + return ''; + } + + return bpmnMessage.get('jsonSchemaId'); + }; + + const setValue = (value) => { + + const { businessObject } = element; + const msgRef = getMessageRefElement(element); + + if (!msgRef) { + alert('Please select a message'); + return; + } + + let definitions = getRoot(businessObject); + if (!definitions.get('rootElements')) { + definitions.set('rootElements', []); + } + + // Retrieve Message + let bpmnMessage = definitions.get('rootElements').find(element => + element.$type === 'bpmn:Message' && (element.id === msgRef.id || element.name === msgRef.id) + ); + bpmnMessage.set('jsonSchemaId', value); + + // let extensions = businessObject.extensionElements; + // if (!extensions) { + // extensions = moddle.create('bpmn:ExtensionElements'); + // extensions.values = [] + // } + // const properties = moddle.create( + // MESSAGE_JSONSCHEMA_PARAMETER_ELEMENT_NAME + // ); + // properties.values = [] + // const property = moddle.create( + // 'spiffworkflow:Property' + // ); + // property.name = "jsonSchemaId"; + // property.value = value; + // properties.values.push(property) + // extensions.values.push(properties) + // let definitions = getRoot(businessObject); + // if (!definitions.get('rootElements')) { + // definitions.set('rootElements', []); + // } + }; + + if ( + !(optionType in spiffExtensionOptions) || + spiffExtensionOptions[optionType] === null + ) { + spiffExtensionOptions[optionType] = null; + requestOptions(eventBus, element, commandStack, optionType); + } + + const getOptions = () => { + const optionList = []; + // optionList.push({ + // label: '', + // value: '', + // }); + if ( + optionType in spiffExtensionOptions && + spiffExtensionOptions[optionType] !== null + ) { + spiffExtensionOptions[optionType].forEach((opt) => { + optionList.push({ + label: opt.schema_id, + value: opt.schema_id, + }); + }); + } + return optionList; + }; + + return SelectEntry({ + id, + element, + label, + description, + getValue, + setValue, + getOptions, + debounce, + }); +} + +function requestOptions(eventBus, element, commandStack, optionType) { + eventBus.on('spiff.message_schemas.returned', (event) => { + spiffExtensionOptions[optionType] = event.options; + }); + eventBus.fire(`spiff.message_schemas.requested`, { eventBus }); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageLaunchEditorButton.js b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageLaunchEditorButton.js new file mode 100755 index 0000000..58ee02b --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageLaunchEditorButton.js @@ -0,0 +1,57 @@ +import { HeaderButton } from '@bpmn-io/properties-panel'; +import { useService } from 'bpmn-js-properties-panel'; +import { + findCorrelationPropertiesAndRetrievalExpressionsForMessage, + getMessageRefElement, +} from '../../MessageHelpers'; + +/** + * Sends a notification to the host application saying the user + * would like to edit something. Hosting application can then + * update the value and send it back. + */ +export function MessageLaunchEditorButton(props) { + const { element, moddle } = props; + + const sendEvent = 'spiff.message.edit'; + const listenEvent = 'spiff.message.update'; + + const eventBus = useService('eventBus'); + + const messageRef = getMessageRefElement(element); + const correlationProperties = + findCorrelationPropertiesAndRetrievalExpressionsForMessage(element); + const parsedCorrelationProperties = correlationProperties.map((item) => ({ + id: item.correlationPropertyModdleElement.id, + retrievalExpression: + item.correlationPropertyRetrievalExpressionModdleElement.messagePath.body, + })); + + let messageId = null; + if (messageRef && messageRef.id) { + messageId = messageRef.id; + } + if (messageRef && messageRef.name && messageRef.name !== messageId) { + messageId = messageRef.name; + } + return HeaderButton({ + className: 'spiffworkflow-properties-panel-button', + id: `message_launch_message_editor_button`, + onClick: () => { + eventBus.fire(sendEvent, { + value: { + messageId, + correlation_properties: parsedCorrelationProperties, + }, + eventBus, + listenEvent, + }); + + // Listen for a response, to update the script. + eventBus.once(listenEvent, (response) => { + messageRef.id = response.value; + }); + }, + children: 'Open message editor', + }); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessagePayload.jsx b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessagePayload.jsx new file mode 100755 index 0000000..3831ad8 --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessagePayload.jsx @@ -0,0 +1,104 @@ +import React from 'react'; +import { useService } from 'bpmn-js-properties-panel'; +import { TextAreaEntry } from '@bpmn-io/properties-panel'; +import { + getMessageElementForShapeElement, + isMessageEvent, +} from '../../MessageHelpers'; + +/** + * Allows the creation, or editing of messagePayload at the bpmn:sendTask level of a BPMN document. + */ +export function MessagePayload(props) { + const shapeElement = props.element; + const { moddle, element, commandStack } = props; + const debounce = useService('debounceInput'); + const messageElement = getMessageElementForShapeElement(shapeElement); + const disabled = !messageElement; + + const getMessagePayloadObject = () => { + if (element) { + const { extensionElements } = isMessageEvent(element) + ? element.businessObject.eventDefinitions[0] + : element.businessObject; + if (extensionElements && extensionElements.get('values')) { + let payloadResp = extensionElements + .get('values') + .filter(function getInstanceOfType(e) { + return e.$instanceOf('spiffworkflow:MessagePayload'); + })[0]; + return payloadResp; + } + } + return null; + }; + + const getValue = () => { + const messagePayloadObject = getMessagePayloadObject(); + if (messagePayloadObject) { + return messagePayloadObject.value; + } else { + // Check : for old models where payload exists on message level + const bo = isMessageEvent(element) + ? element.businessObject.eventDefinitions[0] + : element.businessObject; + + const { messageRef } = bo; + if (messageRef) { + const { extensionElements } = messageRef; + const payloadResp = (extensionElements) ? extensionElements + .get('values') + .filter(function getInstanceOfType(e) { + return e.$instanceOf('spiffworkflow:MessagePayload'); + })[0] : undefined; + + if (payloadResp) { + setValue(payloadResp.value); + return payloadResp.value; + } + } + } + return ''; + }; + + const setValue = (value) => { + + var extensions = isMessageEvent(element) + ? element.businessObject.eventDefinitions[0].get('extensionElements') || + moddle.create('bpmn:ExtensionElements') + : element.businessObject.get('extensionElements') || + moddle.create('bpmn:ExtensionElements'); + + let messagePayloadObject = getMessagePayloadObject(); + if (!messagePayloadObject) { + messagePayloadObject = moddle.create('spiffworkflow:MessagePayload'); + extensions.get('values').push(messagePayloadObject); + } + messagePayloadObject.value = value; + + isMessageEvent(element) + ? element.businessObject.eventDefinitions[0].set( + 'extensionElements', + extensions + ) + : element.businessObject.set('extensionElements', extensions); + + commandStack.execute('element.updateProperties', { + element, + properties: {}, + }); + }; + + return ( + + ); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageSelect.jsx b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageSelect.jsx new file mode 100755 index 0000000..a773006 --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageSelect.jsx @@ -0,0 +1,206 @@ +import React from 'react'; +import { useService } from 'bpmn-js-properties-panel'; +import { SelectEntry } from '@bpmn-io/properties-panel'; +import { + createOrUpdateCorrelationProperties, + createOrUpdateCorrelationPropertiesV2, + findMessageModdleElements, + getMessageRefElement, + getRoot, + isMessageElement, + isMessageEvent, + isMessageRefUsed, + setParentCorrelationKeys, + synCorrleationProperties, +} from '../../MessageHelpers'; + +export const spiffExtensionOptions = {}; + +/** + * Allows the selection, or creation, of Message at the Definitions level of a BPMN document. + */ +export function MessageSelect(props) { + const shapeElement = props.element; + const { commandStack, element, moddle } = props; + const debounce = useService('debounceInput'); + const eventBus = useService('eventBus'); + const bpmnFactory = useService('bpmnFactory'); + + const getValue = () => { + const messageRefElement = getMessageRefElement(shapeElement); + if (messageRefElement) { + return messageRefElement.id; + } + return ''; + }; + + const setValue = async (value) => { + + // Define variables + const messageId = value; + const { businessObject } = element; + let oldMessageRef = (businessObject.eventDefinitions) ? businessObject.eventDefinitions[0].messageRef : businessObject.messageRef; + let definitions = getRoot(element.businessObject); + if (!definitions || !definitions.get('rootElements')) { + definitions.set('rootElements', []); + } + + // Retrieve Message + let bpmnMessage = definitions + .get('rootElements') + .find( + (element) => + element.$type === 'bpmn:Message' && + (element.id === messageId || element.name === messageId), + ); + + // If the Message doesn't exist, create new one + if (!bpmnMessage) { + bpmnMessage = bpmnFactory.create('bpmn:Message', { + id: messageId, + name: messageId, + }); + definitions.get('rootElements').push(bpmnMessage); + } + + // Update messageRef of current Element + if (isMessageEvent(shapeElement)) { + element.businessObject.eventDefinitions[0].set( + 'extensionElements', + moddle.create('bpmn:ExtensionElements'), + ); // Clear extension element + const messageEventDefinition = element.businessObject.eventDefinitions[0]; + messageEventDefinition.messageRef = bpmnMessage; + // call this to update the other elements in the props panel like payload + commandStack.execute('element.updateModdleProperties', { + element: element, + moddleElement: element.businessObject, + properties: {}, + }); + } else if (isMessageElement(shapeElement)) { + element.businessObject.set( + 'extensionElements', + moddle.create('bpmn:ExtensionElements'), + ); // Clear extension element + element.businessObject.messageRef = bpmnMessage; + commandStack.execute('element.updateProperties', { + element: element, + properties: {}, + }); + } + + // Add Correlation Properties of for the new message + const msgObject = spiffExtensionOptions['spiff.messages'] + ? spiffExtensionOptions['spiff.messages'].find( + (msg) => msg.identifier === messageId, + ) + : undefined; + + if (msgObject) { + createOrUpdateCorrelationPropertiesV2( + bpmnFactory, + commandStack, + element, + msgObject['correlation_properties'], + messageId, + ); + } + + if (oldMessageRef) { + + // Remove previous message in case it's not used anymore + const isOldMessageUsed = isMessageRefUsed(definitions, oldMessageRef.id); + if (!isOldMessageUsed) { + const rootElements = definitions.get('rootElements'); + const oldMessageIndex = rootElements.findIndex( + (element) => + element.$type === 'bpmn:Message' && element.id === oldMessageRef.id, + ); + if (oldMessageIndex !== -1) { + rootElements.splice(oldMessageIndex, 1); + definitions.rootElements = rootElements; + } + } + + // Automatic deletion of previous message correlation properties + synCorrleationProperties(element, definitions, moddle); + } + + // Update Correlation key if Process has collaboration + try { + setParentCorrelationKeys(definitions, bpmnFactory, element, moddle); + } catch (error) { + console.error('Error Caught while synchronizing Correlation key', error); + } + + }; + + eventBus.on('spiff.add_message.returned', (event) => { + const cProperties = Object.entries(event.correlation_properties).map(([identifier, properties]) => ({ + identifier, + retrieval_expression: properties.retrieval_expressions[0] + })); + let newMsg = { + identifier: event.name, + correlation_properties: cProperties + }; + spiffExtensionOptions['spiff.messages'] = (Array.isArray(spiffExtensionOptions['spiff.messages']) && spiffExtensionOptions['spiff.messages']) ? spiffExtensionOptions['spiff.messages'] : []; + spiffExtensionOptions['spiff.messages'].push(newMsg); + setValue(event.name); + }); + + requestOptions(eventBus, bpmnFactory, element, moddle); + + const getOptions = () => { + // Load messages from XML + const options = []; + const messages = findMessageModdleElements(shapeElement.businessObject); + for (const message of messages) { + options.push({ label: message.name, value: message.id }); + } + + // Load messages from API + if ( + spiffExtensionOptions['spiff.messages'] && + spiffExtensionOptions['spiff.messages'] !== null + ) { + spiffExtensionOptions['spiff.messages'].forEach((opt) => { + options.push({ + label: opt.identifier, + value: opt.identifier, + }); + }); + } + + // Remove duplicated options + const uniqueArray = removeDuplicatesByLabel(options); + return uniqueArray; + }; + + return ( + + ); +} + +function requestOptions(eventBus, bpmnFactory, element, moddle) { + eventBus.on(`spiff.messages.returned`, (event) => { + spiffExtensionOptions['spiff.messages'] = event.configuration.messages; + }); + eventBus.fire(`spiff.messages.requested`, { eventBus }); +} + +function removeDuplicatesByLabel(array) { + const seen = new Map(); + return array.filter((item) => { + return seen.has(item.label) ? false : seen.set(item.label, true); + }); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/MessageVariable.jsx b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageVariable.jsx old mode 100644 new mode 100755 similarity index 62% rename from app/spiffworkflow/messages/propertiesPanel/MessageVariable.jsx rename to app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageVariable.jsx index 41610b8..cf3dfdf --- a/app/spiffworkflow/messages/propertiesPanel/MessageVariable.jsx +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/MessageVariable.jsx @@ -1,22 +1,23 @@ import React from 'react'; import { useService } from 'bpmn-js-properties-panel'; import { TextFieldEntry } from '@bpmn-io/properties-panel'; -import { getMessageElementForShapeElement } from '../MessageHelpers'; +import { getMessageElementForShapeElement, isMessageEvent } from '../../MessageHelpers'; /** * Allows the creation, or editing of messageVariable at the bpmn:sendTask level of a BPMN document. */ export function MessageVariable(props) { const shapeElement = props.element; + const { moddle, element, commandStack } = props; const debounce = useService('debounceInput'); const messageElement = getMessageElementForShapeElement(shapeElement); const disabled = !messageElement; const getMessageVariableObject = () => { - if (messageElement) { - const { extensionElements } = messageElement; + if (element) { + const { extensionElements } = (isMessageEvent(element)) ? element.businessObject.eventDefinitions[0] : element.businessObject; if (extensionElements) { - return messageElement.extensionElements + return extensionElements .get('values') .filter(function getInstanceOfType(e) { return e.$instanceOf('spiffworkflow:MessageVariable'); @@ -35,21 +36,25 @@ export function MessageVariable(props) { }; const setValue = (value) => { + var extensions = (isMessageEvent(element)) ? + element.businessObject.eventDefinitions[0].get('extensionElements') || moddle.create('bpmn:ExtensionElements') : + element.businessObject.get('extensionElements') || moddle.create('bpmn:ExtensionElements'); + let messageVariableObject = getMessageVariableObject(); if (!messageVariableObject) { - messageVariableObject = messageElement.$model.create( + messageVariableObject = moddle.create( 'spiffworkflow:MessageVariable' ); - if (!messageElement.extensionElements) { - messageElement.extensionElements = messageElement.$model.create( - 'bpmn:ExtensionElements' - ); - } - messageElement.extensionElements + extensions .get('values') .push(messageVariableObject); } messageVariableObject.value = value; + (isMessageEvent(element)) ? element.businessObject.eventDefinitions[0].set('extensionElements', extensions) : element.businessObject.set('extensionElements', extensions); + commandStack.execute('element.updateProperties', { + element, + properties: {}, + }); }; return ( diff --git a/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/TaskEventMessageProvider.js b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/TaskEventMessageProvider.js new file mode 100755 index 0000000..9453d53 --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/elementLevelProvider/TaskEventMessageProvider.js @@ -0,0 +1,199 @@ +import { useService } from "bpmn-js-properties-panel"; +import { HeaderButton, ListGroup, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; +import { canReceiveMessage, getMessageRefElement, getRoot } from "../../MessageHelpers"; +import { CorrelationPropertiesList } from './CorrelationPropertiesList'; +import { MessageSelect } from './MessageSelect'; +import { MessagePayload } from './MessagePayload'; +import { CorrelationCheckboxEntry } from './CorrelationCheckbox'; +import { MessageJsonSchemaSelect } from './MessageJsonSchemaSelect'; +import { MessageVariable } from './MessageVariable'; +import { MessageLaunchEditorButton } from "./MessageLaunchEditorButton"; +import { MatchingCorrelationEntries } from "./MatchingConditionArray"; +import { MatchingCorrelationCheckboxEntry } from "./MatchingCorrelationCheckbox"; + +/** + * Adds a group to the properties panel for editing messages for the SendTask + * @param element + * @param translate + * @returns The components to add to the properties panel. */ +export function createMessageGroup( + element, + translate, + moddle, + commandStack, + elementRegistry +) { + + const { businessObject } = element; + + const entries = [ + { + id: 'selectMessage', + element, + component: MessageSelect, + isEdited: isTextFieldEntryEdited, + moddle, + commandStack, + }, + { + id: 'messageLaunchEditorButton', + element, + translate, + component: MessageLaunchEditorButton, + moddle + } + ]; + + if (canReceiveMessage(element)) { + entries.push({ + id: 'messageVariable', + element, + component: MessageVariable, + isEdited: isTextFieldEntryEdited, + moddle, + commandStack, + }); + } else { + entries.push({ + id: 'messagePayload', + element, + component: MessagePayload, + isEdited: isTextFieldEntryEdited, + moddle, + commandStack, + }); + } + + if (canReceiveMessage(element)) { + // Given the user the possibility to either enable/disable showing correlations conditions. + entries.push({ + id: 'spiffworkflow:isMatchingCorrelation', + element, + moddle, + commandStack, + component: MatchingCorrelationCheckboxEntry, + name: 'enable.correlation', + label: translate('Enable Condition Matching'), + description: 'Determine when this message should be received based on matching data values.', + }); + } + + // Given the user the possibility to either enable/disable showing correlations. + // entries.push({ + // id: 'isCorrelated', + // element, + // moddle, + // commandStack, + // component: CorrelationCheckboxEntry, + // name: 'enable.correlation', + // label: translate('Enable Correlation'), + // description: 'You can define specific correlation properties for your message.', + // }); + + var results = [ + { + id: 'messages', + label: translate('Message'), + isDefault: true, + entries, + } + ] + + // Showing Correlation Properties Group if correlation is enabled + // if (businessObject.get('isCorrelated')) { + // results.push({ + // id: 'correlationProperties', + // label: translate('Correlation Properties'), + // isDefault: true, + // component: ListGroup, + // ...CorrelationPropertiesList({ + // element, + // moddle, + // commandStack, + // elementRegistry, + // translate, + // }), + // }) + // } + + // Adding JsonSchema Group + // results.push({ + // id: 'messageSchema', + // label: translate('Json-Schema'), + // entries: [ + // { + // component: MessageJsonSchemaSelect, + // element, + // name: 'msgJsonSchema', + // label: translate('Define JSON Schema'), + // description: translate('Select a JSON schema for your message'), + // moddle, + // commandStack + // }, + // { + // component: LaunchJsonSchemaEditorButton, + // element, + // name: 'messageRef', + // label: translate('Launch Editor') + // } + // ] + // }) + + // Adding Correlation Conditions Section + const isMatchingCorrelation = businessObject.get('spiffworkflow:isMatchingCorrelation'); + if (isMatchingCorrelation && isMatchingCorrelation !== "false" && canReceiveMessage(element)) { + results.push({ + id: "correlationConditions", + label: translate('Matching Conditions'), + ...MatchingCorrelationEntries({ + element, + moddle, + commandStack, + translate, + }) + }) + } + + return results; +} + +function LaunchJsonSchemaEditorButton(props) { + const { element } = props; + const eventBus = useService('eventBus'); + return HeaderButton({ + id: 'spiffworkflow-search-call-activity-button', + class: 'spiffworkflow-properties-panel-button', + children: 'Launch Editor', + onClick: () => { + const { businessObject } = element; + + const msgRef = getMessageRefElement(element); + if (!msgRef) { + alert('Please select a message'); + return ''; + } + + let definitions = getRoot(businessObject); + if (!definitions.get('rootElements')) { + definitions.set('rootElements', []); + } + + // Retrieve Message + let bpmnMessage = definitions.get('rootElements').find(element => + element.$type === 'bpmn:Message' && (element.id === msgRef.id || element.name === msgRef.id) + ); + + if (!bpmnMessage) { + alert('Error : Message not found!'); + return ''; + } + + eventBus.fire('spiff.msg_json_schema_editor.requested', { + messageId: msgRef.name, + schemaId: bpmnMessage.get('jsonSchemaId'), + eventBus, + element + }); + } + }); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CollaborationPropertiesProvider.js b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CollaborationPropertiesProvider.js new file mode 100755 index 0000000..c39c09a --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CollaborationPropertiesProvider.js @@ -0,0 +1,69 @@ +import { MessageArray } from './MessageArray'; +import { CorrelationKeysArray } from './CorrelationKeysArray'; +import { CorrelationPropertiesArray } from './CorrelationPropertiesArray'; +import { ListGroup } from '@bpmn-io/properties-panel'; + +/** + * Adds a group to the properties panel for the script task that allows you + * to set the script. + * @param element + * @param translate + * @returns The components to add to the properties panel. */ +export function createCollaborationGroup( + element, + translate, + moddle, + commandStack, + elementRegistry +) { + + const results = [ + { + id: 'messages', + label: translate('Messages'), + isDefault: true, + component: ListGroup, + ...MessageArray({ + element, + moddle, + commandStack, + elementRegistry, + translate, + }), + }, + { + id: 'correlation_properties', + class: 'correlation_properties', + className: 'correlation_properties', + label: translate('Correlation Properties'), + isDefault: true, + component: ListGroup, + ...CorrelationPropertiesArray({ + element, + moddle, + commandStack, + elementRegistry, + translate, + }), + } + ]; + + // Hide Correlation Keys + // if (element.type === 'bpmn:Collaboration') { + // results.push({ + // id: 'correlation_keys', + // label: translate('Correlation Keys'), + // isDefault: true, + // component: ListGroup, + // ...CorrelationKeysArray({ + // element, + // moddle, + // commandStack, + // elementRegistry, + // translate, + // }), + // }) + // } + + return results; +} \ No newline at end of file diff --git a/app/spiffworkflow/messages/propertiesPanel/CorrelationKeysArray.js b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CorrelationKeysArray.js old mode 100644 new mode 100755 similarity index 78% rename from app/spiffworkflow/messages/propertiesPanel/CorrelationKeysArray.js rename to app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CorrelationKeysArray.js index 5852906..b6a99b2 --- a/app/spiffworkflow/messages/propertiesPanel/CorrelationKeysArray.js +++ b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CorrelationKeysArray.js @@ -1,7 +1,7 @@ import { useService } from 'bpmn-js-properties-panel'; import { SimpleEntry, TextFieldEntry } from '@bpmn-io/properties-panel'; -import { findCorrelationKeys, getRoot } from '../MessageHelpers'; -import { removeFirstInstanceOfItemFromArrayInPlace } from '../../helpers'; +import { createNewCorrelationKey, findCorrelationKeys, getRoot } from '../../MessageHelpers'; +import { removeFirstInstanceOfItemFromArrayInPlace } from '../../../helpers'; /** * Provides a list of data objects, and allows you to add / remove data objects, and change their ids. @@ -12,6 +12,7 @@ export function CorrelationKeysArray(props) { const { element, moddle, commandStack } = props; const correlationKeyElements = findCorrelationKeys(element.businessObject); + const items = correlationKeyElements.map((correlationKeyElement, index) => { const id = `correlationGroup-${index}`; return { @@ -35,18 +36,7 @@ export function CorrelationKeysArray(props) { function add(event) { event.stopPropagation(); - if (element.type === 'bpmn:Collaboration') { - const newCorrelationKeyElement = moddle.create('bpmn:CorrelationKey'); - newCorrelationKeyElement.name = - moddle.ids.nextPrefixed('CorrelationKey_'); - const currentCorrelationKeyElements = - element.businessObject.get('correlationKeys'); - currentCorrelationKeyElements.push(newCorrelationKeyElement); - commandStack.execute('element.updateProperties', { - element, - properties: {} - }); - } + createNewCorrelationKey(element, moddle, commandStack); } return { items, add }; @@ -70,11 +60,6 @@ function removeFactory(props) { }; } -// <--- The correlationGroup -// lover_name -// lover_instrument -// -// function correlationGroup(props) { const { idPrefix, correlationKeyElement, commandStack } = props; const entries = [ diff --git a/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CorrelationPropertiesArray.js b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CorrelationPropertiesArray.js new file mode 100755 index 0000000..92ba977 --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/CorrelationPropertiesArray.js @@ -0,0 +1,150 @@ +import { useService } from 'bpmn-js-properties-panel'; +import { + isTextFieldEntryEdited, + TextFieldEntry, +} from '@bpmn-io/properties-panel'; +import { + getRoot, + findCorrelationProperties, + findCorrelationKeyForCorrelationProperty, + createNewCorrelationProperty, +} from '../../MessageHelpers'; +import { removeFirstInstanceOfItemFromArrayInPlace } from '../../../helpers'; + +/** + * Allows the creation, or editing of messageCorrelations at the bpmn:sendTask level of a BPMN document. + */ +export function CorrelationPropertiesArray(props) { + const { moddle } = props; + const { element } = props; + const { commandStack } = props; + const { translate } = props; + + const correlationPropertyArray = findCorrelationProperties( + element.businessObject + ); + + const items = correlationPropertyArray.map( + (correlationPropertyModdleElement, index) => { + const id = `correlation-${index}`; + const entries = MessageCorrelationPropertyGroup({ + idPrefix: id, + correlationPropertyModdleElement, + translate, + element, + commandStack, + moddle, + }); + return { + id, + label: correlationPropertyModdleElement.name, + entries, + autoFocusEntry: id, + remove: removeFactory({ + element, + correlationPropertyModdleElement, + commandStack, + moddle, + }), + }; + } + ); + + function add(event) { + event.stopPropagation(); + createNewCorrelationProperty(element, moddle, commandStack); + } + + return { items, add }; +} + +function removeFactory(props) { + const { element, correlationPropertyModdleElement, moddle, commandStack } = + props; + + return function (event) { + event.stopPropagation(); + const rootElement = getRoot(element.businessObject); + const { rootElements } = rootElement; + + const oldCorrelationKeyElement = findCorrelationKeyForCorrelationProperty( + correlationPropertyModdleElement, + moddle + ); + if (oldCorrelationKeyElement) { + removeFirstInstanceOfItemFromArrayInPlace( + oldCorrelationKeyElement.correlationPropertyRef, + correlationPropertyModdleElement + ); + } + + removeFirstInstanceOfItemFromArrayInPlace( + rootElements, + correlationPropertyModdleElement + ); + commandStack.execute('element.updateProperties', { + element, + properties: { + messages: rootElements, + }, + }); + }; +} + +function MessageCorrelationPropertyGroup(props) { + const { + idPrefix, + correlationPropertyModdleElement, + translate, + element, + commandStack, + moddle, + } = props; + return [ + { + id: `${idPrefix}-correlation-property-name`, + component: CorrelationPropertyNameTextField, + isEdited: isTextFieldEntryEdited, + idPrefix, + element, + correlationPropertyModdleElement, + translate, + commandStack, + }, + ]; +} + +function CorrelationPropertyNameTextField(props) { + const { + id, + element, + correlationPropertyModdleElement, + commandStack, + translate, + } = props; + + const debounce = useService('debounceInput'); + const setValue = (value) => { + commandStack.execute('element.updateModdleProperties', { + element, + moddleElement: correlationPropertyModdleElement, + properties: { + name: value, + id: value, + }, + }); + }; + + const getValue = () => { + return correlationPropertyModdleElement.name; + }; + + return TextFieldEntry({ + element, + id: `${id}-name-textField`, + label: translate('Name'), + getValue, + setValue, + debounce, + }); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/MessageArray.js b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/MessageArray.js old mode 100644 new mode 100755 similarity index 81% rename from app/spiffworkflow/messages/propertiesPanel/MessageArray.js rename to app/spiffworkflow/messages/propertiesPanel/processLevelProvider/MessageArray.js index 3e1a87c..4aadbd6 --- a/app/spiffworkflow/messages/propertiesPanel/MessageArray.js +++ b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/MessageArray.js @@ -1,7 +1,8 @@ import { useService } from 'bpmn-js-properties-panel'; import { TextFieldEntry } from '@bpmn-io/properties-panel'; -import { getRoot, findMessageModdleElements } from '../MessageHelpers'; -import { removeFirstInstanceOfItemFromArrayInPlace } from '../../helpers'; +import { getRoot, findMessageModdleElements, createNewMessage } from '../../MessageHelpers'; +import { removeFirstInstanceOfItemFromArrayInPlace } from '../../../helpers'; +import { MessagePropertiesMultiSelect } from './MessagePropertiesMultiSelect'; /** * Provides a list of data objects, and allows you to add / remove data objects, and change their ids. @@ -10,8 +11,8 @@ import { removeFirstInstanceOfItemFromArrayInPlace } from '../../helpers'; */ export function MessageArray(props) { const { element, moddle, commandStack, translate } = props; - const messageElements = findMessageModdleElements(element.businessObject); + const items = messageElements.map((messageElement, index) => { const id = `messageElement-${index}`; return { @@ -22,6 +23,7 @@ export function MessageArray(props) { element, messageElement, commandStack, + moddle, translate, }), autoFocusEntry: id, @@ -36,19 +38,7 @@ export function MessageArray(props) { function add(event) { event.stopPropagation(); - if (element.type === 'bpmn:Collaboration') { - const newMessageElement = moddle.create('bpmn:Message'); - const messageId = moddle.ids.nextPrefixed('Message_'); - newMessageElement.id = messageId; - newMessageElement.name = messageId; - const rootElement = getRoot(element.businessObject); - const { rootElements } = rootElement; - rootElements.push(newMessageElement); - commandStack.execute('element.updateProperties', { - element, - properties: {}, - }); - } + createNewMessage(element, moddle, commandStack); } return { items, add }; @@ -94,7 +84,7 @@ function removeFactory(props) { } function messageGroup(props) { - const { messageElement, commandStack, translate, idPrefix } = props; + const { messageElement, commandStack, moddle, translate, idPrefix } = props; return [ { id: `${idPrefix}-name`, @@ -103,6 +93,14 @@ function messageGroup(props) { commandStack, translate, }, + { + id: `${idPrefix}-properties`, + component: MessagePropertiesSelectField, + messageElement, + commandStack, + moddle, + translate, + } ]; } @@ -161,3 +159,18 @@ function MessageNameTextField(props) { debounce, }); } + +function MessagePropertiesSelectField(props) { + const { id, element, moddle, translate, messageElement } = props; + + const debounce = useService('debounceInput'); + + return MessagePropertiesMultiSelect({ + element, + id: `${id}-properties-input`, + label: translate('Properties'), + debounce, + messageElement, + moddle + }); +} diff --git a/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/MessagePropertiesMultiSelect.js b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/MessagePropertiesMultiSelect.js new file mode 100755 index 0000000..67deb41 --- /dev/null +++ b/app/spiffworkflow/messages/propertiesPanel/processLevelProvider/MessagePropertiesMultiSelect.js @@ -0,0 +1,87 @@ +import { html } from 'htm/preact'; +import { useService } from 'bpmn-js-properties-panel'; +import { getCorrelationPropertiesIDsFiltredByMessageRef, setMessageRefToListofCorrelationProperties } from '../../MessageHelpers'; + +import NiceSelect from 'nice-select2/dist/js/nice-select2'; + +let niceSelectInputs = {}; + +export function MessagePropertiesMultiSelect(props) { + + const { element, id, moddle, messageElement, commandStack } = props; + + const modeling = useService('modeling'); + const translate = useService('translate'); + const debounce = useService('debounceInput'); + + const setValue = (value) => { + // Add message ref to the selected correlation properties + setMessageRefToListofCorrelationProperties(messageElement, value, element, moddle, commandStack) + }; + + const getOptions = () => { + const correlationProperties = getCorrelationPropertiesIDsFiltredByMessageRef(element.businessObject, moddle, messageElement); + return correlationProperties; + }; + + function handleSelectChange(e) { + const selectedOptions = Array.from(e.target.selectedOptions).map(option => option.value); + setValue(selectedOptions); + } + + const initializeNiceSelect = () => { + const selectElement = document.getElementById(`${id}_select`); + if (!selectElement) return; + + if (niceSelectInputs[id] && niceSelectInputs[id] !== null ) { + niceSelectInputs[id].destroy(); + } + + const opts = { + // data: options, + searchable: true, + placeholder: 'Select message properties', + showSelectedItems: true + }; + + niceSelectInputs[id] = new NiceSelect(selectElement, opts); + updateSelectOptions(selectElement) + + + }; + + function updateSelectOptions(selectElement) { + for (let option of selectElement.options) { + const matchingOption = options.find(opt => opt.value === option.value); + if (matchingOption && matchingOption.selected) { + option.setAttribute('selected', 'true'); + } + } + } + + const renderSelect = (options) => { + return html` + + `; + } + + const options = getOptions(); + + setTimeout(() => { + initializeNiceSelect(); + }, 0); + + return html` +
+ + ${renderSelect(options)} +
+ `; + +} diff --git a/app/spiffworkflow/moddle/spiffworkflow.json b/app/spiffworkflow/moddle/spiffworkflow.json index a55d625..2cdb69b 100644 --- a/app/spiffworkflow/moddle/spiffworkflow.json +++ b/app/spiffworkflow/moddle/spiffworkflow.json @@ -49,6 +49,26 @@ } ] }, + { + "name": "ProcessVariableCorrelation", + "superClass": [ "Element" ], + "properties": [ + { + "name": "propertyId", + "type": "String", + "xml": { + "serialize": "property" + } + }, + { + "name": "expression", + "type": "String", + "xml": { + "serialize": "property" + } + } + ] + }, { "name": "CalledDecisionId", "superClass": [ "Element" ], diff --git a/package-lock.json b/package-lock.json index c0048d5..3d842bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "min-dash": "^3.8.1", "min-dom": "^3.2.1", "moddle": "^5.0.3", + "nice-select2": "^2.1.0", "react": "^18.2.0", "react-dom": "18.2.0", "tiny-svg": "^2.2.3" @@ -2285,7 +2286,7 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -2299,7 +2300,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.0.0" } @@ -2308,7 +2309,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.0.0" } @@ -2317,7 +2318,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -2327,13 +2328,13 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "devOptional": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.19", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -2634,7 +2635,7 @@ "version": "8.44.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -2644,7 +2645,7 @@ "version": "3.7.4", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, + "devOptional": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -2654,7 +2655,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", - "dev": true + "devOptional": true }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", @@ -2684,7 +2685,7 @@ "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true + "devOptional": true }, "node_modules/@types/json5": { "version": "0.0.29", @@ -2702,7 +2703,7 @@ "version": "20.5.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==", - "dev": true + "devOptional": true }, "node_modules/@types/yargs": { "version": "15.0.15", @@ -2723,7 +2724,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "dev": true, + "devOptional": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -2733,25 +2734,25 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "devOptional": true }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "devOptional": true }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true + "devOptional": true }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, + "devOptional": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -2762,13 +2763,13 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "devOptional": true }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "dev": true, + "devOptional": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -2780,7 +2781,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, + "devOptional": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -2789,7 +2790,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, + "devOptional": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -2798,13 +2799,13 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "devOptional": true }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "dev": true, + "devOptional": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -2820,7 +2821,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dev": true, + "devOptional": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -2833,7 +2834,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dev": true, + "devOptional": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -2845,7 +2846,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "dev": true, + "devOptional": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -2859,7 +2860,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "dev": true, + "devOptional": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" @@ -2905,13 +2906,13 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "devOptional": true }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "devOptional": true }, "node_modules/accepts": { "version": "1.3.8", @@ -2930,7 +2931,7 @@ "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -2942,7 +2943,7 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, + "devOptional": true, "peerDependencies": { "acorn": "^8" } @@ -2960,7 +2961,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "devOptional": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3015,7 +3016,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, + "devOptional": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -3329,8 +3330,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64id": { "version": "2.0.0", @@ -3526,7 +3526,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3564,7 +3563,7 @@ "version": "4.21.10", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", - "dev": true, + "devOptional": true, "funding": [ { "type": "opencollective", @@ -3596,7 +3595,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "devOptional": true }, "node_modules/bytes": { "version": "3.1.2", @@ -3682,7 +3681,7 @@ "version": "1.0.30001525", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001525.tgz", "integrity": "sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q==", - "dev": true, + "devOptional": true, "funding": [ { "type": "opencollective", @@ -3782,7 +3781,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.0" } @@ -3895,8 +3894,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/confusing-browser-globals": { "version": "1.0.11", @@ -4120,11 +4118,27 @@ "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "peer": true }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4134,6 +4148,81 @@ "node": ">= 8" } }, + "node_modules/css-loader": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", + "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.4", + "postcss-modules-scope": "^3.1.1", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-loader/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/custom-event": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", @@ -4413,7 +4502,7 @@ "version": "1.4.508", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.508.tgz", "integrity": "sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg==", - "dev": true + "devOptional": true }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -4473,7 +4562,7 @@ "version": "5.15.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, + "devOptional": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -4588,7 +4677,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==", - "dev": true + "devOptional": true }, "node_modules/es-set-tostringtag": { "version": "2.0.1", @@ -4634,7 +4723,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -5234,7 +5323,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, + "devOptional": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -5246,7 +5335,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=4.0" } @@ -5270,7 +5359,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.8.x" } @@ -5310,7 +5399,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "devOptional": true }, "node_modules/fast-diff": { "version": "1.3.0", @@ -5350,7 +5439,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "devOptional": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -5652,14 +5741,26 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/function.prototype.name": { "version": "1.1.6", @@ -5759,7 +5860,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5791,7 +5891,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "devOptional": true }, "node_modules/globals": { "version": "11.12.0", @@ -5852,7 +5952,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "devOptional": true }, "node_modules/graceful-readlink": { "version": "1.0.1", @@ -5879,7 +5979,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -6065,6 +6164,17 @@ "node": ">=0.10.0" } }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/ids": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/ids/-/ids-1.0.5.tgz", @@ -6133,7 +6243,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -6263,7 +6372,6 @@ "version": "2.13.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -6567,8 +6675,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/isobject": { "version": "3.0.1", @@ -6730,7 +6837,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -6744,7 +6851,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } @@ -6753,7 +6860,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, + "devOptional": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6809,13 +6916,13 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "devOptional": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "devOptional": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -7082,7 +7189,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.11.5" } @@ -7346,7 +7453,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "devOptional": true }, "node_modules/merge2": { "version": "1.4.1", @@ -7386,7 +7493,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 0.6" } @@ -7395,7 +7502,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, + "devOptional": true, "dependencies": { "mime-db": "1.52.0" }, @@ -7424,7 +7531,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -7436,7 +7542,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7713,7 +7818,17 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "devOptional": true + }, + "node_modules/nice-select2": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nice-select2/-/nice-select2-2.1.0.tgz", + "integrity": "sha512-tcxPbB/OLvS3c5DEWf9KguTFRAt1LmSwR6HCTM438LJzviLArHHKQgnYNhDoPyYxQ0W6CXMTD4ZTHTm2VeVung==", + "dependencies": { + "cross-env": "^7.0.3", + "css-loader": "^6.7.3", + "shx": "^0.3.4" + } }, "node_modules/nice-try": { "version": "1.0.5", @@ -7765,7 +7880,7 @@ "version": "2.0.13", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true + "devOptional": true }, "node_modules/normalize-package-data": { "version": "2.5.0", @@ -8029,7 +8144,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -8152,7 +8266,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -8161,7 +8274,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -8169,8 +8281,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { "version": "1.8.0", @@ -8208,8 +8319,7 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -8308,6 +8418,122 @@ "node": ">=8" } }, + "node_modules/postcss": { + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz", + "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz", + "integrity": "sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/preact": { "version": "10.17.1", "resolved": "https://registry.npmjs.org/preact/-/preact-10.17.1.tgz", @@ -8432,7 +8658,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -8491,7 +8717,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, + "devOptional": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -8782,7 +9008,6 @@ "version": "1.22.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", - "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -8913,7 +9138,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -9009,7 +9234,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, + "devOptional": true, "dependencies": { "randombytes": "^2.1.0" } @@ -9036,7 +9261,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -9048,7 +9272,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -9062,6 +9285,56 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/shelljs/node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/shelljs/node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/shx": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", + "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==", + "dependencies": { + "minimist": "^1.2.3", + "shelljs": "^0.8.5" + }, + "bin": { + "shx": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -9217,7 +9490,15 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "engines": { "node": ">=0.10.0" } @@ -9226,7 +9507,7 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, + "devOptional": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -9456,7 +9737,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -9474,7 +9754,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -9483,7 +9763,7 @@ "version": "5.19.3", "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.3.tgz", "integrity": "sha512-pQzJ9UJzM0IgmT4FAtYI6+VqFf0lj/to58AV0Xfgg0Up37RyPG7Al+1cepC6/BVuAxR9oNb41/DL4DEoHJvTdg==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -9501,7 +9781,7 @@ "version": "5.3.9", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", @@ -9535,7 +9815,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -9553,7 +9833,7 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "devOptional": true }, "node_modules/text-table": { "version": "0.2.0", @@ -9894,7 +10174,7 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "dev": true, + "devOptional": true, "funding": [ { "type": "opencollective", @@ -9930,11 +10210,16 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, + "devOptional": true, "dependencies": { "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -9991,7 +10276,7 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, + "devOptional": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -10004,7 +10289,7 @@ "version": "5.88.2", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", - "dev": true, + "devOptional": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -10129,7 +10414,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, + "devOptional": true, "engines": { "node": ">=10.13.0" } @@ -10138,7 +10423,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, + "devOptional": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -10151,7 +10436,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=4.0" } @@ -10160,7 +10445,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, + "devOptional": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -10178,7 +10463,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -10330,8 +10614,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { "version": "8.11.0", diff --git a/package.json b/package.json index 9d68a48..470ae5c 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "min-dash": "^3.8.1", "min-dom": "^3.2.1", "moddle": "^5.0.3", + "nice-select2": "^2.1.0", "react": "^18.2.0", "react-dom": "18.2.0", "tiny-svg": "^2.2.3" diff --git a/test/spec/MessagesSpec.js b/test/spec/MessagesSpec.js index 8b0d240..3d81640 100644 --- a/test/spec/MessagesSpec.js +++ b/test/spec/MessagesSpec.js @@ -1,4 +1,7 @@ import TestContainer from 'mocha-test-container-support'; +import { + query as domQuery, +} from 'min-dom'; import { BpmnPropertiesPanelModule, BpmnPropertiesProviderModule, @@ -8,15 +11,20 @@ import { expectSelected, findEntry, findGroupEntry, - // findInput, findSelect, findTextarea, - // findButtonByClass, - // pressButton, - // findDivByClass, + findInput, + pressButton, + findButtonByClass, + getPropertiesPanel, + changeInput, + findDivByClass } from './helpers'; import spiffModdleExtension from '../../app/spiffworkflow/moddle/spiffworkflow.json'; import messages from '../../app/spiffworkflow/messages'; +import { fireEvent } from '@testing-library/preact'; +import { getBpmnJS, inject } from 'bpmn-js/test/helper'; +import { findCorrelationProperties, findMessageModdleElements } from '../../app/spiffworkflow/messages/MessageHelpers'; describe('Messages should work', function () { const xml = require('./bpmn/collaboration.bpmn').default; @@ -41,12 +49,23 @@ describe('Messages should work', function () { }) ); - it('should allow you to see the collaborations section', async function () { - // THEN - a select Data Object section should appear in the properties panel - const entry = findGroupEntry('correlation_keys', container); - expect(entry).to.exist; - await expectSelected('my_collaboration'); - }); + const new_message_event = (eventBus) => { + eventBus.fire('spiff.add_message.returned', { + name: 'msgName', + correlation_properties: { + "c1": { + "retrieval_expressions": [ + "c1x" + ] + }, + "c2": { + "retrieval_expressions": [ + "cxxxx1x" + ] + } + } + }); + }; it('should show a Message Properties group when a send task is selected', async function () { // Select the send Task @@ -80,7 +99,7 @@ describe('Messages should work', function () { // Select the second Task const sendShape = await expectSelected('ActivitySendLetter'); expect(sendShape, "Can't find Send Task").to.exist; - + // THEN - there is a payload. const payload = findEntry('messagePayload', container); expect(payload, "Can't find the message payload").to.exist; @@ -95,42 +114,152 @@ describe('Messages should work', function () { await expectSelected('my_collaboration'); }); - it('should show the correlations inside the message group', async function () { - // Select the second Task + it('should be able to create new message from sendMessageTask if no message is found', inject(async function (canvas, modeling) { + + let rootShape = canvas.getRootElement(); + + // Retrieve the current number of existing messages + const messageElemendBeforeDelete = findMessageModdleElements(rootShape.businessObject); + expect(messageElemendBeforeDelete.length).to.equal(2); + + // Select message element const sendShape = await expectSelected('ActivitySendLetter'); expect(sendShape, "Can't find Send Task").to.exist; - // THEN - there are correlations. - const correlations = findGroupEntry('correlationProperties', container); - expect(correlations, "Can't find the message correlations").to.exist; - await expectSelected('my_collaboration'); + const entry = findEntry('selectMessage', getPropertiesPanel()); + expect(entry).to.exist; + + let selector = findSelect(entry); + expect(selector.options.length).to.equal(2); + + changeInput(selector, 'love_letter_response'); + const messageElemend = findMessageModdleElements(rootShape.businessObject); + expect(messageElemend.length).to.equal(2); + + })); + + it('should be able to add new message and correlation properties on add_message_event', async function () { + + const modeler = getBpmnJS(); + + // Select message element + const sendShape = await expectSelected('ActivitySendLetter'); + expect(sendShape, "Can't find Send Task").to.exist; + + const entry = findEntry('selectMessage', getPropertiesPanel()); + expect(entry).to.exist; + + // Expect to find two existing messages + let selector = findSelect(entry); + expect(selector.options.length).to.equal(2); + + // Fire add new message event + modeler.get('eventBus').on('spiff.add_message.requested', (event) => { + new_message_event(modeler.get('eventBus')) + }); + modeler.get('eventBus').fire('spiff.add_message.requested'); + + const sendShapecc = await expectSelected('ActivitySendLetter'); + expect(sendShapecc, "Can't find Send Task").to.exist; + + const updatedEntry = findEntry('selectMessage', getPropertiesPanel()); + expect(updatedEntry).to.exist; + + const updatedSelector = findSelect(updatedEntry); + expect(updatedSelector.options.length).to.equal(3); + expect(updatedSelector.options[2].value).to.equal('msgName'); + }); - // it('should add a new correlation when clicked', async function () { + it('should be able to generate default Correlation keys on changing message', async function () { + + }) + + + // 🔶🔶 OLD Features + + // // it('should show the correlations inside the message group', async function () { + // // // Select the second Task + // // const sendShape = await expectSelected('ActivitySendLetter'); + // // expect(sendShape, "Can't find Send Task").to.exist; + + // // // Enable correlation + // // const checkbox = findInput('checkbox', container); + // // pressButton(checkbox); + + // // // THEN - there are correlations. + // // const correlations = findGroupEntry('correlationProperties', container); + // // expect(correlations, "Can't find the message correlations").to.exist; + // // await expectSelected('my_collaboration'); + // // }); + + // it('should not showing the correlations inside the message group if is not enabled', async function () { // // Select the second Task // const sendShape = await expectSelected('ActivitySendLetter'); // expect(sendShape, "Can't find Send Task").to.exist; - // - // const buttonClass = - // 'bio-properties-panel-group-header-button bio-properties-panel-add-entry'; - // const button = findButtonByClass(buttonClass, container); - // pressButton(button); - // + + // // Check correlation properties + // const correlations = findGroupEntry('correlationProperties', container); + // expect(correlations, "Can't find the message correlations").not.to.exist; // }); - // + + // // Old Feature + // // it('should add a new correlation when clicked', async function () { + // // // Select the second Task + // // const sendShape = await expectSelected('ActivitySendLetter'); + // // expect(sendShape, "Can't find Send Task").to.exist; + + // // // Enable correlation + // // const checkbox = findInput('checkbox', container); + // // pressButton(checkbox); + + // // const buttonClass = + // // 'bio-properties-panel-group-header-button bio-properties-panel-add-entry'; + // // const button = findButtonByClass(buttonClass, container); + // // pressButton(button); + + // // }); + // it('should add a new Correlation Key when clicked', async function () { - // const divClass = 'bio-properties-panel-list'; - // const divs = findDivByClass(divClass, container); - // // const buttonClass = // 'bio-properties-panel-group-header-button bio-properties-panel-add-entry'; // const button = findButtonByClass(buttonClass, container); // pressButton(button); - // // // THEN - a select Data Object section should appear in the properties panel // const entry = findGroupEntry('correlation_keys', container); // expect(entry).to.exist; - // - // const divs2 = findDivByClass(divClass, container); // }); + + // it('should be able to delete an existing message', inject(function (canvas, modeling) { + // let rootShape = canvas.getRootElement(); + // // Retrieve current number of existing messages + // const messageElemendBeforeDelete = findMessageModdleElements(rootShape.businessObject); + // expect(messageElemendBeforeDelete.length).to.equal(2); + // // Trigger delete action + // let deleteButton = domQuery('.bio-properties-panel-remove-entry', container); + // fireEvent.click(deleteButton); + // const messageElemendAfterDelete = findMessageModdleElements(rootShape.businessObject); + // expect(messageElemendAfterDelete.length).to.equal(1); + // })); + + // it('should be able to delete an existing correlation property', inject(function (canvas, modeling) { + // let rootShape = canvas.getRootElement(); + // // Retrieve current number of existing messages + // const correlationPropertiesBeforeDelete = findCorrelationProperties(rootShape.businessObject); + // expect(correlationPropertiesBeforeDelete.length).to.equal(3); + // // Trigger delete action + // const correlationPropertiesDiv = domQuery(`div[data-group-id='group-correlation_properties']`, container); + // let deleteButton = domQuery('.bio-properties-panel-remove-entry', correlationPropertiesDiv); + // fireEvent.click(deleteButton); + // const correlationPropertiesAfterDelete = findCorrelationProperties(rootShape.businessObject); + // expect(correlationPropertiesAfterDelete.length).to.equal(2); + // })); + + // it('should allow you to see the collaborations section', async function () { + // // THEN - a select Data Object section should appear in the properties panel + // const entry = findGroupEntry('correlation_keys', container); + // expect(entry).to.exist; + // await expectSelected('my_collaboration'); + // }); + }); diff --git a/test/spec/bpmn/collaboration.bpmn b/test/spec/bpmn/collaboration.bpmn index a193fd3..8d24b60 100644 --- a/test/spec/bpmn/collaboration.bpmn +++ b/test/spec/bpmn/collaboration.bpmn @@ -1,10 +1,18 @@ - + - + @@ -14,15 +22,7 @@
- - - - { - 'to': { 'name': my_lover_variable } - } - - - + @@ -55,6 +55,13 @@ Flow_1bl6jeh Flow_0tp8uut + + + { + 'to': { 'name': my_lover_variable } + } + + Flow_0tp8uut @@ -75,7 +82,8 @@ - + @@ -165,7 +173,8 @@ - + @@ -192,4 +201,4 @@ - + \ No newline at end of file