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