diff --git a/src/components/inspectors/DataInputAssociation.vue b/src/components/inspectors/DataInputAssociation.vue new file mode 100644 index 000000000..1c195bcb4 --- /dev/null +++ b/src/components/inspectors/DataInputAssociation.vue @@ -0,0 +1,320 @@ + + + + + + {{ $t('Data Inputs') }} + {{ dataInputs.length }} + + + {{ $t('Add Data Input') }} + + + + + {{ $t('No data inputs configured') }} + + + + + + + + + {{ $t('Assignment Expression') }} + + + + + + + + + + + {{ $t('Use FEEL expressions to map data to this input') }} + + + + + + + + + + {{ $t('Are you sure you want to delete this data input?') }} + + {{ deleteDataInput.id }} - {{ deleteDataInput.name }} + + + + + + + + + + + {{ dataInput.name || $t('Data Input') }} + {{ dataInput.id }} + + + + + + + + + + + + + {{ $t('Assignment Expression') }}: + + {{ dataInput.assignmentExpression }} + + + + + + + + + + \ No newline at end of file diff --git a/src/components/inspectors/ElementDestination.vue b/src/components/inspectors/ElementDestination.vue index 7ad7d7821..804af1a2e 100644 --- a/src/components/inspectors/ElementDestination.vue +++ b/src/components/inspectors/ElementDestination.vue @@ -3,7 +3,7 @@ [], }, value: { type: String, @@ -144,12 +145,12 @@ export default { node() { return this.$root.$children[0].$refs.modeler.highlightedNode.definition; }, - helper() { + helperText() { if (this.node.$type === 'bpmn:EndEvent') { return this.$t('The user will go here after completing the process.'); } - return this.$t('Select where to send users after this task. Any Non-default destination will disable the “Display Next Assigned Task” function.'); + return this.$t('Select where to send users after this task. Any Non-default destination will disable the "Display Next Assigned Task" function.'); }, }, created() { @@ -180,14 +181,14 @@ export default { } }, loadData() { - this.optionsCopy = this.options.map(option => ({ + this.optionsCopy = (this.options || []).map(option => ({ value: option.value, content: this.$t(option.content), })); this.elementDestination = this.optionsCopy?.[0] ?? null; - - if (this.value) { + // validate the value is a valid JSON + if (this.value && this.isValidJSON(this.value)) { this.local = JSON.parse(this.value); this.elementDestination = this.getElementDestination(); this.destinationType = this.getDestinationType(); @@ -202,6 +203,14 @@ export default { } } }, + isValidJSON(string) { + try { + JSON.parse(string); + return true; + } catch (_) { + return false; + } + }, getElementDestination() { if (!this.local?.type) return null; return this.optionsCopy.find(element => element.value === this.local.type); diff --git a/src/components/inspectors/InspectorPanel.vue b/src/components/inspectors/InspectorPanel.vue index f8ba71db6..eaca40d5a 100644 --- a/src/components/inspectors/InspectorPanel.vue +++ b/src/components/inspectors/InspectorPanel.vue @@ -78,6 +78,10 @@ Vue.component('FormAccordion', FormAccordion); Vue.component('FormDatePicker', FormDatePicker); Vue.component('FormMultiSelect', FormMultiSelect); +// Register custom inspector components +import MessageThrowEventDataInputs from './MessageThrowEventDataInputs'; +Vue.component('MessageThrowEventDataInputs', MessageThrowEventDataInputs); + export default { components: { }, props: ['nodeRegistry', 'moddle', 'processNode', 'parentHeight', 'canvasDragPosition', 'definitions'], diff --git a/src/components/inspectors/MessageSelect.vue b/src/components/inspectors/MessageSelect.vue index 2c452ae79..f29ebbc81 100644 --- a/src/components/inspectors/MessageSelect.vue +++ b/src/components/inspectors/MessageSelect.vue @@ -6,7 +6,7 @@ :value="selectedOption" @input="change" :placeholder="$t(placeholder)" - :options="options" + :options="messageOptions" :multiple="multiple" :track-by="trackBy" :show-labels="false" @@ -154,7 +154,7 @@ export default { }, data() { return { - options: [], + messageOptions: [], selectedOption: null, pmql: 'id!=' + window.ProcessMaker.modeler.process.id, showListMessages: false, @@ -305,7 +305,7 @@ export default { this.showNewMessage = false; }, updateOptions(globalMessages) { - this.options = uniqBy([...this.localMessages, ...globalMessages], 'id'); + this.messageOptions = uniqBy([...this.localMessages, ...globalMessages], 'id'); }, loadOptions() { this.updateOptions([]); @@ -328,7 +328,7 @@ export default { value: { immediate: true, handler(value) { - this.selectedOption = this.options.find(option => get(option, this.trackBy) == value); + this.selectedOption = this.messageOptions.find(option => get(option, this.trackBy) == value); if (value && !this.selectedOption) { this.loadSelected(value); diff --git a/src/components/inspectors/messageThrowEventDataInputsConfig.js b/src/components/inspectors/messageThrowEventDataInputsConfig.js new file mode 100644 index 000000000..e2c9898dc --- /dev/null +++ b/src/components/inspectors/messageThrowEventDataInputsConfig.js @@ -0,0 +1,20 @@ +export default { + component: 'FormAccordion', + container: true, + config: { + initiallyOpen: true, + label: 'Data Inputs & Assignments', + icon: 'database', + name: 'message-throw-event-data-inputs-accordion', + }, + items: [ + { + component: 'MessageThrowEventDataInputs', + config: { + label: 'Data Inputs', + name: 'dataInputs', + helper: 'Configure data inputs and their assignment expressions for the message payload', + }, + }, + ], +}; diff --git a/src/components/modeler/Modeler.vue b/src/components/modeler/Modeler.vue index 6e912c2d9..8f9d473b0 100644 --- a/src/components/modeler/Modeler.vue +++ b/src/components/modeler/Modeler.vue @@ -1295,8 +1295,7 @@ export default { }); const tasksThatHaveDataInputAssociations = flowElements.filter(task => task.get('dataInputAssociations') && - task.get('dataInputAssociations').length > 0); - + task.get('dataInputAssociations').length > 0 && task.$type !== 'bpmn:IntermediateThrowEvent'); tasksThatHaveDataInputAssociations.forEach(task => { task.get('dataInputAssociations').forEach(dataAssociationLink => { this.setNode(dataAssociationLink, flowElements); @@ -1335,7 +1334,7 @@ export default { this.addLanes(process); - const flowElements = process.get('flowElements'); + let flowElements = process.get('flowElements'); const artifacts = process.get('artifacts'); this.loadFlowElements(flowElements, artifacts); diff --git a/src/components/nodes/messageEndEvent/index.js b/src/components/nodes/messageEndEvent/index.js index 1d04bffc0..991f021ab 100644 --- a/src/components/nodes/messageEndEvent/index.js +++ b/src/components/nodes/messageEndEvent/index.js @@ -3,8 +3,8 @@ import merge from 'lodash/merge'; import cloneDeep from 'lodash/cloneDeep'; import endEventConfig from '@/components/nodes/endEvent'; import defaultNames from '@/components/nodes/endEvent/defaultNames'; -import { default as messageEventDefinition, messageSelector } from '../messageEventDefinition'; - +import { default as messageEventDefinition } from '../messageEventDefinition'; +import MessageSelect from '@/components/inspectors/MessageSelect'; const id = 'processmaker-modeler-message-end-event'; export default merge(cloneDeep(endEventConfig), { @@ -27,7 +27,14 @@ export default merge(cloneDeep(endEventConfig), { { items: [ {}, - messageSelector('Select the message reference that this element throws'), + { + component: MessageSelect, + config: { + label: 'Message', + name: 'messageRef', + helper: 'Select the message reference that this element throws', + }, + }, ], }, ],
{{ dataInput.assignmentExpression }}